【问题标题】:Get printable name of any QKeyEvent key value获取任何 QKeyEvent 键值的可打印名称
【发布时间】:2018-11-23 20:51:33
【问题描述】:

我正在使用 PyQt5。当我编写一个 keyPressEvent 处理程序时,为了调试目的,我希望能够打印出关于按下了哪些键的人类可读的描述。无论事件中按下了多少个键,或者它们是修饰键还是“常规”键,我都希望能够打印这样的东西。

我已经看到this previous question,其中接受的答案(使用 C++)建议创建 QKeySequence 并使用其.toString 方法。我可以这样做:

def keyPressEvent(self, event):
    print("got a key event of ", QKeySequence(event.key()).toString())

但是,这并不总是有效。例如,如果我按下 Shift 键,当我尝试输出(或者如果我尝试将其编码为 UTF-8)时会导致编码错误。这似乎是因为 QKeySequence 不适用于孤立的修饰键:

>>> QKeySequence(Qt.Key_Shift).toString().encode('unicode-escape')
b'\\u17c0\\udc20'

它给出了胡言乱语,而不是我所期望的,即“Shift”。如果我使用Qt.SHIFT(有点,因为它提供“Shift+”),它就可以工作,但这没有用,因为如果我按下 Shift 键,Qt.SHIFT 不是我在event.key() 中得到的。

我怎样才能让 Qt 给我一个 anything 的可打印表示,它可能曾经event.key() 的值,其中 event 是一个 QKeyEvent?

【问题讨论】:

  • 这就是元对象系统的用途 - other answer to cited question 正是您所需要的。
  • @KubaOber:对我来说,如何使代码适应 Python 并不明显。你能展示如何在 PyQt5 中做到这一点吗?我在接受答案的前半部分遇到了类似的问题;在 PyQt 中,我看不到如何访问所描述的“反向”映射,理论上这会将 Key_Shift 之类的数值映射到它们的文本名称。
  • 我认为您需要查看Qt.ShiftModifierQt.ControlModifier 看看这里:stackoverflow.com/questions/8772595/…
  • @ChristofferGøthgen:这些似乎是 Qt.SHIFT 和 Qt.CTRL 的别名,正如我所说,它们没有用,因为它们不存在于键值中。我的出发点是event.key()的值;我想将 that 转换为字符串表示形式。我知道我可以通过检查来自event.modifiers() 的所有修饰符并将它们手动映射到字符串来手动完成,但我想知道是否有一种方法可以让 Qt 给我它而不必自己做所有这些。
  • Qt 能给你什么?为什么?它是 Python,它比 C++ 简单得多。 Qt 对象具有 Key_foo 属性。枚举它们并找到所有匹配项是微不足道的。您甚至可以预先缓存它们的反向映射,以便更快地查找。还有Qt.KeyboardModifierMask等。忘掉C++吧。想想 Python。 Python 具有无处不在的自省功能。如果你知道一个对象有一个属性,你当然可以枚举它,自省它等等。这与 C++ 非常非常不同。在 C++ 中,您需要 moc 来内省枚举。在 Python 中,它在语言中。

标签: python qt pyqt pyqt5 keyboard-events


【解决方案1】:

处理具体问题:

我怎样才能让 Qt 给我任何东西的可打印表示 这可能是 event.key() 的值,其中 event 是 QKeyEvent?

首先要注意的是event.key() 返回一个int,而不是Qt.Key。这仅仅是因为密钥可以是任何 unicode 值。因此,给出字面上任何东西的可打印表示实际上并不可行,因为并非每个 unicode 键都是可打印的,并且枚举它们是不切实际的。

Qt 提供的唯一 API 是 QKeySequnce 类。但是,正如您所发现的,它不会以您想要的方式处理所有输入。所以你必须推出自己的解决方案。

尽可能使用QMetaEnum 将键值转换为其名称可能很诱人。但是,这在这里不起作用,因为Qt 对象没有staticMetaObject,而且PyQt 不提供类似qt_getQtMetaObject 的任何东西。它目前也没有实现QMetaEnum.fromType(尽管这可能会在未来的版本中改变)。

所以唯一可用的解决方案是使用普通的 python 自省来构建映射,并从中构建可打印的表示。

这是一个基本的演示(仅在 Linux 上测试):

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget

keymap = {}
for key, value in vars(Qt).items():
    if isinstance(value, Qt.Key):
        keymap[value] = key.partition('_')[2]

modmap = {
    Qt.ControlModifier: keymap[Qt.Key_Control],
    Qt.AltModifier: keymap[Qt.Key_Alt],
    Qt.ShiftModifier: keymap[Qt.Key_Shift],
    Qt.MetaModifier: keymap[Qt.Key_Meta],
    Qt.GroupSwitchModifier: keymap[Qt.Key_AltGr],
    Qt.KeypadModifier: keymap[Qt.Key_NumLock],
    }

def keyevent_to_string(event):
    sequence = []
    for modifier, text in modmap.items():
        if event.modifiers() & modifier:
            sequence.append(text)
    key = keymap.get(event.key(), event.text())
    if key not in sequence:
        sequence.append(key)
    return '+'.join(sequence)

class Window(QWidget):
    def keyPressEvent(self, event):
        print(keyevent_to_string(event))

if __name__ == '__main__':

    app = QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 100, 300, 200)
    window.show()
    sys.exit(app.exec_())

【讨论】:

  • @BrenBarn 这是一个非常好的答案...为什么还没有经过验证?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-26
  • 2016-10-10
  • 2017-09-05
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
相关资源
最近更新 更多