一、QT的事件发送类QCoreApplication

QT使用QCoreApplication类为Qt程序提供了事件循环机制。该类继承QObject。QCoreApplication包含主事件循环,来自操作系统的事件(例如计时器和网络事件)和其他事件都将在主事件循环中被处理和调度。

在QT的程序中,主函数一般都是这样的

int main(int argc, char *argv[])
{QApplication a(argc, argv);mainWindow w;w.show();return a.exec();
}

在QT的main函数中,第一句必须定义一个QApplication的对象。QApplication间接继承了QCoreApplication,其对象a调用的是父类QCoreApplication中的exec(),然后进入了主事件循环。

static int QCoreApplication::exec()

主事件循环的生命周期和函数exec的生命周期是相等的,如果主事件循环不退出,那么exec将永远执行,不结束

QCoreApplication中的quit()函数和exit()函数可以使主事件循环退出

static void QCoreApplication::quit()
static void QCoreApplication::exit(int returnCode = 0)

当调用上述两个函数中的任何一个后,QT应用程序的主事件循环退出,并且QT应用程序返回到调用exec的地方,同时exec函数退出并返回对应的退出码,退出码正常值是0,表示正常退出,非0值表示有错误,此外,如果没有主事件循环,那么,调用该函数将不会执行任何动作

QCoreApplication除了提供exec()、quit()和exit()外,还提供了sendEvent()立刻发送事件;postEvent()将事件发布到事件队列中,等待处理;removePostedEvents()将删除事件队列中的所有事件;也可以使用sendPostedEvents()分发事件队列中的所有事件。

1.sendEvent

static bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)

sendEvent()通过notify函数立刻将事件event发送给接受者receiver。返回值由对象的实际事件处理程序决定是true or false,所以,当sendEvent()返回时,事件过滤器或对象本身的事件处理程序已经处理完该事件。sendEvent发送完事件后,并不会删除该事件。

示例

int main(int argc, char *argv[])
{QApplication a(argc, argv);mainWindow w;QPointF pos;pos.setX(100);pos.setY(100);QMouseEvent event(QEvent::MouseButtonPress, pos, Qt::NoButton, 0, 0);QApplication::sendEvent(w.gettextEdit(), &event);w.show();return a.exec();
}

可见,当运行主函数后,事件马上发送,并通过事件过滤其打印出一条log

2.postEvent

static void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)

postEvent并不会立刻发送事件,而是将事件event添加到事件队列中并立即返回

当QT程序回到主事件循环时,将使用notify()函数将队列中存储的所有事件一起发送。

事件event的对象必须分配在堆上,因为事件的发送队列要在发送后把事件删除,而不能让事件的生命周期自动结束,分配在堆上可以保证事件的生命周期。

事件按优先级从高到低的顺序排序,即优先级高的事件在优先级较低的事件之前排队。优先级介于INT_MAX和INT_MIN之间;有具有相同优先级的事件将按照发布(添加)的顺序进行处理。

事件的优先级在枚举Qt::EventPriority中定义

enum EventPriority {HighEventPriority = 1,//具有此优先级的事件将在具有NormalEventPriority或LowEventPriority的事件之前发送。NormalEventPriority = 0,//具有此优先级的事件在具有HighEventPriority的事件之后但在具有LowEventPriority的事件之前发送。LowEventPriority = -1//具有高优先级的事件在具有HighEventPriority或NormalEventPriority的事件之后发送。
};

优先级示例

enum CustomEventPriority{ImportantEventPriority = Qt::HighEventPriority,  // An important eventMoreImportantEventPriority = ImportantEventPriority + 1,// A more important eventCriticalEventPriority = 100 * MoreImportantEventPriority, // A critical eventStatusEventPriority = Qt::LowEventPriority,// Not that importantIdleProcessingDoneEventPriority = StatusEventPriority - 1// These are less important than Status events};

3.notify

virtual bool QCoreApplication::notify(QObject *receiver, QEvent *event)

该函数是将事件event发给接受者receiver的实际执行者,返回值由具体的事件处理程序决定,所有事件的发送最终都会调用该函数。

当某些事件发送给接受者后,如果接受者对该事件不感兴趣(比如返回值为false),那么该事件会发给接受者对象的父对象(不是基类或者父类)处理,以此类推,直至发送给位于对象树模型上的最顶层对象,也就是说,无论任何事件,一定有接收者和接收者的事件处理程序来接收,事件处理程序有可能是父类的事件处理程序或者是父对象的事件处理程序或者是本类中的重写的事件处理程序

4.removePostedEvents

static void QCoreApplication::removePostedEvents(QObject *receiver, int eventType = 0)

删除事件队列中的所有事件,不要调用这个函数!!!

5.sendPostedEvents

static void QCoreApplication::sendPostedEvents(QObject *receiver = Q_NULLPTR, int event_type = 0)

立即分派事件排队中的所有事件,如果receiver为空,则event_type事件将被发送给所有对象。如果event_type为0,则将所有事件发送给接收者。这两个参数都由默认实参,也就是说,默认情况下,调用该函数后会将事件队列中的所有事件发送给QT程序中的所有对象

注意:窗口相关的事件不是由此函数分发,而是由函数processEvents()分发

6.processEvents

static void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents)
static void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)

这个函数有两种重载形式,第一种形式是根据ProcessEventsFlags处理调用线程中所有还没处理的事件,第二种形式是根据ProcessEventsFlags在maxtime毫秒内处理调用线程中还没处理的事件

这个函数通常可以在长时间繁忙运行的QT程序中被调用,以保持QT程序对事件的响应速度

二、QT的t事件队列接口类QAbstractEventDispatcher

QAbstractEventDispatcher类提供了管理Qt事件队列的接口,事件分配器接收事件后,将它们发送到QCoreApplication或QApplication实例进行处理。QAbstractEventDispatcher是一个纯虚基类,具体的接口实现根据操作系统而在不同的子类中实现

其中的processEvents函数形式如下

virtual bool QAbstractEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) = 0;

该函数处理与标志匹配的未处理事件,直到没有更多事件可处理为止。 如果事件被处理,则返回true;否则,返回false。

如果在标志中设置了QEventLoop :: WaitForMoreEvents标志,则此函数的行为如下:

如果有未处理事件,则此函数在处理完事件后返回。

如果没有可用的事件,则此函数将会等待,直到有更多未处理事件为止,然后处理完新的事件后返回。

如果没有在标志中设置QEventLoop :: WaitForMoreEvents标志,并且没有未处理事件,则此函数将立即返回。

此函数不会连续处理事件; 在处理所有可获得的事件后,根据标志位看看是否需要等待新的事件或者直接返回

三、QT的事件循环类QEventLoop

QEventLoop类提供一种进入和退出事件循环的方法。

创建一个QEventLoop对象并对其调用exec()以启动事件循环。 从事件循环中,调用exit()将强制exec()返回,事件循环退出。

int QEventLoop::exec(ProcessEventsFlags flags = AllEvents)
void QEventLoop::exit(int returnCode = 0)

和QCoreApplication中的exec和exit的作用相同,因为QCoreApplication中的exec最终会创建QEventLoop对象并调用QEventLoop的exec

所以,QT的事件循环机制相关的主要类除了QObject外,还有三个,QCoreApplication负责事件的发送,QAbstractEventDispatcher负责事件队列的管理和事件队列的分发,QEventLoop负责创建事件循环

参考

https://doc.qt.io/Qt-5/qabstracteventdispatcher.html

https://doc.qt.io/Qt-5/eventsandfilters.html

https://doc.qt.io/Qt-5/qcoreapplication.html

https://doc.qt.io/Qt-5/qeventloop.html

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

8.QT的事件循环与事件发送相关类相关推荐

  1. c/c++:Libevent应用(Libevent介绍、 事件处理框架 - event_base、事件循环、事件、带缓冲区的事件、链接监听器)

    目录 1. Libevent介绍 1.1 安装Libevent 2. 事件处理框架 - event_base 2.1 event_base API函数 event_base和fork(进程)关系: 3 ...

  2. Qt中事件循环机制详解

    问题1:Qt中常见的事件有哪些? 答:鼠标事件(QMouseEvent).键盘事件(QKeyEvent).绘制事件(QPaintEvent).窗口尺寸改变(QResizeEvent).滚动事件(QSc ...

  3. Qt 之 Eventloop 事件循环

    文章目录 需求 QEventLoop Demo1- 登录 Demo2- 延时 Demo3- 在程序中等待服务器返回 理解QT事件循环 事件循环抽象 Qt是事件驱动的 Qt常见事件 Qt事件从哪里来 Q ...

  4. 关于Qt的事件循环以及QEventLoop的简单使用

    1.一般我们的事件循环都是由exec()来开启的,例如下面的例子: 1 QCoreApplicaton::exec() 2 QApplication::exec() 3 QDialog::exec() ...

  5. Qt事件循环的一些理解

    1.事件循环一般用exec()函数开启.QApplicaion::exec().QMessageBox::exec()都是事件循环.其中前者又被称为主事件循环. 事件循环首先是一个无限"循环 ...

  6. Qt线程间通信-自定义事件

    线程间通信: 1.自定义事件:postEvent(): 2.信号与槽[本质也是通过自定义事件实现的] 注意:每个线程都有自己的事件循环 自定义事件: 1.从QEvent继承: 2.registerEv ...

  7. 技术干货 | JavaScript 之事件循环(Event Loop)

    导读:学过 JavaScript(下文简称 JS) 的都知道它是一门单线程的.非阻塞的脚本语言.单线程意味着,JS 代码在执行的任何时候,都只有一个主线程来处理所有的任务,这也就意味着 JS 无法进行 ...

  8. Node.js文件的同步异步事件循环

    刚接触Node.js关于同步异步,事件循环的笔记: 1,文件同异步 var fs = require('fs'); fs.readFile('file.txt', 'utf-8', function( ...

  9. JavaScript事件循环

    大厂面试题分享 面试题库 后端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 一.异步执行原理 1. 单线程的JavaScript 我们知道,JavaScript是一种单线程语言,它主要 ...

最新文章

  1. NLP重大突破?一文读懂XLNet“屠榜”背后的原理
  2. 如何得到iterator的当前元素_Java中迭代器Iterator详解
  3. 谷歌已推送 Android Q Beta 1
  4. 关于async和await的探讨
  5. 跳跃表(Skip list)原理与java实现
  6. 前端学习(2893):导航组件的编写和属性技巧设置
  7. mysql添加临时索引_mysql 中添加索引的三种方法
  8. 无锡linux内核开发,【Linux系统-无锡有前途吗】Softtek2021年Linux系统-无锡就业前景-看准网...
  9. 沉筛得招牢蛹得客频冉酶厍笨频涸
  10. 三维扫描3D打印在创客教育中的实际应用
  11. 冒犯有时是必要的:如何开启一段亲密关系?
  12. 行程单批量打印软件(eTerm航空电子客票行程单打印软件)
  13. 使用PHP制作 简易员工管理系统之二(管理员登陆界面以及验证)
  14. httpclient中警告Encrypted Alert后断开连接问题处理
  15. 英语计算机手抄报图片大全,五年级英语手抄报图片大全
  16. JAVA 面试(更新)
  17. javascript:验证是否是真实有效的身份证号码函数
  18. 二、三级等保建议安全设备及其主要依据(毫无保留版)
  19. js中slice、splice、split的比较
  20. Exact Audio Copy

热门文章

  1. linux基础(day22)
  2. 微信小程序尝鲜一个月现状分析
  3. 诊断Java中的内存泄露
  4. 【命令】usemod 的用法
  5. 信息安全系统设计基础第五周学习总结
  6. 招不招新人?IT经理很纠结.
  7. 基于SSM+Layui实现医院预约挂号系统
  8. Spark的RDD 文件读取与保存
  9. python绘图添加上下标
  10. 如何反转 Python 中的字符串