zoukankan      html  css  js  c++  java
  • Qt 键盘事件 长按按键反复触发event事件问题解决

    1.问题描述

    上一篇文章中,简单实现了利用qt检测用户按键操作并将键按下释放操作打印在Qt界面上的一个小程序。但是在测试过程中会出现一个现象,那就是长按某个键不放,界面一直在刷新press、release、press、release……(如下图)

    也就是说,在长按某个键不释放的情况下,keyPressEvent和keyReleaseEvent事件会不断被触发。尽管这是Qt设计实现好的事件机制,但在用户体验上,这是不合常理的。我们希望实现的是:按下某个键(比如Tab键),界面只打印一次"Key_Tab Press";当手松开时,界面上才打印"Key_Tab Release"。

    2.问题说明event->isAutoRepeat()

    为此查询了Qt官方文档和几篇博客。

    官方文档上提到一个QKeyEvent的成员函数isAutoRepeat:

    bool QKeyEvent::isAutoRepeat () const
    Returns true if this event comes from an auto-repeating key; returns false if it comes from an initial key press.

    Note that if the event is a multiple-key compressed event that is partly due to auto-repeat, this function could return either true or false indeterminately.

     可以看到,当event来自于auto-repeating key,isAutoRepeat返回true;当event事件来自于最初的按键,则sAutoRepeat返回false。这么说可能不好理解,那不妨Jungle做个小测试。

    2.1.在keyPressEvent里打印isAutoRepeat返回值

    操作:长按Tab键,在keyPressEvent里打印isAutoRepeat返回值,松开Tab键后,再次长按Tab键,再松开

     1 void QKeyBoard::keyPressEvent(QKeyEvent *event){
     2     switch(event->key()){
     3         case Qt::Key_Tab:
     4             if(event->isAutoRepeat()==true){
     5                 this->ui.textEdit_press->append("true");
     6             }
     7             else{
     8                 this->ui.textEdit_press->append("false");
     9             }
    10             this->ui.textEdit_press->append("Key_Tab Press");
    11             break;
    12         /*default:
    13             this->ui.textEdit->append("KeyEvent");*/
    14     }
    15 }

    测试结果如下图:

    从测试结果可以看到,长按下Tab键第一次触发keyPressEvent事件时isAutoRepeat返回false,之后长按过程中isAutoRepeat返回值均为true。松键后再次长按,isAutoRepeat返回false,之后长按过程中isAutoRepeat返回值均为true。即只有首次按下Tab键时,isAutoRepeat返回值为false。结合这个结果来看Qt官方文档的描述,似乎更好理解一点。

    2.2.在keyReleaseEvent里打印isAutoRepeat返回值

    同样,Jungle在keyReleaseEvent里打印isAutoRepeat返回值,运行结果如下(代码略):

    可以看到, 长按下Tab键,自动触发keyReleaseEvent事件时isAutoRepeat返回true,真正松键后触发keyReleaseEvent事件时isAutoRepeat返回true。

    2.3.测试总结

    结合Qt官方文档和上述测试,可以得出如下结论:

    • 按键触发的keyPressEvent事件,isAutoRepeat返回false;自动触发的keyPressEvent事件,isAutoRepeat返回true;
    • 松键触发的keyReleaseEvent事件,isAutoRepeat返回true;自动触发的keyReleaseEvent事件,isAutoRepeat返回false。

    3.解决

    在真正按键和松键事件触发时,加上对isAutoRepeat返回值的判断,具体判断如2.3总结所言,示例代码如下:

     1 void QKeyBoard::keyPressEvent(QKeyEvent *event){
     2     switch(event->key()){
     3         case Qt::Key_Tab:
     4             if(!event->isAutoRepeat()){
     5                 this->ui.textEdit_press->append("Key_Tab Press");
     6                 /* add your code here*/
     7             }
     8             break;
     9     
    10         /*default:
    11             this->ui.textEdit->append("KeyEvent");*/
    12     }
    13 }
    14  
    15 void QKeyBoard::keyReleaseEvent(QKeyEvent *event){
    16     switch(event->key()){
    17         case Qt::Key_Tab:
    18             if(!event->isAutoRepeat()){
    19                 this->ui.textEdit_release->append("Key_Tab Release");
    20                 /* add your code here*/
    21             }
    22             break;
    23         /*default:
    24             this->ui.textEdit->append("KeyEvent");*/
    25     }
    26 }

    在某些博客里,作者可能增设了某个变量来标记键是否被按下,并在按下和松键时更新标记。但Jungle认为并没有必要,像上述那样加入判断即可。

  • 相关阅读:
    inflate用一个XML源填充view. LayoutInflater
    关于inflate的第3个参数
    关于inflate的第3个参数
    android ImageView scaleType属性
    android ImageView scaleType属性
    Android中设置文本颜色的三种方法
    JDK1.8与spring3.x的不兼容
    Spring整合activiti单元测试
    良好编程习惯的养成
    No output operations registered, so nothing to execute
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14184801.html
Copyright © 2011-2022 走看看