[英]How to override keyPressEvent of QTextEdit?
I override keyPressEven() of widget QTextEdit:我覆盖了小部件 QTextEdit 的 keyPressEven():
void myTextEdit::keyPressEvent(QKeyEvent *e)
{
if(e->key()==Qt::Key_0)
{
qDebug() << "Ok";
}
}
Button 0 works - show "Ok", but does not write in field of QTextEdit.按钮 0 有效 - 显示“确定”,但不在 QTextEdit 的字段中写入。 Why?为什么? Thanks advance.先谢谢了。
You need to call the base class implementation if you want to keep the default behaviour:如果要保留默认行为,则需要调用基类实现:
void myTextEdit::keyPressEvent(QKeyEvent *e)
{
if(e->key()==Qt::Key_0)
{
qDebug() << "Ok";
}
QTextEdit::keyPressEvent(e);
}
See the docs for keyPressEvent .请参阅keyPressEvent的文档。
In case someone using PySide2
is having trouble overriding QTextEdit
's built-in keybindings, I post my solution here.如果有人使用PySide2
无法覆盖QTextEdit
的内置键绑定,我会在此处发布我的解决方案。 Hopefully this is also useful for C++.希望这对 C++ 也有用。
We are using a QTextEdit
in an application and want to distribute a series of keybindings, but the text editor has already several hardcoded bindings.我们在应用程序中使用QTextEdit
并希望分发一系列键绑定,但文本编辑器已经有几个硬编码绑定。 We want the editor to ignore them and hand them over to its parent, so they can be eventually handled by our code.我们希望编辑器忽略它们并将它们交给它的父级,这样它们最终可以由我们的代码处理。
While the docs say that whenever an event is ignored (eg by returning True
in the installed eventFilter
method) it automatically gets passed on to the parent, the truth is that when doing that for predefined keybindings QTextEdit
did not hand them over: the event got ignored AND absorbed .虽然文档说当一个事件被忽略时(例如通过在安装的eventFilter
方法中返回True
)它会自动传递给父级,但事实是,当为预定义的键绑定执行此操作时QTextEdit
并没有将它们移交给:事件得到忽略和吸收。 So any textedit built-in keybindings filtered this way will be effectively globally disabled.因此,以这种方式过滤的任何 textedit 内置键绑定都将被有效地全局禁用。
Direct event passing via sendEvent
inside the editor's eventFilter
had an interesting effect:在编辑器的eventFilter
通过sendEvent
直接传递事件有一个有趣的效果:
sendEvent
and returning super().sendEvent
, the keybinding got executed by the editor AND the event passed to the receiver.当调用sendEvent
并返回super().sendEvent
,编辑器执行键绑定并将事件传递给接收器。sendEvent
and returning True
, the keybinding didn't get executed, and the event didn't get passed to the receiver.当调用sendEvent
并返回True
,键绑定没有被执行,事件也没有传递给接收者。sendEvent
and returning False
, the keybinding didn't get executed, and the event passed to the receiver twice .当调用sendEvent
并返回False
,键绑定没有被执行,事件传递给接收者两次。Furthermore:此外:
event.ignore()
didn't have any effect: the editor executed the built-in anyway.使用event.ignore()
没有任何效果:编辑器无论如何都会执行内置的。event.spontaneous()
caused a segfault due to a missing pointer.由于缺少指针,尝试通过event.spontaneous()
进行区分会导致段错误。 Probably something got GCed but didn't try to debug that.可能有些东西被垃圾回收了,但没有尝试调试。Maybe I missed something.也许我错过了什么。 Anyway, below I detail the approach that worked for me.无论如何,下面我详细介绍了对我有用的方法。
The plan is to completely block the event, but broadcast it via signals
, and then connect to them wherever we want.计划是完全阻止事件,但通过signals
广播它,然后在我们想要的任何地方连接到它们。 In your text editor instance, define the signal eg as follows:在您的文本编辑器实例中,定义信号,例如如下:
eventCatched = QtCore.Signal(QtCore.QEvent)
Then, eg the following event filter will prevent execution of a few keybindings, and emit them once via eventCatched
:然后,例如以下事件过滤器将阻止执行一些键绑定,并通过eventCatched
发出一次eventCatched
:
def eventFilter(self, obj, evt):
"""
Remember to install via self.installEventFilter(self)
"""
catch_control_keys = {QtCore.Qt.Key_Left, QtCore.Qt.Key_Right}
catch = False
# documentation for keys and modifiers:
# https://doc.qt.io/qtforpython-5/PySide2/QtCore/Qt.html
if evt.type() == QtCore.QEvent.KeyPress:
modifiers = evt.modifiers()
ctrl = bool(modifiers & QtCore.Qt.ControlModifier)
shift = bool(modifiers & QtCore.Qt.ShiftModifier)
alt = bool(modifiers & QtCore.Qt.AltModifier)
key = evt.key()
# catch all undo/redo builtins
if ((ctrl and shift and key == QtCore.Qt.Key_Z) or
evt.matches(QtGui.QKeySequence.Undo) or
evt.matches(QtGui.QKeySequence.Redo)):
catch = True
# catch specified control-keys
if ctrl and not shift and not alt:
if key in catch_control_keys:
catch = True
#
if catch:
# block event but send it as signal
self.eventCatched.emit(evt)
return True
else:
return super().eventFilter(obj, evt)
Then, we are free to connect the signal wherever we want to, we just need a method that handles events.然后,我们可以自由地将信号连接到任何我们想要的地方,我们只需要一个处理事件的方法。 In my case, I just wanted to pass them to the main window, which can be done with the following one-liner in the constructor:就我而言,我只是想将它们传递给主窗口,这可以在构造函数中使用以下单行代码来完成:
text_editor.eventCatched.connect(lambda evt: QtCore.QCoreApplication.sendEvent(self, evt))
This way, whenever we catch an event in the text editor, it will be ignored and won't be propagated the standard way.这样,每当我们在文本编辑器中捕获一个事件时,它将被忽略并且不会以标准方式传播。 Instead, a signal will be emitted, and we can subscribe to that signal to eg restart the propagation tree at a different point, as shown here via sendEvent
.相反,将发出一个信号,我们可以订阅该信号以例如在不同的点重新启动传播树,如此处通过sendEvent
所示。
Hope this helps!希望这有帮助!
Cheers,干杯,
Andres安德烈斯
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.