Почему происходит ошибка переполнения стека
Преподаватель задал задание:
Печатаешь в QPlainText какой либо текст, и он должен при обнаружение определенной группы символов, заменять на определенную фразу, например: @#RUB@ заменять на "рубли" и т.д.. Мной было принято решение, отслеживать событие изменения текста в QPlainText, то есть на каждый ввод нового символа, я буду брать весь текст из QPlainTextи прогонять через замену:
void MainWindow::on_plainTextEdit_textChanged()
{
//ui->plainTextEdit->blockSignals(true);
ui->plainTextEdit->setPlainText
(
ui->plainTextEdit->toPlainText()
.replace("#@RUB@", "₽", Qt::CaseInsensitive).replace("#@РУБ@", "₽", Qt::CaseInsensitive)
.replace("#@AUTH@", "©", Qt::CaseInsensitive).replace("#@АВТП@", "©", Qt::CaseInsensitive)
.replace("#@PM@", "‰", Qt::CaseInsensitive).replace("#@ПМ@", "‰", Qt::CaseInsensitive)
.replace("#@GS@", "®", Qt::CaseInsensitive).replace("#@ЗК@", "®", Qt::CaseInsensitive)
.replace("#@EURO@", "€", Qt::CaseInsensitive).replace("#@ЕВРО@", "€", Qt::CaseInsensitive)
);
//ui->plainTextEdit->blockSignals(false);
}
Вопрос, почему крашит с событием переполнения стека? Я делал по методичке и в ней, при изменении текста, в событии textChanged()якобы не крашит, по крайней мере пример брал от туда, вот кусок кода:
void MainWindow::on_plainTextEdit_textChanged()
{
QString str = ui->plainTextEdit->toPlainText(); // получаем текст виджета
if (parseText->change(str)) // были ли примеры
{
ui->plainTextEdit->setPlainText(parseText->getText()); // заменяем текст примеры с результатами
}
}
Отключение сигнала в момент изменения содержимого QPlainText помогает, но тогда возникает проблема с позицией курсора - он постоянно прыгает в начало, при вводе нового символа. Где мои ошибки, пожалуйста объясните. Версия QT 5.15.
Ответы (1 шт):
Вы своими руками загоняете в рекурсию
[signal]void QPlainTextEdit::textChanged() This signal is emitted whenever the document's content changes; for example, when text is inserted or deleted, or when formatting is applied.
Т.е. после замены текста (setPlainText()) сигнал вызовется по новой. Текст опять заменится (хоть и на тот же самый), снова вызовется сигнал. и т.д.
По решению проблемы. Можете попробовать заменять текст ТОЛЬКО если присутствуют ваши паттерны (пример для одного. остальное допишете). В идеале код надо переписать полность на использование курсоров БЕЗ полной замены текста (на больших текстах это будет работать не оптимально)
void MainWindow::on_plainTextEdit_textChanged()
{
int cursorPos = ui->plainTextEdit->textCursor().position(); // при замене текста курсор сдвинется в начало, поэтому запоминайте заранее
bool isEnd = ui->plainTextEdit->textCursor().atEnd(); // то же самое
QTextCursor cur = ui->plainTextEdit->textCursor();
QString s = ui->plainTextEdit->toPlainText();
if(s.indexOf("#@RUB@",Qt::CaseInsensitive)!=-1){
ui->plainTextEdit->setPlainText(s.replace("#@RUB@", "₽", Qt::CaseInsensitive));
qApp->processEvents();
if(isEnd){ // паттерн дописан в конец текста или в середину?
cur.movePosition(QTextCursor::End); // курсор в конец текста
}else{
cur.movePosition(QTextCursor::Start); // перемещаем курсор в начало
cur.movePosition(QTextCursor::Right,QTextCursor::MoveAnchor,cursorPos-5); // перемещаем вправо на cursorPos-5 (длина паттерна-1)
}
ui->plainTextEdit->setTextCursor(cur);
}
}