为 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 的事实,可能使用
div
或 a
标签隐藏结构。注意下面)
鉴于 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 是唯一的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章