開發環境:win10+vs2015+qt5.9.1
背景:QPushButton的雙擊事件雖然一直有,但是在雙擊完成之前,總會響應到單擊的事件處理或者連接槽,使用很不方便。自己子類化了一個QPushButton來區分這兩種點擊事件的處理
1 /* 2 * Description: 分開響應單擊和雙擊的QPushButton 3 * Author: 公子開明 KaiMing Prince 4 * Detail: 默認的QPushButton,雙擊事件觸發前會先觸發單擊事件,影響兩個操作的分別處理 5 * Class: DoubleClickedButton 6 * Implement: 本類實現了QPushButton雙擊和單擊的分別處理事件 7 */ 8 #ifndef _DOUBLE_CLICKED_BUTTON_H__ 9 #define _DOUBLE_CLICKED_BUTTON_H__ 10 #include <QPushButton> 11 12 class QTimer; 13 14 class DoubleClickedButton : public QPushButton 15 { 16 Q_OBJECT 17 18 public: 19 DoubleClickedButton(QWidget *parent=Q_NULLPTR); 20 DoubleClickedButton(const QString &text, QWidget *parent = Q_NULLPTR); 21 DoubleClickedButton(const QIcon &icon, const QString &text, QWidget *parent = Q_NULLPTR); 22 23 ~DoubleClickedButton(); 24 25 protected: 26 virtual bool event(QEvent* event); 27 28 signals: 29 void singleClicked(); 30 void doubleClicked(); 31 32 private: 33 bool m_bDoubleClicked; 34 QTimer* m_single_clicked_timer; 35 }; 36 #endif //_DOUBLE_CLICKED_BUTTON_H__
首先,我們需要一個定時器來延時判斷單擊事件,當收到單擊事件是啟動定時器;當定時器觸發還沒有第二次單擊進入的時候,認為是單擊事件;觸發之前收到雙擊事件或第二次單擊事件,則視為是一個雙擊動作,具體代碼如下
1 #include "DoubleClickedButton.h" 2 #include <QEvent> 3 #include <QTimer> 4 5 DoubleClickedButton::DoubleClickedButton(QWidget *parent) 6 : QPushButton(parent), 7 m_single_clicked_timer(new QTimer(this)), 8 m_bDoubleClicked(false) 9 { 10 m_single_clicked_timer->setSingleShot(true); 11 connect(m_single_clicked_timer, SIGNAL(timeout()), this, SIGNAL(singleClicked())); 12 } 13 14 DoubleClickedButton::DoubleClickedButton(const QString &text, QWidget *parent) 15 : DoubleClickedButton(parent) 16 { 17 setText(text); 18 } 19 20 DoubleClickedButton::DoubleClickedButton(const QIcon &icon, const QString &text, QWidget *parent) 21 : DoubleClickedButton(text, parent) 22 { 23 setIcon(icon); 24 } 25 26 DoubleClickedButton::~DoubleClickedButton() 27 { 28 } 29 30 bool DoubleClickedButton::event(QEvent* event) 31 { 32 switch (event->type()) 33 { 34 case QEvent::MouseButtonRelease: 35 m_bDoubleClicked ? m_bDoubleClicked = false//如果是第二次進入,重置狀態 36 /*這里需要一個超時判斷,超時還沒進入MouseButtonDblClick事件才算是單擊效果*/ 37 : m_single_clicked_timer->start(10);//測試發現間隔時間最好不要低於10ms,否則不夠兩個事件的反饋間隔,如果需要延遲,可以自行修改間隔時間 38 break; 39 case QEvent::MouseButtonDblClick: 40 m_single_clicked_timer->stop();//進入雙擊事件停止掉定時器 41 m_bDoubleClicked = true; 42 emit doubleClicked(); 43 break; 44 default: 45 break; 46 } 47 48 return QPushButton::event(event); 49 }
定時器只能觸發一次,否則會無限發出單擊信號,這里要注意一下;在mouseRelease事件中,判斷是否已經觸發過doubleclick,如果觸發過就不能再啟動定時器了,只有第一次單擊才能觸發定時器,所以我們需要一個bool值判斷一下是否為第二次進入單擊事件。
剩下的就很簡單了,雙擊事件直接關閉定時器,發送出雙擊信號,單擊事件則等待定時器觸發認為沒有第二次點擊再發出單擊信號
定時器的時間在測試中發現最好不要低於10ms,至於具體doubleclick和第二次mouseRelease到底差了多少響應間隔,我沒有具體去打印判斷了,有興趣的可以自己測試,或者參考qt源碼看doubleclick的響應判斷方式