QWidget无法捕获ESCAPE,BACKSPACE或C-x按键事件

时间:2019-07-04 15:19:52

标签: python pyqt pyqt5

我通过覆盖类的KeyPressEvent方法(从QWidget继承)来捕获按键事件,但是我看不到ESCAPE和BACKSPACE键的按键 press 事件,以及C-x或再次C-c。我可以看到关键的 release 事件。谁抓住了他们?

class KeyCaptureWidget(QWidget):
    # init…

    def keyPressEvent(self, event):
        key = event.key()
        logging.info("key press: {}".format(key))

    def keyReleaseEvent(self, event):
        key_code = event.key()
        logging.info("key release: {}".format(key_code))

C-x和说C-b之间的区别如下:

  • 按下C-b会打印:按下控件,按下b,释放b,释放控件。
  • 按下C-x将打印:按下控件,[什么都没有],释放x,释放控件。

在我的QWidget中,我使用了一个QVBoxLayout,其中放置了两个QWebEngine视图。我试图重写QWebEngineView的按键方法,但是它们似乎没有捕获任何东西(这是我所期望的行为)。

    def __init__(self):
        self.qtwindow = KeyCaptureWidget()

        self.layout = QVBoxLayout()
        self.view1 = QWebEngineView()  # or a custom one to override keyPressEvent
        # self.view2 = the same

        self.layout.addWidget(self.view1)
        self.layout.addWidget(self.view2)
        self.qtwindow.setLayout(self.layout)
        self.qtwindow.show()

我试图在我的QWidget类上使用事件过滤器来捕获这些消息,但是再次失败了:我只看到ESC或BACKSPACE的关键版本。

    def __init__(self):
        super().__init__()
        self.installEventFilter(self)

    def eventFilter(self, source, event):
        logging.info("event filter: {}".format(event))
        if event.type() == QEvent.KeyPress:
            logging.info(" event filter key PRESS")
        if event.type() == QEvent.KeyRelease:
            logging.info(" event filter key RELEASE")
        return True

我如何抓住他们?谢谢。

1 个答案:

答案 0 :(得分:2)

事件不一定会在所有窗口小部件之间传播,如果窗口小部件消耗了事件,则事件将不再传播到父窗口。对于键盘事件,只有具有焦点的窗口小部件才会首先使用事件,在您的情况下,QWebEngineView会先使用它们,并阻止将其投影到其他窗口小部件中。如果要从窗口的键盘中听到事件,则必须使用QShortcuts,为此必须创建QShortcut:

  • Ctrl + C QtGui.QKeySequence("Ctrl+C")
  • Ctrl + X QtGui.QKeySequence("Ctrl+X")
  • Esc QtGui.QKeySequence("Escape")
  • Backspace QtGui.QKeySequence("Backspace")

考虑到上述情况,解决方案是:

from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.m_view1 = QtWebEngineWidgets.QWebEngineView()
        self.m_view2 = QtWebEngineWidgets.QWebEngineView()
        self.m_view1.load(QtCore.QUrl("https://stackoverflow.com/questions/56890831"))
        self.m_view2.load(QtCore.QUrl("https://doc.qt.io/"))

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.m_view1)
        lay.addWidget(self.m_view2)

        QtWidgets.QShortcut(
            QtGui.QKeySequence("Ctrl+C"), self, activated=self.on_Ctrl_C
        )

        QtWidgets.QShortcut(
            QtGui.QKeySequence("Ctrl+X"), self, activated=self.on_Ctrl_X
        )

        QtWidgets.QShortcut(
            QtGui.QKeySequence("Escape"), self, activated=self.on_Escape
        )

        QtWidgets.QShortcut(
            QtGui.QKeySequence("Backspace"), self, activated=self.on_Backspace
        )

    @QtCore.pyqtSlot()
    def on_Ctrl_C(self):
        print("Ctrl+C")

    @QtCore.pyqtSlot()
    def on_Ctrl_X(self):
        print("Ctrl+X")

    @QtCore.pyqtSlot()
    def on_Escape(self):
        print("Escape")

    @QtCore.pyqtSlot()
    def on_Backspace(self):
        print("Backspace")


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())