获取任何QKeyEvent键值的可打印名称 [英] Get printable name of any QKeyEvent key value

查看:123
本文介绍了获取任何QKeyEvent键值的可打印名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我已经看到此先前的问题,其中可接受的答案(使用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给我可打印的任何表示形式, ever 可能是event.key()的值,其中event是QKeyEvent?

解决方案

要处理特定问题:

我怎样才能让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_())

I'm using PyQt5. When I write a keyPressEvent handler, I would like to be able to print, for debugging purposes, a human-readable description of what keys were pressed. I want to be able to print such a thing no matter what, regardless of how many keys were pressed in the event, or whether they were modifiers or "regular" keys.

I have seen this previous question in which the accepted answer (using C++) suggests creating a QKeySequence and using its .toString method. I can do this like this:

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

However, this does not always work. For instance, if I press the Shift key, it will result in an encoding error when I try to output (or if I try to encode it to UTF-8). This seems to be because QKeySequence does not work on isolated modifier keys:

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

It gives gibberish instead of what I would expect, namely "Shift". It works if I use Qt.SHIFT (sort of, in that it gives "Shift+"), but that is of no use, because Qt.SHIFT is not what I get in event.key() if I press the Shift key.

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?

解决方案

To deal with the specific question:

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?

The first things to note is that event.key() returns an int, rather than a Qt.Key. This is simply because the key can be any unicode value whatsoever. As a consequnce of this, it is not really feasible to give a printable representation of literally anything, since not every unicode key is printable, and it is impractical to enumerate them all.

The only API Qt provides for this is the QKeySequnce class. However, as you have found, it does not handle all inputs in the way you want. So you will have to roll your own solution.

It might be tempting to use QMetaEnum to convert key values to their names wherever possible. However, this won't work here, because there is no staticMetaObject for the Qt object, and PyQt does not provide anything like qt_getQtMetaObject. It also doesn't currently implement QMetaEnum.fromType (although this is likely to change in future versions).

So the only available solution is to use normal python introspection to build a mapping, and build up a printable representation from that.

Here is a basic demo (only tested on 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_())

这篇关于获取任何QKeyEvent键值的可打印名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆