【问题标题】:PyQt not recognizing arrow keysPyQt 无法识别箭头键
【发布时间】:2014-08-22 02:12:04
【问题描述】:

我正在尝试编写一个(目前非常)简单的 PyQt 应用程序,并希望允许用户使用箭头键进行导航,而不是单击按钮。

我已经实现了基本功能,并且在我的主要QWidget 中,我覆盖了keyPressEvent,而现在,我所要求的只是它会发出警报(QMessageBox.information(self, "Hey", "pressed:{}".format(event), QMessageBox.Ok))。

这对于标准 ASCII 键(例如字母和 Enter 键)非常有效,但是当我按下箭头键时它完全被忽略了,我终生无法弄清楚原因。

我的一部分想知道键盘是否还有其他问题,因为我使用的是没有数字键盘的笔记本电脑(它是带有标准常规 ASCII 键盘的 HP,四个箭头键楔入右 Shift 下方,并且没有数字键盘)。

有什么建议或帮助吗?如果需要,我可以发布代码,但由于 keyPressEvent 适用于所有其他键,我不确定它会添加什么。

【问题讨论】:

  • 您能否发布一段简短的工作代码来重现该问题?我不知道为什么会这样,但我不是 Qt 专家。
  • 我试图将代码精简到 MAFE(最小的适当失败示例)并且问题消失了......所以我一定错过了一些东西,也许添加了另一个小部件,如 @Kitsune Meyoko建议(虽然设置 FocusPolicy 在第一次尝试时不起作用) - 我会做一些实验并回复你。谢谢!
  • 这个老问题的所有读者,也检查这个线程:stackoverflow.com/q/39807858/2039431

标签: python pyqt4 arrow-keys


【解决方案1】:

如果您不想关注子小部件的任何内容。如果您只想要主 QWidget,请设置 Children No Focus Policy;

例如,希望有帮助;

import sys
from PyQt4 import QtGui, QtCore

class QCustomWidget (QtGui.QWidget):
    def __init__ (self, parent = None):
        super(QCustomWidget, self).__init__(parent)
        myQLayout = QtGui.QVBoxLayout()
        self.my1QPushButton = QtGui.QPushButton('Test 1', self)
        self.my2QPushButton = QtGui.QPushButton('Test 2', self)
        self.setChildrenFocusPolicy(QtCore.Qt.NoFocus)
        myQLayout.addWidget(self.my1QPushButton)
        myQLayout.addWidget(self.my2QPushButton)
        self.setLayout(myQLayout)

    def setChildrenFocusPolicy (self, policy):
        def recursiveSetChildFocusPolicy (parentQWidget):
            for childQWidget in parentQWidget.findChildren(QtGui.QWidget):
                childQWidget.setFocusPolicy(policy)
                recursiveSetChildFocusPolicy(childQWidget)
        recursiveSetChildFocusPolicy(self)

    def keyPressEvent (self, eventQKeyEvent):
        messageQMessageBox = QtGui.QMessageBox(QtGui.QMessageBox.Question, 'Question', 'Hello Main', QtGui.QMessageBox.Yes)
        messageQMessageBox.exec_()
        QtGui.QWidget.keyPressEvent(self, eventQKeyEvent)

appQApplication = QtGui.QApplication(sys.argv)
windowQCustomWidget = QCustomWidget()
windowQCustomWidget.setFixedSize(640, 480)
windowQCustomWidget.show()
sys.exit(appQApplication.exec_())

QWidget.setFocusPolicy (self, Qt.FocusPolicy policy) Reference

FocusPolicy ENUM Reference


widget中的当前光标,按键生效。

案例1:纯QWidget:这种情况下它可以跟踪所有关键,因为专注于自我QWidget

import sys
from PyQt4 import QtGui, QtCore

class QCustomWidget (QtGui.QWidget):
    def __init__ (self, parent = None):
        super(QCustomWidget, self).__init__(parent)
        myQLayout = QtGui.QVBoxLayout()
        self.setLayout(myQLayout)

    def keyPressEvent (self, eventQKeyEvent):
        messageQMessageBox = QtGui.QMessageBox(QtGui.QMessageBox.Question, 'Question', 'Hello', QtGui.QMessageBox.Yes)
        messageQMessageBox.exec_()
        QtGui.QWidget.keyPressEvent(self, eventQKeyEvent)

appQApplication = QtGui.QApplication(sys.argv)
windowQCustomWidget = QCustomWidget()
windowQCustomWidget.setFixedSize(640, 480)
windowQCustomWidget.show()
sys.exit(appQApplication.exec_())

案例 2:在QWidget 中添加按钮:此案例无法跟踪箭头键,因为它已使用焦点按钮和箭头键设置新的焦点位置。 (如果您在 linux 中使用样式 Windows,您可以看到焦点网格线)

import sys
from PyQt4 import QtGui, QtCore

class QCustomWidget (QtGui.QWidget):
    def __init__ (self, parent = None):
        super(QCustomWidget, self).__init__(parent)
        myQLayout = QtGui.QVBoxLayout()
        self.my1QPushButton = QtGui.QPushButton('Test 1', self)
        self.my2QPushButton = QtGui.QPushButton('Test 2', self)
        myQLayout.addWidget(self.my1QPushButton)
        myQLayout.addWidget(self.my2QPushButton)
        self.my1QPushButton.keyPressEvent = self.button1KeyPressEvent
        self.my2QPushButton.keyPressEvent = self.button2KeyPressEvent
        self.setLayout(myQLayout)

    def keyPressEvent (self, eventQKeyEvent):
        messageQMessageBox = QtGui.QMessageBox(QtGui.QMessageBox.Question, 'Question', 'Hello Main', QtGui.QMessageBox.Yes)
        messageQMessageBox.exec_()
        QtGui.QWidget.keyPressEvent(self, eventQKeyEvent)

    def button1KeyPressEvent (self, eventQKeyEvent):
        messageQMessageBox = QtGui.QMessageBox(QtGui.QMessageBox.Question, 'Question', 'Hello Button 1', QtGui.QMessageBox.Yes)
        messageQMessageBox.exec_()
        QtGui.QPushButton.keyPressEvent(self.my1QPushButton, eventQKeyEvent)

    def button2KeyPressEvent (self, eventQKeyEvent):
        messageQMessageBox = QtGui.QMessageBox(QtGui.QMessageBox.Question, 'Question', 'Hello Button 2', QtGui.QMessageBox.Yes)
        messageQMessageBox.exec_()
        QtGui.QPushButton.keyPressEvent(self.my2QPushButton, eventQKeyEvent)

appQApplication = QtGui.QApplication(sys.argv)
windowQCustomWidget = QCustomWidget()
windowQCustomWidget.setFixedSize(640, 480)
windowQCustomWidget.show()
sys.exit(appQApplication.exec_())

我不知道 PyQt 的箭头键返回的 ASCII 是什么,但你可以避免这种情况。在pyQt中有QtCore.Qt.Key的ENUM,你可以阅读类参考;

例子:

def keyPressEvent (self, eventQKeyEvent):
    key = eventQKeyEvent.key()
    if key == QtCore.Qt.Key_F1:
        print 'Help'
    elif key == QtCore.Qt.Key_F5:
        print 'Reload'
    elif key == QtCore.Qt.Key_Left:
        print 'Left'
    elif key == QtCore.Qt.Key_Up:
        print 'Up'
    elif key == QtCore.Qt.Key_Right:
        print 'Right'
    elif key == QtCore.Qt.Key_Down:
        print 'Down'

另见:Qt.Key ENUM Reference

【讨论】:

  • 这就是我试图让它工作时开始的地方,但如果我把 QMessageBox 作为该函数的第一行,它仍然不会被调用,这意味着按下这些箭头键甚至根本没有注册为 KeyPressEvent
  • (并且,作为一个可能幽默的旁注 - 我添加 QMessageBoxs 的原因是因为我尝试使用 Qt.Key_Up 但它不起作用所以我想“好吧,让我打印有关此事件的信息以查看发生了什么")
  • 你的实现是什么小部件类。小部件中的当前光标,它具有按下键的效果。例如,按钮列表。箭头键不起作用,因为它通过设置新的光标位置使用。
  • 只是一个普通的QWidget
  • @KitsuneMeyoko,这是一个非常相似的问题:stackoverflow.com/q/39807858/2039431。也许你也知道那里的答案。
猜你喜欢
  • 1970-01-01
  • 2019-02-19
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 2021-08-18
  • 2014-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多