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尽可能将键值转换为其名称可能很诱人。然而,这不会在这里工作,因为没有staticMetaObject为Qt对象,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)
| 归档时间: |
|
| 查看次数: |
2672 次 |
| 最近记录: |