QT知识整理

devtools/2024/11/29 22:08:45/

QT核心机制:元对象系统,事件模型,信号与槽

使用元对象系统需要满足三个条件:

  • 只有QObject派生类才可以使用元对象系统特性。
  • 在类声明前使用Q_OBJECT()宏来开启元对象功能。
  • 使用Moc工具为每个QObject派生类提供实现代码。

moc 全称是 Meta-Object Compiler,也就是“元对象编译器”,它主要用于处理C++源文件中的非标准C++代码。Qt 程序在交由标准编译器编译之前,先要使用 moc 分析 C++ 源文件。如果它发现在一个头文件中包含了宏 Q_OBJECT,则会生成另外一个 C++ 源文件。这个源文件中包含了 Q_OBJECT 宏的实现代码。这个新的文件名字将会是原文件名前面加上 moc_ 构成。这个新的文件同样将进入编译系统,最终被链接到二进制代码中去。因此我们可以知道,这个新的文件不是“替换”掉旧的文件,而是与原文件一起参与编译。另外,我们还可以看出一点,moc 的执行是在预处理器之前。因为预处理器执行之后,Q_OBJECT 宏就不存在了。

既然每个源文件都需要 moc 去处理,那么我们在什么时候调用了它呢?实际上,如果你使用 qmake 的话,这一步调用会在生成的 makefile 中展现出来。从本质上来说,qmake 不过是一个 makefile 生成器,因此,最终执行还是通过 make 完成的。

Moc的主要功能如下:

清理代码:Moc会删除源文件中与C++标准不符的代码,例如某些未使用的变量、类型或函数。

生成C++类和函数:Moc会将源文件中的预处理器指令和特殊C++语句转换为C++类和函数,这些类和函数可以在其他Qt模块中使用。

处理资源文件:Moc可以将源文件中的资源文件(如图像、字符串等)转换为C++类和函数,使得这些资源可以在其他Qt模块中访问。

提供扩展:Moc可以处理模板代码,从而使得代码可以根据特定的Qt模块或对象模型扩展。

清理和清理:Moc支持两次清理,第一次清理通常用于移除不需要的C++代码,第二次清理用于移除第一次清理后仍然存在的未使用的代码。

moc解析流程
1.moc查找头文件中的signals,slots,标记出信号和槽。
2.将信号槽信息存储到类静态变量staticMetaObject中,并且按声明顺序进行存放,建立索引。
3.当发现有connect连接时,将信号槽的索引信息放到一个map中彼此配对。
4.当调用emit时,调用信号函数,并且传递发送信号的对象指针,元对象指针,信号索引,参数列表到active函数
5.通过active函数找到在map中找到所有与信号对应的槽索引
6.根据槽索引找到槽函数,执行槽函数。

如何触发信号?

使用emit()来触发信号

信号与槽的具体流程。

  1. moc查找头文件中的signals,slots,标记出信号和槽。
  2. 将信号槽信息存储到类静态变量staticMetaObject中,并且按声明顺序进行存放,建立索引。
  3. 当发现有connect连接时,将信号槽的索引信息放到一个map中,彼此配对。
  4. 当调用emit时,调用信号函数,并且传递发送信号的对象指针,元对象指针,信号索引,参数列表到active函数
  5. 通过active函数找到在map中找到所有与信号对应的槽索引
  6. 根据槽索引找到槽函数,执行槽函数。

信号槽机制的优缺点:

优点:类型安全,松散耦合,灵活。

缺点:同回调函数相比,运行速度较慢。

 优点:

  1. 类型安全:需要关联的信号槽的签名必须是等同的。即信号的参数类型和参数个数同接受该信号的槽的参数类型和参数个数相同。若信号和槽签名不一致,则编译器会报错。
  2. 松散耦合:信号和槽机制减弱了Qt对象的耦合度。激发信号的Qt对象无需知道是哪个对象的那个槽接收它发出的信号,它只需要在适当的时间发送适当的信号即可,而不需要关心是否被接收和哪个对象接收了。Qt保证适当的槽得到了调用,即使关联的对象在运行时删除,程序也不会崩溃。
  3. 灵活性:一个信号可以关联多个槽,多个信号也可以关联同一个槽。

缺点:

  1. 速度较慢:与回调函数相比,信号和槽机制运行速度比直接调用非虚函数慢10倍左右。

原因:

  • 需要定位接收信号的对象。
  • 安全地遍历所有槽。
  • 编组,解组传递参数。
  • 多线程的时候,信号需要排队等候。

总结:这点性能损失对比带来的优点,完全可以接受。

为什么 new QWidget 不需要 delete

Qt提供了一种机制,能够自动、有效的组织和管理继承自QObject的Qt对象,这种机制就是对象树。 Qt库中的很多类都以QObject作为它们的基类。QObject的对象总是以树状结构组织自己。当我们创建一个QObject对象时,可以指定其父对象(也被称为父控件),新创建的对象将被加入到父对象的子对象(也被称为子控件)列表中。当父对象被析构时,这个列表中的所有子对象会被析构。不但如此,当某个QObject对象被析构时,它会将自己从父对象的列表中删除,以避免父对象被析构时,再次析构自己。

Qt connect 函数,第五个参数有以下五种:

  1. Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型。如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。
  2. Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数和信号发送者在同一线程。效果看上去就像是直接在信号发送位置调用了槽函数,效果上看起来像函数调用,同步执行。 emit语句后面的代码将在与信号关联的所有槽函数执行完毕后才被执行。
  3. Qt::QueuedConnection:信号发出后,信号会暂时被放到一个消息队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,然后执行和信号关联的槽函数,这种方式既可以在同一线程内传递消息也可以跨线程操作。 emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕
  4. Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。而且接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。
  5. Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是为了避免重复连接。

http://www.ppmy.cn/devtools/138023.html

相关文章

NLP信息抽取大总结:三大任务(带Prompt模板)

信息抽取大总结 1.NLP的信息抽取的本质?2.信息抽取三大任务?3.开放域VS限定域4.信息抽取三大范式?范式一:基于自定义规则抽取(2018年前)范式二:基于Bert下游任务建模抽取(2018年后&a…

Flink--API 之 Source 使用解析

目录 一、Flink Data Sources 分类概览 (一)预定义 Source (二)自定义 Source 二、代码实战演示 (一)预定义 Source 示例 基于本地集合 基于本地文件 基于网络套接字(socketTextStream&…

IDEA 2024 Maven 设置为全局本地仓库,避免新建项目重新配置maven

使用idea创建Java项目时每次都要重新配置Maven,非常麻烦。其实IDEA可以配置全局Maven。方法如下: 1.关闭所有项目进入初始页面 2.选择所有配置 3.设置为自己的路径

C/C++绘制爱心

系列文章 序号直达链接1C/C爱心代码2C/C跳动的爱心3C/C李峋同款跳动的爱心代码4C/C满屏飘字表白代码5C/C大雪纷飞代码6C/C烟花代码7C/C黑客帝国同款字母雨8C/C樱花树代码9C/C奥特曼代码10C/C精美圣诞树11C/C俄罗斯方块12C/C贪吃蛇13C/C孤单又灿烂的神-鬼怪14C/C闪烁的爱心15C/…

漏洞管理与补丁管理详解:系统安全的基石

文章目录 漏洞管理与补丁管理详解:系统安全的基石什么是漏洞管理?什么是补丁管理?漏洞管理与补丁管理的联系与区别实施漏洞管理与补丁管理的最佳实践 漏洞管理与补丁管理详解:系统安全的基石 在网络安全的防护体系中,…

使用 Nginx 在 Ubuntu 22.04 上安装 LibreNMS 开源网络监控系统

#LibreNMS 是一个功能强大的开源网络监控系统,它能够为你的网络性能和设备提供全面的监控。本文将引导你通过一系列步骤,在 Ubuntu 22.04 服务器上安装和配置 LibreNMS,使用 Nginx 作为 Web 服务器。 简介 LibreNMS 提供了对网络设备和性能…

使用NAS开启无纸化办公,Docker部署开源文档管理系统『Paperless-ngx』

使用NAS开启无纸化办公,Docker部署开源文档管理系统『Paperless-ngx』 哈喽小伙伴们好,我是Stark-C~ 对于文案类的办公场景来说,手头堆放最多的可能就是各种文档文件,以及各种用过的打印废纸。 这么多年来,不管是领…

SAP开发语言ABAP开发入门

1. 了解ABAP开发环境和基础知识 - ABAP简介 - ABAP(Advanced Business Application Programming)是SAP系统中的编程语言,主要用于开发企业级的业务应用程序,如财务、物流、人力资源等模块的定制开发。 - 开发环境搭建 - 首先需…