The built in QtextEdit's textChanged signal does not include the current text (like with QlineEdit). I would like to subclass QTextEdit so that it emits a similar signal that does include the current text.
I found a solution that works, but I find it a bit hackish:
class MyTextEdit(QTextEdit):
plainTextChanged = pyqtSignal(str)
def __init__(self):
super().__init__()
self.textChanged.connect(lambda: self.plainTextChanged.emit(self.toPlainText()))
Are there other (more idiomatic?) ways to do this? Could you override the code that generates the textChanged signal? In my imagination that would look something like this:
class MyTextEdit(QTextEdit):
plainTextChanged = pyqtSignal(str)
def __init__(self):
super().__init__()
def some_override(self):
...
self.plainTextChanged.emit(self.toPlainText())
Your implementation is correct, but it's usually better to use a function instead of a lambda. You can't "override" the default behavior of a signal.
As explained in the comments, Qt doesn't provide by default a signal that emits the text in order to avoid overhead, since the size of the contents is undefined (and could be very large).
Consider that toPlainText()
uses the QTextEdit's QTextDocument toPlainText()
:
This function returns the same as toRawText(), but will replace some unicode characters with ASCII alternatives. In particular, no-break space (U+00A0) is replaced by a regular space (U+0020), and both paragraph (U+2029) and line (U+2028) separators are replaced by line feed (U+000A). If you need the precise contents of the document, use toRawText() instead.
If you're using Qt >= 5.9 and you could have the above characters, you can use the text document toRawText()
:
class MyTextEdit(QTextEdit):
plainTextChanged = pyqtSignal(str)
def __init__(self):
super().__init__()
self.textChanged.connect(self.emitPlainText)
def emitPlainText(self):
self.plainTextChanged.emit(self.document().toRawText())
# otherwise:
self.plainTextChanged.emit(self.toPlainText())