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

标签 python qt pyqt pyqt5 keyboard-events

我正在使用 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+”),但这没有用,因为 Qt.SHIFT不是我得到的event.key()如果我按下 Shift 键。

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

最佳答案

处理具体问题:

How can I get Qt to give me a printable representation of anything that might ever be the value of event.key(), where event is a QKeyEvent?



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

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

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

因此,唯一可用的解决方案是使用普通的 python 内省(introspection)来构建映射,并从中构建可打印的表示。

这是一个基本的演示(仅在 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_())

关于python - 获取任何 QKeyEvent 键值的可打印名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50851350/

相关文章:

python - Spark : How to parse and transform json string from spark data frame rows

python - 如何在 python 中将可变长度参数与关键字参数结合起来?

c++ - qt 和 libbluedevil : No Such slot

c++ - QTableWidget Item 获取Widget类型并访问它

python - 如何更改 QPushButton 文本和背景颜色

python - 使用 QSqlTableModel 的 QListView 中的复选框

python - 类型错误 : cannot unpack non-iterable bool object

python - 从 python 运行 perl 脚本

c++ - 当 QSortFilterProxyModel 过滤 QTreeView 中的项目时,如何自动展开该项目?

python - 在 PyQt 中创建和添加 MapQuickItem 到 map