获取任何 QKeyEvent 键值的可打印名称

Bre*_*arn 5 python qt pyqt keyboard-events pyqt5

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

我已经看到了上一个问题,其中接受的答案(使用 C++)建议创建一个 QKeySequence 并使用它的.toString方法。我可以这样做:

def keyPressEvent(self, event):
    print("got a key event of ", QKeySequence(event.key()).toString())
Run Code Online (Sandbox Code Playgroud)

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

>>> QKeySequence(Qt.Key_Shift).toString().encode('unicode-escape')
b'\\u17c0\\udc20'
Run Code Online (Sandbox Code Playgroud)

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

我怎样才能获得Qt来给我的可打印表示事情可能永远是价值event.key(),这里event是一个QKeyEvent?

ekh*_*oro 10

处理具体问题:

我怎样才能让 Qt 为我提供任何可能是 event.key() 值的可打印表示,其中 event 是 QKeyEvent?

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

Qt 为此提供的唯一 API 是QKeySequnce类。但是,正如您所发现的,它并没有以您想要的方式处理所有输入。因此,您将不得不推出自己的解决方案。

QMetaEnum尽可能将键值转换为其名称可能很诱人。然而,这不会在这里工作,因为没有staticMetaObjectQt对象,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_())
Run Code Online (Sandbox Code Playgroud)