1. Qt事件概述

事件是对各种应用程序需要知道的由应用程序内部或者外部产生的事情或者动作的通称。对于初学者,总会对Qt中信号和事件的概念混淆不清。其实,记住事件比信号更底层就可以了。比如说,我们用鼠标按下界面上的一个按钮,它会发射clicked()单击信号,但是,它怎么知道自己被按下的呢,那就是通过鼠标事件处理的。这里可以看到,鼠标事件比信号更底层。

在Qt中处理事件有多种方法,不过最常用的是重写Qt事件处理函数。

2. Qt事件的来源

3. Qt事件机制

Qt中定义的事件是一个从QEvent类继承而来的对象,它表示应用程序内部或外部发生了某些应用程序自身必须知道的事情。任何从QObject类派生的对象均可以通过QObject::event()方法接收事件。事件产生时,Qt会创建一个合适的QEvent对象或其子对象,然后通过调用QObject类的event()函数将这个事件对象传给特定的QObject对象或其子对象。需要指出的是,event()函数自身并不处理事件,而是根据事件类型调用相应的事件处理器,其返回值告知这个事件是否被接受并进行了处理。例如,QWidget类中的event()函数实现将鼠标、键盘和重绘等常见事件交给mousePressEvent()、keyPressEvent()和paintEvent()这些特定的事件处理器进行处理。

事件处理方式顺序:

  • Qt事件产生后立即被分发到QWidget对象
  • QWidget中的event(QEvent*)进行事件处理
  • event()根据事件类型调用不同的事件处理函数
  • 在事件处理函数中发送Qt中预定义的信号
  • 调用信号关联的槽函数

在Qt内部,Qt通过由函数QCoreApplication::exec()启动的主事件循环不停抓取事件队列中的本地窗口事件,然后将它们转换成对应的QEvent对象,并最终将这些QEvent对象发送到目的QObject对象来完成上述一系列事件的处理动作。

需要注意的是,不应该混淆事件和信号这两个概念。通常,在使用已有的窗口部件时,信号是十分有用的,而在自定义新的窗口部件时,事件则更为重要。举例来讲,当使用QPushButton类时,程序员往往只关注其clicked()信号,而很少关心底层的鼠标或者键盘事件。但当自定义一个类似QPushButton的类时,程序员就不得不编写一定量的代码来处理鼠标或者键盘事件,并在适当的时候发送clicked()信号。从这个角度讲,事件比信号更底层

Qt的事件处理有5种级别:

1.      重写控件的事件处理函数:如重写keyPressEvent(),mousePressEvent()和paintEvent(),这是最常用的事件处理方法,我们已经看到过很多这样的例子了。

2.      重写QObject::event(),在事件到达事件处理函数前处理它。在需要改变Tab键的惯用法时这样做。也可以处理那些没有特定事件处理函数的比较少见的事件类型(例如,QEvent::HoverEnter)。我们重写event()时,必须要调用基类的event(),由基类处理我们不需要处理的那些情况。

3.      给单独的QObject对象安装事件过滤器:对象用installEventFilter()注册后,所有目标对象的事件都首先到达监视对象的eventFilter()函数。如果一个对象有多个事件过滤器,过滤器按顺序激活,先到达最近安装的监视对象,最后到达最先安装的监视对象。

4.      给QApplication对象安装事件过滤器,如果qApp(唯一的QApplication对象)安装了事件过滤器,程序中所有对象的每个事件在被送到任何其它事件过滤器之前都要送到eventFilter()函数中。这个方法在调试的时候非常有用,在处理禁止使能状态的控件的鼠标事件时这个方法也很常用。

5.      继承QApplication,重写notify()。Qt调用QApplication::nofity()来发送事件。重写这个函数是在其他事件过滤器接收事件前得到所有事件的唯一方法。通常事件过滤器是最有用的,因为在同一时间,可以有任意数量的事件过滤器,但是notify()函数只有一个。

4.  鼠标事件

QKeyEvent类:描述一个键盘事件。当键盘按键被按下或者被释放时,键盘事件便会被发送给拥有键盘输入焦点的部件。

相关函数:

key();                                   //获取键盘对应的键值,不区分大小写
void keyPressEvent(QKeyEvent *event);    //按下事件
void keyReleaseEvent(QKeyEvent *event);  //抬起事件

单个事件:

if (event->key() == Qt::Key_Up){ }

组合事件:

if (event->modifiers() == Qt::ControlModifier){ }

void Widget::keyPressEvent(QKeyEvent *event)
{int x,y;if (event->modifiers() == Qt::ControlModifier) {switch (event->key()) {case Qt::Key_Down:x = m_endPt.x()+10;y = m_endPt.y()+10;m_endPt.setX(x);m_endPt.setY(y);update();m_bIsDrawing = true;break;case Qt::Key_Up:x = m_endPt.x()-10;y = m_endPt.y()-10;m_endPt.setX(x);m_endPt.setY(y);update();m_bIsDrawing = true;break;}}
}void Widget::keyReleaseEvent(QKeyEvent *event)
{switch (event->key()) {case Qt::Key_Down:m_bIsDrawing = false;update();break;case Qt::Key_Up:m_bIsDrawing = false;update();break;}
}

5.  键盘事件

QMouseEvent类:表示一个鼠标事件,当在窗口部件中按下抬起鼠标或者移动鼠标指针时,都会产生鼠标事件。

相关函数:

button();                                       //返回鼠标的事件值
buttons();                                      //返回鼠标的事件值(移动事件时)
x();                                            //返回X坐标
y();                                            //返回Y坐标
pos();                                          //返回X和Y坐标
void mousePressEvent(QMouseEvent *event);      //按下事件处理函数
void mouseReleaseEvent(QMouseEvent *event);    //弹起事件处理函数
void mouseDoubleClickEvent(QMouseEvent *event);//双击事件处理函数
void mouseMoveEvent(QMouseEvent *event);       //移动事件处理函数

鼠标事件值:

QWheelEvent类:表示鼠标滚轮事件,在这个类中主要是获取滚轮移动方向和距离

相关函数 :

delta() //获取滚轮移动的距离函数 每当滚轮旋转一下,默认的是15度向上滚动,delta()函数返回正值向下滚动,delta()函数返回负值
void wheelEvent(QWheelEvent *event);
void Widget::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton){m_lastPt = event->pos();m_bIsDrawing = true;   //正在绘图}
}void Widget::mouseReleaseEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton){m_endPt = event->pos();m_bIsDrawing = false;update();}}void Widget::mouseMoveEvent(QMouseEvent *event)
{if (event->buttons() == Qt::LeftButton){m_endPt = event->pos();update();}}

6. 定时器事件

Qt中有两种方法来使用定时器,一种是定时器事件,另一种是使用信号和槽。一般使用了多个定时器时最好使用定时器事件来处理。

6.1 多个定时器

QTimerEvent类:定时器事件类。

相关函数:

timerId();                                  //  返回定时器值
void timerEvent(QTimerEvent *event);          //  定时器事件处理函数
   m_timerId1 = startTimer(1000);m_timerId2 = startTimer(1000);m_timerId3 = startTimer(1000);

这里开启了三个定时器,分别返回了它们的id,这个id用来区分不同的定时器。定时器的时间单位是毫秒。每当一个定时器溢出时,都会调用定时器事件处理函数,我们可以在该函数中进行相应的处理。

void Widget::timerEvent(QTimerEvent *event)
{if (event->timerId() == m_timerId1) {qDebug("style 2:timerId %d,hello world...",event->timerId());}else if (event->timerId() == m_timerId2){qDebug("style 2:timerId %d,hello world...",event->timerId());}else if (event->timerId() == m_timerId3){qDebug("style 2:timerId %d,hello world...",event->timerId());}
}

6.2 信号与槽方式

如果只是想开启少量的定时器,也可以使用信号和槽来实现。

   QTimer *timer = new QTimer(this);connect(timer,SIGNAL(timeout()),this,SLOT(updateTimer()));timer->start(1000);
void Widget::updateTimer()
{qDebug("style 1: hello world .....");
}

7. 事件过滤

相关函数:

bool eventFilter(QObject *watched, QEvent *event);   // 过滤器函数 参数:1.接受事件的对象 2.事件类型
void installEventFilter(QObject *filterObj);         // 安装一个过滤器
bool myApplication::eventFilter(QObject *obj, QEvent *event)
{static int k=1;if(event->type()==QEvent::MouseButtonPress||event->type()==QEvent::MouseButtonDblClick){qDebug()<<"Click"<<k;k++;return true;}return QApplication::eventFilter(obj,event);}

参考资料:

1. Qt5 事件(event)机制详解

2. 17.QT-事件处理分析、事件过滤器、拖放事件

3. QT基础:66---事件处理(键盘事件、鼠标事件、滚轮事件、事件过滤器)

4. Qt之事件处理机制

5. Qt事件原理

Qt学习笔记之事件处理相关推荐

  1. QT学习笔记(七):定时器事件的3种常用使用方式

    QT学习笔记(七):定时器事件的2种常用使用方式 Qt中定时器的使用有2种方法:一种是使用QObject类提供的定时器通过重载 timerEvent 事件处理过程函数,一种就是使用QTimer类. 其 ...

  2. Qt学习笔记,Qt国际化

    Qt学习笔记,Qt国际化 Qt国际化步骤: 第一步:设置.pro文件,加入TRANSLATIONS为国际化做准备 TRANSLATIONS = language/language_en.ts\     ...

  3. Qt学习笔记,Qt程序架构设计要旨

    Qt学习笔记,Qt程序架构设计要旨 时间过得很快,转眼学习Qt已经有一个多月了,对Qt的学习也在不断的深入中.自己手下的code也很多了,不过不得不说,还有很多的部分没有接触过,比如网络编程,2D,3 ...

  4. Qt学习笔记之MySQL数据库

    一.MySQL概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQ ...

  5. Qt学习笔记之数据库

    一.数据库简介 1.1.数据和数据库(DB) 用计算机进行数据处理,首先就要把信息以数据形式存储到计算机中,故数据是可以被计算机接受和处理的符号.根据所表示的信息特征不同,数据有不同的类别,如数字.文 ...

  6. Qt学习笔记之文件处理

    Qt提供了通用的文件处理类QFile和处理文本的QTextStream类和处理二进制数据的QDataStream类,这些流操作极大地方便了对文件的督促存储.对文件信息和目录进行操作的类是QfileIn ...

  7. Qt学习笔记之国际化

    国际化的英文表述为Internationalization,通常简写为I18N(首尾字母加中间的字符数),一个应用程序的国际化就是使该应用程序可以让其他国家的用户使用的过程. 1. 相关的Qt类和AP ...

  8. Qt学习笔记之 字符串类型小结

    1. Qt常用字符串类型 1.1 QString QString是Unicode编码的字符串,存储一系列16位的QChar,每一个QChar对应一个Unicode 4.0编码的字符,详见<Qt学 ...

  9. Qt学习笔记,再次分析EVA源码之后得出的结论-QListView,QListViewItem(Qt3);Q3ListView,Q3ListViewItem(Qt4)...

    Qt学习笔记,再次分析EVA源码之后得出的结论-QListView,QListViewItem(Qt3);Q3ListView,Q3ListViewItem(Qt4) 今天再次分析了Eva的源码,也看 ...

最新文章

  1. R删除冗余行数据基于dplyr包
  2. 原创 | 斯坦福Machine Learning with Graphs 学习笔记(第二讲)
  3. ipsec ip替换_点到多点ipsec-vpn NAT穿透和固定IP共存
  4. C#实现winform软件开机自动启动并最小化到系统托盘
  5. leetcode 128. Longest Consecutive Sequence | 128. 最长连续序列(Java)
  6. 深入dos编程_编程入门先要学什么?打怪升级走起来!
  7. CSDN下载频道积分规则2.1
  8. 人工智能 之 机器学习常用算法总结 及 各个常用分类算法精确率对比
  9. 通过GetVersionEx获取Win10版本号
  10. 三月不开单,开单吃三月说的是你吗?
  11. Volkswagen profit roars back two yea iot L?sungen rs after 'dieselgate'
  12. 电商宝打单发货-菜鸟面单回收
  13. 总体设计、概要设计和详细设计
  14. Fresco使用PhotoDraweeView 实现图片的手势缩放
  15. 百度地图导航的接入(包含三种选择方式驾车、公交、步行)
  16. 路由器为何会有特殊的默认路由(静态路由的一种特殊形式------默认路由)
  17. vmware虚拟机安装win7_vmware虚拟机中安装mac Catalina10.15
  18. android登录加密传输,android环境下两种md5加密方式(示例代码)
  19. python得垃圾回收机机制gc
  20. c语言实验设备管理系统设计作业,c语言程序设计实验设备管理系统

热门文章

  1. boost::scoped_thread相关的测试程序
  2. boost::mpl模块实现single_view相关的测试程序
  3. boost::mp11::mp_map_update_q相关用法的测试程序
  4. ITK:高斯的一阶导数进行卷积来计算图像的梯度
  5. VTK:PolyData之ExternalContour
  6. VTK:网格之TableBasedClipDataSetWithPolyData2
  7. OpenCV检测ArUco标记
  8. DelegateModelGroup QML类型
  9. Qt Creator浏览项目内容
  10. OpenGL 基于PBR的specular textured 镜面纹理的实例