Qt:QPushButton 单击、双击响应区分
开发环境: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的响应判断方式
https://github.com/KaiMingPrince