void QTextDocument::contentsChange(int position, int charsRemoved, int charsAdded) [signal]
Этот сигнал испускается всякий раз, когда изменяется содержание документа; например, когда текст вставляется или удаляется, или когда применяется форматирование.
Пользователь может щелкнуть вырезать / нажать клавишу удаления / возврата или любым другим способом и удалит текст.
Проблема в том, что этот сигнал испускается после удаления текста. Так что я не знаю, какой текст был удален. Теперь позиция и charsRemoved бесполезны.
Я хочу узнать удаленный текст QPlainTextEdit. Есть ли способ добиться этого?
Я вижу 2 возможных решения:
Сохраняйте содержимое документа после каждого изменения содержимого, поэтому при каждом следующем изменении вы будете иметь доступ к предыдущему содержимому и сможете извлечь значение, используя позиция а также charsRemoved.
Плюсы: Это изолированный механизм и не будет мешать другим сигналам или слотам.
Минусы: Это подразумевает значительную память и загрузку процессора (каждое изменение текста приводит к полному копированию строки).
(лучше на мой взгляд) В реализации функции слота используйте undo()
а также redo()
методы QPlainTextEdit
восстановить предыдущее содержимое на время запроса charsRemoved. Обратите внимание, что зовет undo()
а также redo()
не буду вызвать contentsChange()
сигнал (я только что проверил), так что это так просто.
Плюсы: Не вызывает дополнительной памяти. Не уверен насчет загрузки процессора, но я думаю, что в этом случае тоже лучше.
Минусы: Это будет работать только с Отменить повторить механизм включен (что по умолчанию), и это также может повлиять на любой код отмены / повтора, который вы используете или переопределяете (обычно это не так).
Чтобы быть понятным, пример кода, снятый для решения 2:
void MainWindow::textChanged(int pos, int rem, int add)
{
ui->plainTextEdit->undo();
qDebug() << ui->plainTextEdit->document()->toPlainText().mid(pos, rem); // <- text removed
ui->plainTextEdit->redo();
qDebug() << ui->plainTextEdit->document()->toPlainText().mid(pos, add); // <- text added
}
Трюк с вызовом undo
а также redo
предложенный Googie это хорошо, чтобы сделать его еще более эффективным, можно использовать QTextCursor
извлечь текст вместо вызова toPlainText
:
void TextEdit::slotCheckRange(int pos, int removed, int added){
if(removed > 0){
undo();
QTextCursor c(textCursor());
c.setPosition(pos);
c.setPosition(pos + removed, QTextCursor::KeepAnchor);
qDebug() << "Removed: " << removed << " (" << c.selectedText() << ")";
redo();
}
if(added > 0){
QTextCursor c(textCursor());
c.setPosition(pos);
c.setPosition(pos + added, QTextCursor::KeepAnchor);
qDebug() << "Added: " << added << " (" << c.selectedText() << ")";
}
}