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認為並沒有必要,像上述那樣加入判斷即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM