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 }