为 keyPressEvent 子类化 QTextEdit 是唯一的方法吗?
Is subclassing QTextEdit for keyPressEvent override the only way?
我正在使用 PySide2 构建一个 Qt 应用程序,它至少有一个类似于文本编辑器的视图。我有两个原因想要修改 QTextEdit 的 keyPressEvent
方法的功能:
- 添加使用用户定义的键盘操作来操作文本的功能(例如使用 tab/shift+tab 的标准 indent/dedent,尽管还有许多其他操作)。
- 为了促进某些未来的功能,正在显示的文本将存储在一个完全不同的结构中(不是 HTML/RTF/etc,而是一棵树)。这让我相信我不能将 QTextEdit 用作组合视图+控制器,而是必须提取控制器逻辑以在每次按键后正确修改底层结构,并将生成的文本提供给 QTextEdit。 (虽然,我已经考虑过利用 QTextEdit 在引擎盖下使用 HTML 的事实,可能使用
div
或 a
标签隐藏结构。 请注意下面)
考虑到 Python 被解释,这两者的结合 - 加上希望也使用 QSyntaxHighlighter - 让我担心。如果每次按键都会执行大量的业务逻辑,那么它最终可能会非常引人注目。现在,我不想过早地进行优化,但我想避免走上一条看起来我可能不得不进行更耗时的更改的道路。我很好奇,如果没有用 C++ 编写 QTextEdit 子类,是否还有其他一些我没有想到的方法可能会更高效。
或者,如果似乎需要 QTextEdit 的 C++ 子类,则覆盖 keyPressEvent
是最好的方法。
请注意,以下更新与将业务登录注入 QTextEdit 的输入处理(并划分 view/controller 职责)的愿望没有直接关系,而是向其他任何人提供信息与项目 2 有类似的用例: 刚刚在 QtDesigner 中试用了小部件,<a>
锚点和 <meta>
标签都不能至少达到 "tag" 结构元素,同时对用户也是不可见的。 (<a name="something"></a>
不随文本移动,<meta>
始终移动到头部)。
您可以使用事件过滤器来处理按键,而无需子类化 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_())
我正在使用 PySide2 构建一个 Qt 应用程序,它至少有一个类似于文本编辑器的视图。我有两个原因想要修改 QTextEdit 的 keyPressEvent
方法的功能:
- 添加使用用户定义的键盘操作来操作文本的功能(例如使用 tab/shift+tab 的标准 indent/dedent,尽管还有许多其他操作)。
- 为了促进某些未来的功能,正在显示的文本将存储在一个完全不同的结构中(不是 HTML/RTF/etc,而是一棵树)。这让我相信我不能将 QTextEdit 用作组合视图+控制器,而是必须提取控制器逻辑以在每次按键后正确修改底层结构,并将生成的文本提供给 QTextEdit。 (虽然,我已经考虑过利用 QTextEdit 在引擎盖下使用 HTML 的事实,可能使用
div
或a
标签隐藏结构。 请注意下面)
考虑到 Python 被解释,这两者的结合 - 加上希望也使用 QSyntaxHighlighter - 让我担心。如果每次按键都会执行大量的业务逻辑,那么它最终可能会非常引人注目。现在,我不想过早地进行优化,但我想避免走上一条看起来我可能不得不进行更耗时的更改的道路。我很好奇,如果没有用 C++ 编写 QTextEdit 子类,是否还有其他一些我没有想到的方法可能会更高效。
或者,如果似乎需要 QTextEdit 的 C++ 子类,则覆盖 keyPressEvent
是最好的方法。
请注意,以下更新与将业务登录注入 QTextEdit 的输入处理(并划分 view/controller 职责)的愿望没有直接关系,而是向其他任何人提供信息与项目 2 有类似的用例: 刚刚在 QtDesigner 中试用了小部件,<a>
锚点和 <meta>
标签都不能至少达到 "tag" 结构元素,同时对用户也是不可见的。 (<a name="something"></a>
不随文本移动,<meta>
始终移动到头部)。
您可以使用事件过滤器来处理按键,而无需子类化 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_())