QT實現鍵盤復用 單擊 雙擊 長按

2022-01-14 20:43:33 字數 3709 閱讀 2379

**:

首先鍵盤按鍵的單擊、雙擊實現,沒錯!就是用的qtimer,一說到這估計大部分人都知道怎麼回事了,但這裡也有個誤區,那就是如何區分單擊和雙擊的問題,這也是我實現過程中遇到的問題。我最開始的做法是根據按下和釋放的時間間隔來區分的,現在看來這顯然是不對的,但當時腦袋可能矇圈了(>_<),這樣是無法準確的區分單擊和雙擊的,應該用兩次按鍵的時間間隔來區分,這裡在按下、或釋放裡實現都是可以的,我最後選擇在釋放裡實現,後面再說原因。如果誰不清楚按下、釋放什麼意思,自己去查qt幫助文件吧。。。

標頭檔案裡定義幾個相關變數

1

2 qtimer*timer_;

3bool longpress_;//

後面用到

4int clickcount_;//

按鍵計數

5 keyflag keyflag_;//

列舉

1

enum

keyflag

2;

建構函式連線timeout訊號到單擊函式

1

2 timer_ = new qtimer(this

);3 connect(timer_, signal(timeout()), this

, slot(keyoneclick()));

4 clickcount_ = 0

;5 longpress_ = false

;6 keyflag_ = kkey_null;

重寫void keyreleaseevent(qkeyevent *event)

1

void myclass::keyreleaseevent(qkeyevent *event

) 9 clickcount_++;//

點選計數,在400ms內如果點選兩次認為是雙擊

10if (clickcount_ == 2)16

break;17

18case qt::key_s://

注意到沒?我實現的都是字母鍵,其他鍵是不一樣的

19break;20

case

qt::key_d:

21break;22

case

qt::key_f:

23break;24

case

qt::key_j:

25break;26

case

qt::key_k:

27break;28

default:29

break;30

}3132 }

單擊函式,在400ms內未達到雙擊次數,也就是未執行timer_->stop();時間耗盡觸發timeout訊號,執行單擊動作。這裡提一下stop()函式,qtimer執行start(n)後,如果不stop(),那它會迴圈執行。

void

myclass::keyoneclick()

}

至此實現鍵盤單擊和雙擊復用,那麼我們再來看一下長按怎麼處理呢?

先看一下按鍵長按的過程分析,我們知道一按一鬆實現一次click動作,那我們測試一下qt鍵盤長按的具體過程,重寫void keypressevent(qkeyevent *event)、void keyreleaseevent(qkeyevent *event)函式。

為了區分是否是長按,qkeyevent 提供了乙個isautorepeat()函式自動檢測按鍵是否長按

為了方便表示我定義

下面看一下長按會發生什麼吧。

1

void myclass::keypressevent(qkeyevent *event) 9

else

13break;14

default:15

break;16

}1718}

1920

void myclass::keyreleaseevent(qkeyevent *event

) 28

else

32break;33

default:34

break;35

}3637 }

執行結果用我的方式表示為:p(f)r(t)p(t)r(t)…p(t)r(t)p(t)r(f),也就是當你長按時會迴圈發生press和release動作,

第一次執行press動作,此時qkeyevent 不認為你在長按,而在release時,qkeyevent 已經開始認為你在長按了;

第二次到倒數第二次qkeyevent 認為你都在長按;

最後一次,press動作依然為長按,但release卻變成非長按了;

也就是不管你按多久最開始的press肯定為非長按狀態,最後的release肯定為非長按狀態。結合這些特性,我們來實現鍵盤按鍵的復用,即同時實現單擊雙擊和長按三個動作。

前面提到單擊和雙擊的區分,其實在void keypressevent(qkeyevent *event)、void keyreleaseevent(qkeyevent *event)函式裡都可以,反正都是記錄時間差,press-press或release-release沒分別,那最後為什麼選擇在keyreleaseevent(qkeyevent *event)函式裡實現呢?

問題就在還得同時實現長按功能,剛剛分析得出無論你長按還是非長按,第一次的press動作他都是p(f)的,如果在void keypressevent(qkeyevent *event)裡實現,那長按必然會附加一次單擊,這當然不是我們想要的;

再來看看在void keyreleaseevent(qkeyevent *event),如果長按,它第一次就是r(t)了,那就可以通過判斷isautorepeat()的狀態來區分長按和非長按了。

還有乙個問題就是,雖然可以判斷長按了,但是長按時是會迴圈執行的,如不控制,豈不會執行n次長按要實現的動作,因此還要加乙個flag來控制,讓它只執行一次。

最後,還要討論一下長按的最後一次release動作,它和非長按的release是相同的r(f),為了避免這種情況,我們正好利用控制長按的flag來進行區分。

至此分析完畢,我想我們該開始寫**了。

1

void myclass::keyreleaseevent(qkeyevent *event

) 14 clickcount_++;

15if (clickcount_ == 2)21

}22 longpress_ = false;//

置false23}

24else

31}32break;33

34case

qt::key_s:

35break;36

case

qt::key_d:

37break;38

case

qt::key_f:

39break;40

case

qt::key_j:

41break;42

case

qt::key_k:

43break;44

default:45

break;46

}

47 }

親測有效,如有不同方法,歡迎討論,或是有更好的方法,也請不吝分享!

js 實現單擊 雙擊事件

js 實現繫結按鈕單擊 雙擊事件 單擊 雙擊按鈕1 單擊 雙擊按鈕2 方法一 var clickbtn document.getelementbyid clickbtn1 clickbtn.onclick function clickbtn.ondblclick function 方法二 funct...

使用狀態機的按鍵掃瞄 單擊 雙擊和長按

這篇部落格記錄下前面用到的狀態機按鍵掃瞄漏掉的乙個實驗專案,單個按鍵的單擊 雙擊和長按的檢測。如下 include typedef unsigned int uint16 typedef unsigned char uint8 define no key 0xff define key state0...

51微控制器自學 完美的單擊 雙擊 長按 中斷消抖

完整的單擊 雙擊 長按 工作原理 當有按鈕第一次按下時,設定第乙個標誌an,當按鈕第一次釋放後,進入中斷消抖延時計數,假如在計數範圍內第二次按鈕按下,設定第二標誌aa,這樣就把單擊和雙擊區分開,而且是可靠的邏輯標誌,長按為大於1秒的判斷.中斷消抖及按鈕單擊 雙擊 長按處理,雙擊在 中穩穩地檢測到執行...