Qt中如何判断按键是否真正释放?Linux X11下isAutoRepeat失效问题
Linux X11下Qt keyReleaseEvent自动重复问题的解决
问题描述
重写keyReleaseEvent函数时,按住按键触发系统自动重复,会导致该函数被循环调用;且在Linux X11环境下,event->isAutoRepeat()始终返回false,无法区分自动重复产生的释放事件。
复现代码(仅适用于Linux X11)
#include <QApplication> #include <QDebug> #include <QKeyEvent> #include <QWidget> class Window : public QWidget { public: Window(QWidget* parent = nullptr): QWidget(parent) {} void keyReleaseEvent(QKeyEvent* event) override { if (!event->isAutoRepeat())// 在Windows上正常工作 qDebug() << "keyRelease"; } }; int main(int argc, char** argv) { QApplication app(argc,argv); Window window; window.show(); return app.exec(); }
原因分析
根据Qt文档说明:
注意:如果事件是包含自动重复的多键压缩事件,此函数可能会不确定地返回true或false。
在Linux X11环境中,系统自动重复的按键事件处理机制与Windows不同,Qt的isAutoRepeat()无法可靠识别自动重复产生的释放事件,导致该判断失效。
解决方案:手动维护按键状态
通过自行维护当前按下的按键集合,过滤掉自动重复产生的虚假释放事件:
#include <QApplication> #include <QDebug> #include <QKeyEvent> #include <QWidget> #include <QSet> class Window : public QWidget { private: QSet<int> m_pressedKeys; // 记录当前处于按下状态的按键 public: Window(QWidget* parent = nullptr): QWidget(parent) {} void keyPressEvent(QKeyEvent* event) override { if (!m_pressedKeys.contains(event->key())) { m_pressedKeys.insert(event->key()); // 这里处理按键首次按下的逻辑 qDebug() << "keyPress:" << event->key(); } // 若需要处理自动重复的按下事件,可在此添加逻辑 QWidget::keyPressEvent(event); } void keyReleaseEvent(QKeyEvent* event) override { if (m_pressedKeys.contains(event->key())) { m_pressedKeys.remove(event->key()); qDebug() << "keyRelease"; } // 不在集合中的释放事件为自动重复触发,直接忽略 QWidget::keyReleaseEvent(event); } }; int main(int argc, char** argv) { QApplication app(argc,argv); Window window; window.show(); return app.exec(); }
方案说明
- 用
QSet<int>记录当前按下的按键ID,确保每个按键只有在首次按下时被加入集合 - 在
keyReleaseEvent中,仅当按键存在于集合中时,才处理释放逻辑并移除集合中的记录 - 自动重复产生的释放事件会因按键不在集合中而被过滤,避免无效调用
内容的提问来源于stack exchange,提问作者YuXin
相关产品推荐
相关产品推荐

