为 keyPressEvent 子类化 QTextEdit 是唯一的方法吗?

Posted

技术标签:

【中文标题】为 keyPressEvent 子类化 QTextEdit 是唯一的方法吗?【英文标题】:Is subclassing QTextEdit for keyPressEvent override the only way? 【发布时间】:2019-12-09 17:55:57 【问题描述】:

我正在使用 PySide2 构建一个 Qt 应用程序,它至少有一个类似文本编辑器的视图。我想修改QTextEdit的keyPressEvent方法的功能有两个原因:

    添加使用用户定义的键盘操作来操作文本的功能(例如使用 tab/shift+tab 的标准缩进/缩进,尽管还有很多其他操作)。 为了便于未来的某些功能,正在显示的文本将以完全不同的结构(不是 html/RTF/等,而是树)存储。这让我相信我不能将 QTextEdit 用作组合视图+控制器,而是必须提取控制器逻辑以在每次按键后正确修改底层结构,并将生成的文本提供给 QTextEdit。 (虽然,我考虑过利用 QTextEdit 在后台使用 HTML 的事实,可能使用 diva 标签隐藏结构。注意下面

鉴于 Python 是被解释的,这两者的结合——加上也使用 QSyntaxHighlighter 的愿望——让我很担心。如果每次按键都执行大量业务逻辑,那么它最终可能会非常引人注目。现在,我不想过早地进行优化,但我想避免走上一条我可能不得不做出更耗时的改变的道路。我只是好奇,如果没有用 C++ 编写 QTextEdit 子类,是否还有其他一些我没想到的方法可能会更高效。

或者,如果似乎需要 QTextEdit 的 C++ 子类,则覆盖 keyPressEvent 是最好的方法。

请注意,以下更新与将业务登录注入 QTextEdit 的输入处理(以及划分视图/控制器职责)的愿望没有直接关系,而是向具有类似用例的任何其他人提供信息作为第 2 项: 只是在 QtDesigner 中使用小部件,<a> 锚点和 <meta> 标记都不能至少“标记”结构元素,同时对结构元素也是不可见的用户。 (<a name="something"></a> 不随文本移动,<meta> 始终移动到头部)。

【问题讨论】:

嗯,您的上一版与您在上一部分中指出的内容无关。对我来说,它闻起来像 XY problem,你的具体目标是什么?或者更糟糕的是,你的问题太宽泛了,不要在一个问题上问太多。 我觉得不算太多。我在问我将代码注入输入处理过程的提议是否不是最佳解决方案。我提供了更大的背景来说明我为什么要这样做。不过,我会澄清。 我指出,因为 fferri 的答案符合“1”,您应该能够将其扩展到“2”,但这显然很复杂。我认为如果您绕过 keyPressEvent 的先决条件为“2”创建一个新问题会更好,例如:“我想要 X、Y 和 Z,例如如果我写“W”必须发生“w”等。到目前为止,我尝试使用 keyPressEvent:显示代码等“。那将更具可扩展性。由于从标题“你强迫”认为解决方案是 keyPressEvent 并且也许还有另一种选择,例如可以使用 QShortcuts 替换 fferri 的答案 【参考方案1】:

您可以使用事件过滤器来处理按键操作,而无需继承 QTextEdit

from PySide import QtCore, QtGui

class Window(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.edit = QtGui.QTextEdit(self)
        self.edit.installEventFilter(self)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.edit)

    def eventFilter(self, widget, event):
        if (event.type() == QtCore.QEvent.KeyPress and
            widget is self.edit):
            key = event.key()
            if key == QtCore.Qt.Key_Escape:
                print('escape')
            else:
                if key == QtCore.Qt.Key_Return:
                    self.edit.setText('return')
                elif key == QtCore.Qt.Key_Enter:
                    self.edit.setText('enter')
                return True
        return QtGui.QWidget.eventFilter(self, widget, event)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 300, 300)
    window.show()
    sys.exit(app.exec_())

【讨论】:

(刚刚测试过)是的,这确实消除了子类化的需要(对于案例 1)。但是,可能会出现同样的问题,因为所有逻辑都是在 Python 中处理的。 这听起来像是过早的优化。但总的来说,您可以采用任何 CPU 密集型算法并将其移植到 C/C++ 并使其成为 Python 扩展,从而在 Python/Qt 中维护大部分应用程序逻辑。

以上是关于为 keyPressEvent 子类化 QTextEdit 是唯一的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

PyQt / PySide keyPressEvent 默认行为

对于公共密钥,您将如何访问相应的值

是否需要在子类中调用基类的事件处理函数?

Qt 中响应回车事件 keyPressEvent

CAD命令qtext怎么用?

6.20