qt源码---事件系统之QCoreApplication

上一节分析了qt和windows系统之间的消息的传递,本节着重看一下,qt内部的事件是如何传递的?

1.sendEvent函数

在使用的自定义事件时,有时需要手动抛出一个事件,常用的方式有2种,其一时阻塞式的sendEvent函数;其二是postEvent函数;sendEvent函数定义如下:

其主要是将spont设置为fasle,然后转入到notifyInternal2函数中执行处理;

其中self在QCoreApplicationPrivate构造函数中已被指定,所以不为空,if(!self && selfRequired)不会执行;

QInternal::activateCallbacks函数,会检测是否注册了事件回调函数,如果注册了对应的事件函数,会截获此事件;其对应的定义如下:

 由于在实践项目中没有用过此种方式,此处略过

接下来会通过QScopedScopeLevelCounter类将接收对象的scopeLevel变量加1,并在函数退出时,减一;此处猜测是qt标识循环层级使用的,实际是做什么用的,还不清楚;

接下来会转入doNotifity函数处理,notify函数最终也是转入doNotify函数中处理;

此处会检测接收对象和发送对象是否在同一个线程;并最终转入notify_helper函数中处理;

 

 此处会判断接收的对象是否在主线程中,如果是在主线程中,会检测QCoreApplication的对象是否安装了事件过滤器,如果此事件被QCoreApplication事件过滤器检测到并被处理,并不会向下传递;

接下来会判断此接收对象上的事件过滤器是否处理此事件,如果此事件被处理则退出;

最后,进入接收对象自己的event函数,进行事件处理;

通过上述流程可以发现:1、event对象在事件传递过程中,没有执行删除等释放动作,其内存需要用户自己管理;2、sendEvent函数一直在执行函数的调用,并最终转到notify_helper函数中处理,所以其是阻塞式调用;3、事件的传递顺序,先被QCoreApplication对象拦截,接着被对象注册的事件过滤器拦截,最后执行自己的event函数;

2、postEvent函数

 

首先判断接收对象是否为空,如果为空,删除event对象,并退出;

判断接收对象的线程是否被释放,如果接收对象所在的线程已被删除,则删除event对象,并退出;

如果接收对象被移动到其他线程中,再次检测新的线程是否被删除,如果新的线程已被删除,则删除event对象,并退出;

判断事件是否可以被压缩,即删除已经在postEventList中重复的事件,主要针对QTimerEvent事件、QDeferredDeleteEvent、QQuitEvent等事件;

 接下来,执行:

 将QEvent对象放入QScopedPointer中,将receiver、event对象拼装成QPostEvent对象,并放入到QPostEventList中,如果中间出现异常,则event对象内存有QScopedPointer对象回收;

QPostEventList是根据priority优先级进行排序执行的;

接下来将event->posted置为true,postedEvents数量加1,并将canWait设置为false;

最后调用QAbstractEventDispatcher的wakeUp函数;wakeUp函数会调用WinAPI的PostMessage函数,投递一个WM_QT_SENDPOSTEDEVENTS事件,其会被processEvent函数捡取到,并最终转入QCoreApplicationPrivate中的sendPostedEvents函数处理(具体可以参考上一节);

 

 首先判断receiver对象是否为空,是否跨线程执行?由于通过QAbstractEventDispatcher对象调用,其receiver对象为空,所以此处会跳过执行;

将recursion加1,防止递归调用;并判断postEventList列表中是否有事件,如果没有事件需要处理则退出;

接下来主要是从QPostEventList中取出事件,并调用QCoreApplication::sendEvent函数处理;

并且会在此处删除event对象,由QScopedPointer对象负责处理;

另外qt在处理取事件的过程中非常小心,考虑了很多异常情况

期间定义了CleanUp的类,主要是用来处理事件对象被处理后,清空事件列表中已经处理过的事件;

总结:

sendEvent函数:

1、event对象在事件传递过程中,没有执行删除等释放动作,其内存需要用户自己管理;

2、sendEvent函数一直在执行函数的调用,并最终转到notify_helper函数中处理,所以其是阻塞式调用;

3、事件的传递顺序,先被QCoreApplication对象拦截,接着被对象注册的事件过滤器拦截,最后执行自己的event函数;

postEvnet函数:

1、event对象会被保存在全局的postEventList列表中,由事件在处理时被释放;

2、postevent函数会将事件、receiver对象放到全局的QPostEventList列表中,并通过WINAPI的postmessage系统函数,通知QAbstractEventDispatcher类检索到,最终转入到sendPostedEvents函数中处理;

3、上一节已提到windows消息及qt自定义消息如何被检索的过程,所以可以判断出postevent函数的处理是异步的过程;

QCoreApplication类的主要内容已基本结束,下一节会着重介绍下定时器事件;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/63532.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在IDEA同一个窗口中同时打开多个独立项目

文章说明 本文主要说明如何在Intellij Idea中同时打开多个独立的Maven项目。 我在使用idea的时候,由于自己负责了很多项目,经常要在不通的代码之间切换来切换去。然后搜索代码的时候也只能搜到当前打开的这个项目。因为这个原因,一些小项目…

wxwidgets Ribbon使用wxRibbonToolBar实例

wxRibbonToolBar就是工具栏,一下是实现的效果,界面只是功能展示,没有美化 实现代码如下所示: MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(800, 600)) …

vue中点击添加类名,并且实现升降序

1.介绍 要求:掌握indexOf()用法;动态绑定类名的对象写法;iconfont使用;split()用法;三元运算符用法;es6模板字符串; 说明:首先综合元素默认有元素并且是降序。服务器传来的数据格式…

C++物理引擎Box2D的下载,编译,VS2013配置环境

文章目录 网站和下载地址编译工具:编译box2dhelloworld测试网站和下载地址 https://box2d.org/ 下载地址 https://hub.nuaa.cf/erincatto/box2d/tags 编译工具: 1.VS2013 2.cmake 下载地址 https://cmake.org/ 编译box2d 下载box2d源码2.4.0,解压。在box2d-2.4.0目录下…

什么是场景营销,小红书场景营销方式和方法有哪些

现在小红书上最流行的就是场景营销,那什么是场景营销,应该怎么做呢?今天来和大家分享下大家都在说得场景营销是什么,在小红书投放怎么做好场景营销? 一、什么是场景化营销 说白来,场景营销(Scene Marketing…

机器学习深度学习——从全连接层到卷积

👨‍🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——非NVIDIA显卡怎么做深度学习(坑点排查) 📚订阅专栏:机器…

Python测试框架pytest:测试用例、查找子集、参数化、跳过

Pytest是一个基于python的测试框架,用于编写和执行测试代码。pytest主要用于API测试,可以编写代码来测试API、数据库、UI等。 pytest是一个非常成熟的全功能的Python测试框架,主要有以下几个优点: 简单灵活,容易上手。…

react搭建在线编辑html的站点——引入grapes实现在线拖拉拽编辑html

文章目录 ⭐前言⭐搭建react ts项目⭐引入grapes 插件⭐结束 ⭐前言 大家好,我是yma16,本文分享关于react搭建在线编辑html的站点。 react 发展历史 React是由Facebook开发的一种JavaScript库,用于构建用户界面。React最初发布于2013年&…

没有配置redis但是报错连接redis失败

问题 没有配置redis但是报错连接redis失败 检查maven配置是否引入了redis依赖(可能是传递依赖,最好检查引进来的公共工程 解决办法 只需要在该工程application.yml文件中配置一下 redis就好,或者移除redis依赖 spring:redis:password: hos…

一文了解 Android Auto 车载开发~

作者:牛蛙点点申请出战 背景 我的的产品作为一个海外音乐播放器,在车载场景听歌是一个很普遍的需求。在用户反馈中,也有很多用户提到希望能在车上播放音乐。同时车载音乐也可以作为提升用户消费时长一个抓手。 出海产品,主要服务…

【Vue】Parsing error: No Babel config file detected for ... vue

报错 Parsing error: No Babel config file detected for E:\Study\Vue网站\实现防篡改的水印\demo02\src\App.vue. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files.             …

玩机搞机---安卓新机型payload.bin刷写救砖 无需专用线刷包

目前的新机型官方卡刷包解包后都是payload.bin分区格式的卡刷固件。而有个别一些机型没有线刷包,当这些机型出现系统问题的时候有以下几种方法参考救砖。遇到类似故障的朋友可以借鉴参考下. 其中的不足和相关的资源可以参考这两个博文。任何教程的目的只是拓展你的…

反射调用private方法的坑

使用反射调用私有方法时,发现空指针异常,无法直接注入导致空指针异常 加入如下代码后,恢复正常 if (AopUtils.isCglibProxy(marketSmsTaskService)) {// 如果是cglib代理对象,则转为原始对象marketSmsTaskService (MarketSmsTas…

SpringBoot3基础用法

技术和工具「!喜新厌旧」 一、背景 最近在一个轻量级的服务中,尝试了最新的技术和工具选型; 即SpringBoot3,JDK17,IDEA2023,Navicat16,虽然新的技术和工具都更加强大和高效,但是适应采坑的过程…

React安装ant design组件库,并使用

ant design是一个很棒的组件库,官方地址:快速上手 - Ant Design 但是如何在React里面用起来,好像并不是很顺畅,没有像Vue里面那么友好,因为我踩过这个坑,虽然安装很简单,但是想要出样式&#x…

地球人口承载力估计 解析和C++代码

Description 假设地球上的新生资源按恒定速度增长。照此测算,地球上现有资源加上新生资源可供x亿人生活a年,或供y亿人生活b年。 为了能够实现可持续发展,避免资源枯竭,地球最多能够养活多少亿人? Input 一行&#xf…

[数据分析与可视化] Python绘制数据地图4-MovingPandas入门指北

MovingPandas是一个基于Python和GeoPandas的开源地理时空数据处理库,用于处理移动物体的轨迹数据。它提供了一组强大的工具,可以轻松地加载、分析和可视化移动物体的轨迹。通过使用MovingPandas,用户可以轻松地处理和分析移动对象数据&#x…

C语言假期作业 DAY 15

一、选择题 1、有如下代码,则 *(p[0]1) 所代表的数组元素是( ) int a[3][2] {1, 2, 3, 4, 5, 6}, *p[3]; p[0] a[1]; A: a[0][1] B: a[1][0] C: a[1][1] D: a[1][2] 答案解析 正确答案: C p 是一个指针数组, p[0] a…

mysql 数据库引擎介绍

一、数据库引擎 数据库引擎是用于存储、处理和保护数据的核心服务。利用数据库引擎可控制访问权限并快速处理事务,从而满足企业内大多数需要处理大量数据的应用程序的要求。 使用数据库引擎创建用于联机事务处理或联机分析处理数据的关系数据库。这包括创建用于存储…

MQTT协议详解「概念、特性、版本及作用」

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是ISO标准下基于发布/订阅方式的轻量级消息协议。MQTT通常使用TCP / IP(传输控制协议/Internet协议)作为其传输,但也可以使用其他双向传输。MQ…