首页 > 解决方案 > 注册 Key_acute 事件在第一次按键时不起作用

问题描述

我正在使用 Qt 5(具体为 PyQt5)并想检查按键。

我遇到的问题是Qt::Key_acute事件未在第一次按下按钮时注册。

我使用德语键盘布局[1],也许这是我不知道的问题,但我仍然想工作,因为我知道它适用于其他程序(非 Qt)。

当按下Key_acute键时(在链接的图像中,退格键的左侧),第一次按下时没有任何反应,但是当我再次按下它时,我得到两个事件打印到控制台:1800(180 = 0x0b4 = Key_acute)。

如何捕获此键的第一个按键事件?

PyQt5 程序示例:

import sys
from PyQt5.QtWidgets import *


class App(QWidget):
    def __init__(self, argv):
        super().__init__()

        self.box = QLabel(self)
        self.show()


    def keyPressEvent(self, ev):
        print(ev.key())
        self.box.setText(str(ev.key()))
        self.box.adjustSize()

        super().keyPressEvent(ev)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App(sys.argv)
    sys.exit(app.exec_())

[1] https://upload.wikimedia.org/wikipedia/commons/3/36/KB_Germany.svg

标签: pythonpyqtpyqt5

解决方案


大多数键盘中的 [ ´ ] 键是“死键”,这是一种特殊的键,等待后面的“组合”实际字符。

据我所知,您只能将这些键作为发布事件,而不是新闻事件。

某些死键被按下两次时,它们不会作为按键/释放事件发送,但您可以将它们event()作为QEvent.InputMethod类型拦截。

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

keyNameFromValue = {}
keyNameFromString = {}
for k, v in vars(Qt).items():
    if isinstance(v, Qt.Key):
        keyNameFromValue[v] = k
        keyNameFromString[QKeySequence(v).toString()] = k


class App(QWidget):
    def __init__(self, argv):
        super().__init__()
        layout = QVBoxLayout(self)
        self.box = QLabel(self)
        layout.addWidget(self.box)
        self.show()

    def event(self, ev):
        if ev.type() == QEvent.InputMethod:
            s = ev.commitString()
            if s:
                self.box.setText('InputMethod > {}: {}'.format(
                     keyNameFromString.get(s, '(Unknown)'), s))
                self.box.adjustSize()
        return super().event(ev)

    def keyPressEvent(self, ev):
        if not ev.isAutoRepeat():
            self.box.setText('KeyPress > {}: {}'.format(
                keyNameFromValue.get(ev.key()), ev.text()))
            self.box.adjustSize()
        super().keyPressEvent(ev)

    def keyReleaseEvent(self, ev):
        if not ev.isAutoRepeat():
            self.box.setText('KeyRelease > {}: {}'.format(
                keyNameFromValue.get(ev.key()), ev.text()))
            self.box.adjustSize()
        super().keyReleaseEvent(ev)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    ex = App(sys.argv)
    sys.exit(app.exec_())

在这种情况下,第一次按下 [´] 键的结果是Key_Dead_Acute(不能直接打印),第二次是Key_acute.

如果您需要显示可打印的死键应如何显示为字符串,则可以为死键(其中少于 50 个)创建自己的基于字典的映射。不幸的是,没有编程方法可以做到这一点,因为即使对于“相同”字符,它们的字符串转换也不同,并且名称或值
之间没有实际的相关性:例如,虽然对应于,变成。Qt.Key_Dead_*Qt.Key_*Qt.Key_Dead_AcuteQt.Key_acuteQt.Key_Dead_GraveQt.Key_QuoteLeft


推荐阅读