PyQt小部件键盘焦点

时间:2016-01-27 19:30:39

标签: python pyqt pyqt5 keypress arrow-keys

首先 - 感谢这个团队!我大约一个月前开始钻研PyQt。在那个时候,我遇到了许多问题,几乎总能在这里找到答案。

直到现在。

我有一个解决方法,但我认为这是一个kluge,可能有一个正确的方法。我想更好地了解发生了什么。

以下是代码:

from PyQt5.QtCore       import *
from PyQt5.QtGui        import *
from PyQt5.QtWidgets    import *


class FormWidget(QWidget):
    def __init__(self, parent):        
        super(FormWidget, self).__init__(parent)

        # Create view with image in it
        self.image = QGraphicsPixmapItem(QPixmap())
        self.scene = QGraphicsScene()
        self.scene.addItem(self.image)
        self.view = QGraphicsView(self.scene)

        self.hlayout = QHBoxLayout()
        self.hlayout.addWidget(self.view)
        self.setLayout(self.hlayout)

#       self.view.keyPressEvent = self.keyPressEvent

    def keyPressEvent(self, event):
        key = event.key()
        mod = int(event.modifiers())
        print(
            "<{}> Key 0x{:x}/{}/ {} {} {}".format(
                self,
                key,
                event.text(),
                "  [+shift]" if event.modifiers() & Qt.SHIFT else "",
                "  [+ctrl]" if event.modifiers() & Qt.CTRL else "",
                "  [+alt]" if event.modifiers() & Qt.ALT else ""
            )
        )


class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        form = FormWidget(self) 
        self.setCentralWidget(form) 


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()
    sys.exit(app.exec_())

原样,除了箭头键之外,所有键盘输入都被重载的keyPressEvent()函数检测到。我发现有足够的帖子谈论这个,因为它是因为子窗口小部件(self.view)正在接收它们。我认为子窗口小部件实际上是接收所有键击,但是忽略了那些正在通过的键盘,并且吮吸了箭头键,这就是为什么它们没有到达父键的keyPressEvent ()函数。这似乎是这样,因为如果我取消注释中间的那条线:

        self.view.keyPressEvent = self.keyPressEvent

它的行为与我期望的一样 - 父母的keyPressEvent()获取所有击键,包括箭头。

如何告诉子窗口小部件忽略所有击键?我想也许这个:

        self.view.setFocusPolicy(Qt.NoFocus)

当我添加它时,keyPressEvent()根本看不到任何键击。

我想我也可以为子进程重载keyPressEvent(),并且只是明确地将所有内容传递给父进程。但这似乎并不比我的kluge好。

我想我一定是在误解。

感谢。只是想学习......

2 个答案:

答案 0 :(得分:2)

您应该考虑使用eventFilter来捕获子窗口小部件上的事件,而不是对子窗口小部件进行子类化或尝试防止击键到达它。您将在子窗口小部件之前看到所有事件,您可以抑制或转换它们。

http://doc.qt.io/qt-5.5/qobject.html#eventFilter

答案 1 :(得分:2)

默认情况下,QWidget不接受键盘焦点,因此您需要明确启用它:

class FormWidget(QWidget):
    def __init__(self, parent):
        ... 
        self.setFocusPolicy(Qt.StrongFocus)