具有自定义 textChanged 信号的 QTextEdit 子类

QTextEdit subclass with custom textChanged signal

QtextEdit 的内置 textChanged 信号不包括当前文本(与 QlineEdit 一样)。 我想将 QTextEdit 子类化,以便它发出包含当前文本的类似信号。

我找到了一个可行的解决方案,但我觉得它有点老套:

class MyTextEdit(QTextEdit):
    plainTextChanged = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.textChanged.connect(lambda: self.plainTextChanged.emit(self.toPlainText()))

还有其他(更惯用的吗?)方法可以做到这一点? 您能否覆盖生成 textChanged 信号的代码? 在我的想象中,它看起来像这样:

class MyTextEdit(QTextEdit):
    plainTextChanged = pyqtSignal(str)

    def __init__(self):
        super().__init__()

    def some_override(self):
        ...
        self.plainTextChanged.emit(self.toPlainText())

您的实现是正确的,但通常使用函数而不是 lambda 会更好。您不能“覆盖”信号的默认行为。

如评论中所述,Qt 默认情况下不提供发出文本的信号以避免开销,因为内容的大小未定义(并且可能非常大)。

考虑 toPlainText() 使用 QTextEdit 的 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.

如果您使用的 Qt >= 5.9 并且您可以使用上述字符,则可以使用文本文档 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())