Qt事件循环

Qt程序执行QApplication::exec()函数后,将进入事件循环来监听应用程序的事件,Qt中所有的事件类都继承于QEvent。

事件发生时,Qt创建一个事件对象,传递给QObject的event()函数,event()函数并不直接处理事件,而是对这些事件按照它们不同的类型分发给不同的事件处理函数。

event()函数主要用于事件的分发,如果要在事件分发之前做一些操作,就需要重写event()函数。

鼠标事件:

#include <QMouseEvent>

1 void mousePressEvent(QMouseEvent *event);               //单击
2 void mouseReleaseEvent(QMouseEvent *event);             //释放
3 void mouseDoubleClickEvent(QMouseEvent *event);         //双击
4 void mouseMoveEvent(QMouseEvent *event);                //移动
5 void wheelEvent(QWheelEvent *event);                    //滚轮
 1 void QtEventTest::mousePressEvent(QMouseEvent *event)
 2 {
 3     if (event->button() == Qt::LeftButton)
 4     {
 5 
 6     }
 7     else if (event->button() == Qt::RightButton)
 8     {
 9 
10     }
11 }
12 
13 void QtEventTest::mouseReleaseEvent(QMouseEvent *event)
14 {
15 
16 }
17 
18 void QtEventTest::mouseDoubleClickEvent(QMouseEvent *event)
19 {
20     if (event->button() == Qt::LeftButton)
21     {
22     }
23     else if (event->button() == Qt::RightButton)
24     {
25     }
26 }
27 
28 void QtEventTest::mouseMoveEvent(QMouseEvent *event)        //默认情况下,此触发事件需要点击一下,才能触发。可设置为自动触发:setMouseTracking(true);
29 {
30     if (event->buttons() & Qt::LeftButton)  //buttons() 位与 左击
31     {
32     }
33 }
34 
35 void QtEventTest::wheelEvent(QWheelEvent *event)
36 {
37     if (event->delta() > 0)
38     {
39         //远离使用者方向滚动
40     }
41     else
42     {
43         //靠近使用者方向滚动
44     }
45 }

Qt中buttons()和button()的区别,官方解析如下:

Qt::MouseButton QMouseEvent::button() const

返回产生事件的按钮

Qt::MouseButton QMouseEvent::buttons() const

返回产生事件的按钮状态,函数返回当前按下的所有按钮,按钮状态可以是Qt::LeftButton,Qt::RightButton,Qt::MidButton或运算组合

假设鼠标左键已经按下,
如果移动鼠标,会发生的move事件,button返回Qt::NoButton,buttons返回LeftButton。
再按下了右键,会发生press事件,button返回RightButton,buttons返回LeftButton | RightButton
再移动鼠标,会发生move事件,button返回Qt::NoButton,buttons返回LeftButton | RightButton
再松开左键,会发生Release事件,button返回LeftButton,buttons返回RightButton
也就是说,button返回“那个按钮发生了此事件”,buttons返回"发生事件时哪些按钮还处于按下状态"

键盘事件:
#include <QKeyEvent>

1 void keyPressEvent(QKeyEvent *event);                   //按下
2 void keyReleaseEvent(QKeyEvent *event);                 //释放

从网上查资料发现,Qt的按键消息响应keyPressEvent()表现为按住一个键时,会先响应一次,停顿一会,然后开始不断响应。

而且Qt的键盘函数有一个问题,它不是“按下按键才触发keyPressEvent(), 弹起按键才触发keyReleaseEvent()",而是”输出按键消息前触发keyPressEvent(),输出后触发keyReleaseEvent()“,表现为按住一个键时,不断地press、release、press、release、press、release......

Qt的QKeyEvent类中提供isAutoRepeat()判断,即按住按键时触发的那些键盘事件isAutoRepeat类型,可以据此排除中间触发的那些press和release

综上所述,Qt的键盘事件整体表现为,按住一个键时:
1、第一次触发keyPressEvent(), isAutoRepeat()返回false

2、没有触发keyReleaseEvent(),停顿一会

3、再一次触发keyPressEvent(),isAutoRepeat()返回true

4、触发keyReleaseEvent()

5、若没松开按键,isAutoRepeat()返回true,返回第3步;若松开按键,isAutoRepeat()返回false

 1 void QtEventTest::keyPressEvent(QKeyEvent *event)
 2 {
 3     if (event->key() == Qt::Key_Up)
 4     {
 5         //避免自动重复,按键重复时return;
 6         if (event->isAutoRepeat())
 7         {
 8             return;
 9         }
10 
11                 ...
12         keyUp = true;  //标记向上方向键已经按下
13     }
14     else if (event->key() == Qt::Key_Left)
15     {
16         if (event->isAutoRepeat())
17         {
18             return;
19         }
20 
21                 ...
22         keyLeft = true;  
23     }
24 }
25 
26 void QtEventTest::keyReleaseEvent(QKeyEvent *event)
27 {
28     if (event->key() == Qt::Key_Up)
29     {
30         if (event->isAutoRepeat())
31         {
32             return;
33         }
34                 
35                 ...
36     }
37     else if (event->key() == Qt::Key_Left)
38     {
39         if (event->isAutoRepeat())
40         {
41             return;
42         }
43 
44                 ...
45     }
46 }
原文地址:https://www.cnblogs.com/Jace-Lee/p/5869170.html