Qt基础之四:Qt信号与槽机制原理及优缺点

news2024/10/5 12:59:38

信号和插槽用于对象之间的通信。信号和槽机制是Qt的核心特性,可能也是与其他框架提供的特性最大不同的部分。Qt的元对象系统使信号和槽成为可能。

一.简介

在GUI编程中,当我们改变一个控件,通常希望其他控件被通知到。更一般的,我们希望任意对象之间能够通信。例如,如果我们点击了“关闭”按钮,我们希望窗口的close()函数被调用。
其他工具包使用回调来实现这种通信。回调函数是一个指向函数的指针,所以如果你想要一个处理函数通知你一些事件,你可以将一个指向另一个函数(回调函数)的指针传递给处理函数。处理函数然后在适当的时候调用回调函数。但回调可能不太直观,而且在确保回调参数的类型正确性方面可能会遇到问题。

二.信号和槽

在Qt中,我们有一个回调技术的替代方案:我们使用信号和槽。当特定事件发生时发出信号。Qt的小部件有许多预定义的信号,但是我们总是可以子类化小部件,添加一些自定义信号。槽(slots)是响应特定信号(signals)而调用的函数。Qt的小部件有许多预定义的槽,但是通常的做法是子类化控件并自定义槽函数,这样就可以处理感兴趣的信号。
下图为信号与槽的关系图:支持一对多,多对一


1.信号和槽机制是类型安全的
信号与槽机制要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,信号的参数可以比槽函数的参数多,此时槽可以忽略多余参数。由于参数的一致性,所以当使用基于函数指针的语法时,编译器可以帮助我们检测类型是否匹配;基于字符串的信号和槽语法将在运行时检测类型不匹配。
2.信号和槽是松散耦合的
信号和槽是松散耦合的,发出信号的类既不知道也不关心哪个槽接收信号。Qt的信号和槽机制确保,如果您将信号连接到时隙,将在正确的时间使用信号的参数调用该槽。信号和槽可以采用任意数量的任何类型的参数。它们完全是类型安全的。
从QObject或其子类(例如QWidget)继承的所有类都可以包含信号和槽。当对象的状态发生变化时,它们会发出信号,它不知道或不关心是否有任何槽在接收它发出的信号,这足以实现信息封装。
槽可以用于接收信号,但它们也是正常的成员功能。就像一个对象不知道是否有任何其他对象接收到它的信号一样,槽也不知道它是否有任何信号连接到它。这确保了可以使用Qt创建真正独立的组件。
您可以将任意多个信号连接到一个槽,并且可以将信号连接到任意多个槽。甚至可以将一个信号直接连接到另一个信号。(每当发出第一个信号时,这将立即发出第二个信号。)
信号和槽共同构成了强大的组件编程机制。

三.信号(signals)

当对象内部状态以对象的客户端或用户感兴趣的某种方式发生变化时—比如点击、鼠标移动等,对象就会发出信号。信号(signals)都是共有(public)的,可以从任何地方发出,但最好只从该定义信号的类及其子类使用该信号。当信号发出时,通常采用直连方式连接槽函数,这种连接方式会立即执行槽函数,就像普通的函数调用一样。此时信号和槽机制完全独立于任何GUI事件循环。一旦所有的槽都返回,emit语句之后的代码就会执行(同步发送)。当使用队列连接时,情况略有不同;在这种情况下,emit关键字后面的代码将立即继续,槽将稍后执行(异步发送)。如果多个槽连接到一个信号,当信号发出时,槽将按照它们连接的顺序依次执行。信号是由moc(元对象编译器)自动生成的,在build目录中的moc_**文件中。信号永远不能有返回类型(即使用void)。

四.槽(slots)

槽在信号发出时被调用。slot也是C++函数,可以像普通函数一样正常调用,它们唯一的特点是可以连接信号。因为槽函数是普通的成员函数,所以当直接调用时,它们遵循普通的C++规则。与回调相比,信号和槽稍微慢一些,因为它们提供了更大的灵活性,尽管实际应用程序中的差异并不大。一般来说,emit一个连接到一些槽的信号,大约比直接调用非虚函数慢十倍。原因是在定位连接对象、安全遍历所有连接(即检查在发送过程中后续槽函数是否被销毁)等所需的开销。虽然十个非虚函数调用可能听起来很多,但它的开销比任何new或delete操作都要小得多。一旦在后续执行需要new或delete的字符串、vector or list等操作,信号和槽开销只占整个函数调用开销的很小一部分。信号和槽机制的简单性和灵活性是非常值得的,用户甚至不会注意到这些开销。
注意,当定义了signals或slots变量的第三方库与基于qt的应用程序一起编译时,可能会导致编译器警告和错误。要解决这个问题,请#undef有问题的预处理器符号

五.在Qt中使用第三方的Signals和Slots

可以将Qt与第三方信号/槽机制一起使用。你甚至可以在同一项目中使用这两种机制。只需将以下行添加到qmake项目(.pro)文件中。

CONFIG += no_keywords

它告诉Qt不要定义moc关键字signals、slot和emit,因为这些名称将由第三方库使用,例如Boost。然后,要继续使用带有no_keywords标志的Qt信号和时隙,只需将源代码中Qt-moc所使用的关键字替换为相应的Qt宏Q_SIGNALS(或Q_SIGNAL)、Q_SLOTS(或Q-SLOT)和Q_EMIT。
在需要信号发送方信息的情况下,Qt提供了QObject::sender()函数,它返回一个指向发送信号的对象的指针。如下所示:

void MyWidget::on_pushButton_clicked()
{
    QPushButton *button = static_cast<QPushButton*>(QObject::sender());
    qDebug() << button->text(); 
}

以上内容参考:https://doc.qt.io/qt-5/signalsandslots.html
总结一下:
1.优点
①类型安全。需要关联的信号槽的签名必须是等同的。即信号的参数类型和参数个数同接受该信号的槽的参数类型和参数个数相同。若信号和槽签名不一致,编译器会报错。
②松散耦合。信号和槽机制减弱了Qt对象的耦合度。发送信号的Qt对象无需知道是那个对象的那个信号槽接收它发出的信号,它只需在适当的时间发送适当的信号即可。Qt可以保证了适当的槽得到了调用,即使关联的对象在运行时被删除。程序也不会奔溃。
③灵活性。一个信号可以关联多个槽,或多个信号关联同一个槽。
2.缺点
速度较慢。与回调函数相比,信号和槽机制运行速度比直接调用非虚函数慢10倍。
原因:
①需要定位接收信号的对象。
②安全地遍历所有关联槽。
③编组、解组传递参数。
④多线程的时候,信号需要排队等待。
然而,与创建对象的new操作及删除对象的delete操作相比,信号和槽的运行代价只是他们很少的一部分。信号和槽机制导致的这点性能损耗,对实时应用程序是可以忽略的。

原文链接:Qt基础之四:Qt信号与槽机制原理及优缺点_草上爬的博客-CSDN博客

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

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

相关文章

【优化覆盖】基于matlab果蝇算法求解无线传感器覆盖优化问题【含Matlab源码 2215期】

一、⛄果蝇算法 果蝇优化算法(Fruit Fly Optimization Algorithm, FOA) 是台湾学者潘文超经过研究发现, 并于2011年提出的一种新型智能优化算法, 它具有很好的全局优化性能, 能够解决很多的优化求解问题.果蝇有着优于其它生物的感官知觉, 特别是视觉与嗅觉, 依靠灵敏的嗅觉, 果…

Linux服务器被入侵后的排查思路(应急响应思路)

目录Linux-暴力破解、替换ps命令并留存后门事件复现一、事件背景二、应急响应过程排查crontab后门排查是否有命令被替换响应过程回顾三、事件还原查看后门排查安全日志Linux-暴力破解、替换ps命令并留存后门事件复现 一、事件背景 服务器疑似被入侵&#xff0c;与恶意IP进行通信…

手眼标定笔记

文章目录基本介绍&#xff1a;坐标系变换运算规则&#xff1a;关系运算说明&#xff1a;坐标系运算规则一&#xff1a;坐标系运算规则二&#xff1a;齐次坐标系&#xff1a;齐次坐标系下的坐标变换&#xff1a;眼在手外&#xff1a;眼在手内&#xff1a;解方程&#xff1a;- Ta…

Spring学习第4篇:Spring 的依赖注入

大家家好&#xff0c;我是一名网络怪咖&#xff0c;北漂五年。相信大家和我一样&#xff0c;都有一个大厂梦&#xff0c;作为一名资深Java选手&#xff0c;深知Spring重要性&#xff0c;现在普遍都使用SpringBoot来开发&#xff0c;面试的时候SpringBoot原理也是经常会问到&…

数据结构 | 单链表

… &#x1f333;&#x1f332;&#x1f331;本文已收录至&#xff1a;数据结构 | C语言 更多知识尽在此专栏中!文章目录&#x1f333;前言&#x1f333;正文&#x1f332;链表打印与销毁&#x1fab4;打印&#x1fab4;销毁&#x1f332;尾部插入与删除&#x1fab4;节点申请&…

javaweb JAVA JSP销售系统购物系统jsp购物系统购物商城系统源码(jsp电子商务系统)网上在线销售

JSP销售系统购物系统jsp购物系统购物商城系统源码&#xff08;jsp电子商务系统&#xff09;网上在线销售

Linux基础 - 虚拟化介绍(KVM)

‍‍&#x1f3e1;博客主页&#xff1a; Passerby_Wang的博客_CSDN博客-系统运维,云计算,Linux基础领域博主 &#x1f310;所属专栏&#xff1a;『Linux基础』 &#x1f30c;上期文章&#xff1a; Linux基础 - 服务管理&#xff08;systemd&#xff09; &#x1f4f0;如觉得博…

爬取医药卫生知识服务系统的药品数据——超详细流程

爬取医药卫生知识服务系统的药品数据——超详细流程 文章目录爬取医药卫生知识服务系统的药品数据——超详细流程前言一、寻找药品数据二、爬取药品ID1.资源获取2.数据提取3.资源保存4.主函数5.总体代码三、爬取药品信息1.加载资源ID2.获取数据3.数据提取4.保存信息5.主函数6.总…

SpringBoot-属性绑定和bean属性校验

目录 属性绑定 自定义类属性绑定 第三方bean属性匹配 规则:松散绑定&#xff08;宽松绑定&#xff09; Bean属性校验 属性绑定 属性绑定&#xff1a;我们可以使用配置文件对类的属性进行赋值绑定。 自定义类属性绑定 我们自定义一个类&#xff0c;在此使用yml文件进行类…

【滤波器】基于matlab实现微波带低通高通带通滤波器设计

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

python科研做图系列之雷达图

文章目录参考资料matplotlib库画的复现一个 pyecharts的雷达图尝试在上面的基础上&#xff0c;把pyecharts 导出存为一般的png图尝试在上面的基础上&#xff0c;把pyecharts 导出存为一般的矢量图用pygal画雷达图参考资料 参考知乎 CSDN给出了一些参数 matplotbib库雷达图官网 …

Python实现九九乘法表的几种方式,入门必备案例~超级简单~

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 们在学习Python的过程中需要不断的积累和练习&#xff0c;这样才能够走的更远&#xff0c; 今天一起来学习怎么用Python写九九乘法表~ 第一种方法&#xff1a;for-for 代码&#xff1a; for i in range(1, 10):for j in…

数据挖掘面试经总结【私人版,仅供参考】

1特征归一化 1.1为什么需要对数值类型的特征做归一化&#xff1f; 线性函数归一化零均值归一化 1.2在对数据进行预处理时&#xff0c;应该怎样处理类别型特征&#xff1f; 序号编码独热编码二进制编码 1.3什么是组合特征&#xff1f;如何处理高维组合特征&#xff1f; 例…

【python】云打印实现

这两天为了实现云打印功能找了很多相关的文章 记录一下这一篇&#xff0c;python云打印实现-朝花夕拾&#xff0c;代码通过监听文件夹有无产生新文件来判断是否执行&#xff0c;我尝试运行了下没问题&#xff0c;于是打算转载一下 程序运行结果 由于对方的代码和我实现的有点出…

【Maven】你好,Maven >>> 与Maven的初次见面~

个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的道路上摸爬滚打&#xff0c;记录学习的过程~ 与Maven的初次见面~一、了解Maven二、Maven的…

Flink双流join导致数据重复

大家都知道flink sql 中 left join 数据不会互相等待&#xff0c;存在 retract 问题&#xff0c;会导致写入 kafka 的数据量变大&#xff0c;就会导致出现数据重复的问题。 举例&#xff1a;即常见的曝光日志流&#xff08;show_log&#xff09;通过 log_id 关联点击日志流&am…

SQL:数据去重的三种方法

1、使用distinct去重 distinct用来查询不重复记录的条数&#xff0c;用count(distinct id)来返回不重复字段的条数。用法注意&#xff1a; distinct【查询字段】&#xff0c;必须放在要查询字段的开头&#xff0c;即放在第一个参数&#xff1b;只能在SELECT 语句中使用&#…

spring整合fastdfs客户端

解决Dependency ‘com.github.tobato:fastdfs-client:1.27.2’ not found 错误问题。 一、 将fastdfs客户端git下来 git https://github.com/happyfish100/fastdfs-client-java.gitcd fastdfs-client-java然后将fastdfs-client-java构建到本地maven仓库 mvn clean install&…

Pandas的数据结构

Pandas的数据结构 处理CSV 文件 CSV&#xff08;Comma-Separated Values&#xff0c;逗号分隔值&#xff0c;有时也称为字符分隔值&#xff0c;因为分隔字符也可以不是逗号&#xff09;&#xff0c;其文件以纯文本形式存储表格数据&#xff08;数字和文本&#xff09;。 Pan…

【强化学习】深入浅出强化学习--机器人找金币

文章目录Grid_mdp.py定义和初始化从环境状态构建观测值ResetStepRenderingClose注册环境参考文章Grid_mdp.py 定义和初始化 首先自定义环境&#xff0c;自定义的环境将继承gym.env环境。在初始化的时候&#xff0c;可以指定环境支持的渲染模式&#xff08;例如human,rgb_arra…