Qt事件传递及相关的性能问题

news2025/1/24 1:33:48

在使用Qt时,我们都知道能通过mousePressEvent,eventFilter等虚函数的重写来处理事件,那么当我们向一个界面发送事件,控件和它的父控件之间的事件传递过程是什么样的呢?
本文将以下图所示界面为例,结合源码介绍Qt事件传递的过程。
父到子的关系依次为:
MyWindow->MyButton->MyEdit。
在这里插入图片描述

在启动程序后,用鼠标点击一下MyEdit,下面是事件传递的过程。

第一步、QCoreApplication(qApp)处理事件

过程

在这里插入图片描述
这里最后接收点击事件的是最上层的控件,也就是本例中的MyEdit。

相关源码

源码按执行顺序来排列。
qwindowsysteminterface.cpp->QWindowSystemInterface::sendWindowSystemEvents
在这里插入图片描述
qapplication->QApplicationPrivate::notify_helper
在这里插入图片描述
qwidgetwindow->QWidgetWindow::handleMouseEvent
在这里插入图片描述
childAt的过程:
1、遍历MyWindow的子控件,找到包含了点击坐标的MyButton。
2、遍历MyButton的子控件,找到包含了点击坐标的MyEdit。
3、遍历MyEdit的子控件,没找到子控件,返回MyEdit。

第二步、控件处理事件

过程

在这里插入图片描述
流程看起来有点复杂,用文字来表示就是以下几点:
1、每个控件处理事件时会先执行qApp安装的事件过滤器,即qApp->installEventFilter安装的。然后执行自己安装的事件过滤器,即this->installEventFilter安装的,最后才是事件处理,如mousePressEvent等。
2、控件在处理事件时可以用setAccepted来设置事件是否被吸收,如果setAccepted(true),那么这个事件不会被传递到父控件中去。
3、事件处理是从子控件开始依次传递到各级父控件的。
4、事件过滤器返回true和e->setAccepted(true)都可以阻断事件往父控件传递,但在事件过滤器中设置e->setAccepted并不能阻止当前控件的事件处理。

相关源码

qapplication->QApplication::notify
在这里插入图片描述
qapplication->QApplicationPrivate::notify_helper
在这里插入图片描述

总结

Qt的事件传递大致就上述说的两步,因为要介绍里面的一些细节,所以看起没那么直观,这里写一个示意的代码来说明整个流程。
现有appFilter(obj, e)和widgetFilter(obj, e)事件过滤器,分别被qApp和各个控件安装。

void handle(systemEvent)
{
    e = toEvent(systemEvent); //转换为QEvent

    /* qApp的事件过滤 */
    if (appFilter(systemEvent.qApp, e) == true)
        return;

    w = qApp.m_widget.childAt(e.pos());  //获取MyEdit

    while (w)
    {
        /* 事件过滤 */
        if (appFilter(w, e) == true)
            break;
        if (widgetFilter(w, e) == true)
            break;

        w.event(e); //事件处理

        /* 判断事件是否被接收 */
        if (e.isAccept())
            break;

        w = w.parentWidget();
    }
}

相关的性能问题

从上面给出的例子可以看到,我们点击一个控件时,会有两个步骤。
1、Qt会先从窗口找到MyWindow,再从MyWindow找到MyButton,再从MyButton找到MyEdit。
2、找到MyEdit后,会执行MyEdit的事件过滤,事件处理,然后依次对MyButton和MyWindow做同样的操作。
这两个步骤带来了一些性能的问题。
1、找MyEdit的过程是递归的,带来了函数栈的开销。
2、如果MyEdit的父控件确实需要处理点击事件,那么多次调用事件过滤,事件处理是有必要的,但是如果传递的是绘图事件呢?当一个子控件接收到绘图事件,这个事件也会被传递给它的父控件们,而想要提升UI的性能,减少不必要的刷新是一个方向。

我们做一个测试,在MyWindow中做以下修改。
在这里插入图片描述
放置多个QFrame控件嵌套在一起。
创建一个MyButton控件,分别对比它作为frame_14和窗口的子控件时执行update的耗时。

update本质上是发送绘图事件来重回控件。

界面中的按钮绑定槽。

void MyWindow::on_pushButton_clicked()
{
    QElapsedTimer timer;
    timer.start();

    for (int i = 0; i < 1000000; ++i)
        button->update();

    qDebug() << "cost time: " << timer.elapsed() << "ms";
}

测试结果:
作为窗口子控件时:
在这里插入图片描述
作为frame_14的子控件时:
在这里插入图片描述
可以看出差别是很大的。
所以我们在设计UI架构时,应避免出现层次过多的情况。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【sentinel】热点规则详解及源码分析

何为热点&#xff1f;热点即经常访问的数据。很多时候我们希望统计某些热点数据中访问频次最高的Top K数据&#xff0c;并对其访问进行限制。 比如&#xff1a; 商品ID为参数&#xff0c;统计一段时间内最常购买的商品ID并进行限制用户ID为参数&#xff0c;针对一段时间内频繁…

【linux】init进程的详解

文章目录 概述init进程完成从内核态向用户态的转变&#xff08;1&#xff09;一个进程先后两种状态&#xff08;2&#xff09;init进程在内核态下的工作内容&#xff08;3&#xff09;init进程在用户态下的工作内容&#xff08;4&#xff09;init进程如何从内核态跳跃到用户态 …

springboot+vue高校社团管理系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的高校社团管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风…

Linux快速安装Erlang和RabbitMQ单机版

环境 CentOS7Xshell6XFtp6Erlang 21.3RabbitMQ 3.8.4 安装方式 同一个软件有很多种安装方式&#xff0c;在Linux系统有几种常见的软件安装方式&#xff1a; 源码编译安装&#xff1a;一般需要解压&#xff0c;然后使用make、make install等命令RPM&#xff08;RedHat Packa…

从物业管理到IT互联网精英,月薪11k的她几经辗转,终得偿所愿!

所谓“男怕入错行”&#xff0c;其实对女生来说也是一样&#xff0c;不同行业对人生的改变太大&#xff0c;想要找到满意的工作&#xff0c;就要不断去尝试。 西安的学员小文&#xff0c;大学毕业后从事的本专业&#xff08;物业管理&#xff09;工作&#xff0c;但不是很喜欢…

条款1:理解模板类型推导

现代C中被广泛应用的auto是建立在模板类型推导的基础上的。而当模板类型推导规则应用于auto环境时&#xff0c;有时不如应用于模板中那么直观。由于这个原因&#xff0c;真正理解auto基于的模板类型推导的方方面面非常重要。 在c中声明一个模板函数的伪代码基本如下&#xff1…

JVM 直接内存(Direct Memory)

直接内存概述 不是虚拟机运行时数据区的一部分&#xff0c;也不是<<Java 虚拟机规范>> 中定义的内存区域直接内存是Java 堆外的、直接向系统申请的内存区间来源于 NIO&#xff0c;通过存在堆中的 DirectByteBuffer 操作 Native 内存访问直接内存的速度会优于 Java…

智慧停车APP系统开发 停车取车缴费智能搞定

生活水平的提高让车辆成为很多人出行主要的代步工具&#xff0c;很多家庭现在已经不止拥有一辆汽车了&#xff0c;所以城市建设中关于停车场的规划管理也是很重要的部分。不过现在出门很多时候还是会碰到找不到停车场&#xff0c;没有车位、收费不合理、乱收费等现象。智慧停车…

调试和优化遗留代码

1. 认识调试器 1.1 含义 一个能让程序运行、暂停、然后对进程的状态进行观测甚至修改的工具。 在日常的开发当中使用非常广泛。(PHP开发者以及前端开发者除外) 1.2 常见的调试器 Go语言的自带的 delve 简写为 “dlv”GNU组织提供的 gdbPHP Xdebug前端浏览器debug 调试 1.3…

DNS投毒

定义 DNS缓存投毒又称DNS欺骗,是一种通过查找并利用DNS系统中存在的漏洞,将流量从合法服务器引导至虚假服务器上的攻击方式。与一般的钓鱼攻击采用非法URL不同的是,这种攻击使用的是合法URL地址。 DNS缓存中毒如何工作 在实际的DNS解析过程中,用户请求某个网站,浏览器首…

English Learning - L3 作业打卡 Lesson1 Day6 2023.5.10 周三

English Learning - L3 作业打卡 Lesson1 Day6 2023.5.10 周三 引言&#x1f349;句1: The expression was first used in America at the beginning of the twentieth century .成分划分弱读连读爆破语调 &#x1f349;句2: It probably comes from the fact that many babies…

分享一组有意思的按钮设计

先上效果图&#xff1a; 一共16个&#xff0c;每个都有自己不同的样式和效果&#xff0c;可以用在自己的项目中&#xff0c;提升客户体验~ 再上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&l…

非Autosar软件手动集成XCP协议栈

文章目录 前言XCP发送XCP接收Xcp初始化Xcp主函数Xcp Event总结前言 最近项目由于各种原因没有直接采用基于Autosar工具生成的代码。只使用了NXP的MCAL。Demo需求实现XCP功能。本文记录手动集成XCP协议的过程,基于CAN总线。集成的前提过程是已有了XCP的静态代码和配置代码。可…

数据结构pta第一天: 堆中的路径 【用数组模拟堆的操作】

这道题其实就涉及两个堆操作&#xff0c; 一个是插入&#xff0c;一个是通过从底到根的遍历 堆的插入&#xff1a;其实就是从下面往上&#xff0c;一个一个比较&#xff0c;&#xff08;因为上面的节点里的值越来越小&#xff0c;如果插入的值比上面的节点小那么就要向上推&am…

基于AT89C51单片机的电子时钟设计与仿真

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87779867?spm1001.2014.3001.5503 源码获取 主要内容&#xff1a; 使用DS1302芯片作为计时设备&#xff0c;用6个7段LED数码管或者LCD162作为显示设备&#xff0c…

【软考七】面向对象技术--UML、设计模式(分数重,刷题刷题)

建议UML和设计模式去听听课&#xff0c;内容多&#xff0c;还需要记。这一部分内容较多&#xff0c;下半年的考生可以慢慢看&#xff0c;上半年的就去刷题吧。 该博客不适合学习UML和设计模式&#xff0c;只适合考试。要学的不要在这浪费时间&#xff0c;切记切记 在5月13号忽然…

MD-MTSP:孔雀优化算法POA求解多仓库多旅行商问题(提供MATLAB代码,可以修改旅行商个数及起点)

一、多仓库多旅行商问题 多旅行商问题&#xff08;Multiple Traveling Salesman Problem, MTSP&#xff09;是著名的旅行商问题&#xff08;Traveling Salesman Problem, TSP&#xff09;的延伸&#xff0c;多旅行商问题定义为&#xff1a;给定一个&#x1d45b;座城市的城市集…

Midjourney8种风格极其使用场景

目录 ​编辑 引言 等距动画 场景 分析性绘图 场景 着色书 场景 信息图画 场景 双重曝光 场景 图示性绘画 场景 二维插图 场景 图解式画像 场景 总结&#xff1a; 八种风格箴言&#xff1a; 引言 我相信大家都或多或少玩过Midjourney&#xff0c;但是要形…

linux系统sed编辑器

sed编辑器 sed编辑器sed基础语法sed查询sed删除sed 替换sed 插入 sed编辑器 sed是文本处理工具&#xff0c;依赖于正则表达式&#xff0c;可以读取文本内容&#xff0c;工具指定条件对数据进行添加、删除、替换等操作&#xff0c;被广泛应用于shell脚本&#xff0c;以完成自动…

我所了解的老板

我所了解的老板 修心篇以名命物 扰我心良心的本来如此 是我心不要全挑剔别人 既是我因 受我之果长久之爱 美女养眼 贤妻养心 调研篇深度思考确定趋势确定时机预测筹划生存资料 做事篇做短视频心态&#xff0c;也是创业的心态做销售冠军的心态&#xff0c;也是创业的心态 修心篇…