如何覆盖QTextEdit的keyPressEvent?

时间:2013-12-30 23:35:30

标签: c++ qt qt-designer

我覆盖了widget QTextEdit的keyPressEven():

void myTextEdit::keyPressEvent(QKeyEvent *e)
{
    if(e->key()==Qt::Key_0)
    {
        qDebug() << "Ok";
    }
}

按钮0工作 - 显示“Ok”,但不写入QTextEdit字段。为什么?谢谢你。

2 个答案:

答案 0 :(得分:2)

如果要保留默认行为,则需要调用基类实现:

void myTextEdit::keyPressEvent(QKeyEvent *e)
{
    if(e->key()==Qt::Key_0)
    {
        qDebug() << "Ok";
    }
    QTextEdit::keyPressEvent(e);
}

请参阅keyPressEvent的文档。

答案 1 :(得分:0)

如果有人使用 PySide2 在覆盖 QTextEdit 的内置键绑定时遇到问题,我会在此处发布我的解决方案。希望这对 C++ 也有用。


场景:

我们在应用程序中使用 QTextEdit 并希望分发一系列键绑定,但文本编辑器已经有几个硬编码绑定。我们希望编辑器忽略它们将它们交给它的父级,以便我们的代码最终可以处理它们。

问题:

虽然文档说每当一个事件被忽略时(例如通过在安装的 True 方法中返回 eventFilter)它会自动传递给父级,但事实是当为预定义的keybindings QTextEdit 没有交出它们:事件被忽略并被吸收。因此,以这种方式过滤的任何 textedit 内置键绑定都将被有效地全局禁用。

通过编辑器 sendEvent 内的 eventFilter 传递的直接事件有一个有趣的效果:

  • 当调用 sendEvent 并返回 super().sendEvent 时,编辑器会执行键绑定并将事件传递给接收器。
  • 调用 sendEvent 并返回 True 时,未执行键绑定,并且未将事件传递给接收器。
  • 当调用 sendEvent 并返回 False 时,键绑定没有被执行,并且事件被传递给接收者两次

此外:

  • 使用 event.ignore() 没有任何效果:编辑器无论如何都会执行内置的。
  • 尝试通过 event.spontaneous() 进行区分导致由于缺少指针而导致段错误。可能有些东西被垃圾回收了,但没有尝试调试。
  • 尝试用“虚拟事件”替换事件并调用 super 也没有奏效。神奇的是,文本编辑器一直在执行内置程序。

也许我错过了什么。无论如何,下面我会详细介绍对我有用的方法。


解决方案:

计划是完全阻止该事件,但通过 signals 广播它,然后在我们想要的任何地方连接到它们。在您的文本编辑器实例中,定义信号,例如如下:

eventCatched = QtCore.Signal(QtCore.QEvent)

然后,例如以下事件过滤器将阻止执行一些键绑定,并通过 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)

然后,我们可以随意连接信号到任何我们想要的地方,我们只需要一个处理事件的方法。就我而言,我只是想将它们传递给主窗口,这可以在构造函数中使用以下单行代码来完成:

text_editor.eventCatched.connect(lambda evt: QtCore.QCoreApplication.sendEvent(self, evt))

这样,每当我们在文本编辑器中捕获一个事件时,它将被忽略并且不会以标准方式传播。相反,将发出一个信号,我们可以订阅该信号,例如在不同的点重新启动传播树,如此处通过 sendEvent 所示。

希望这有帮助!
干杯,
安德烈斯

相关问题