【从零开始学习QT】信号和槽

news2025/6/5 6:02:16

目录

一、信号和槽概述

信号的本质

槽的本质

二、信号和槽的使用

2.1 连接信号和槽

2.2 查看内置信号和槽

2.3 通过 Qt Creator 生成信号槽代码

自定义槽函数

自定义信号

自定义信号和槽

2.4 带参数的信号和槽

三、信号与槽的连接方式

3.1 一对一

(1)一个信号连接一个槽

(2)一个信号连接另一个信号

3.2 一对多

3.3 多对一

四、信号与槽的连接

五、使用 Lambda 表达式定义槽函数


QT专栏:QT_uyeonashi的博客-CSDN博客

一、信号和槽概述

在 Qt 中,用户和控件的每次交互过程称为一个事件。比如 "用户点击按钮" 是一个事件,"用户关闭窗口" 也是一个事件。每个事件都会发出一个信号,例如用户点击按钮会发出 "按钮被点击" 的信号,用户关闭窗口会发出 "窗口被关闭" 的信号。

Qt 中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到 "按钮被点击" 的信号后,会做出 "关闭自己" 的响应动作;再比如输入框自己接收到 "输入框被点击" 的信号后,会做出 "显示闪烁的光标,等待用户输入数据" 的响应动作。在 Qt 中,对信号做出的响应动作就称之为槽

信号和槽是 Qt 特有的消息传输机制,它能将相互独立的控件关联起来。比如,"按钮" 和 "窗口"
本身是两个独立的控件,点击 "按钮" 并不会对 "窗口" 造成任何影响。通过信号和槽机制,可以将 "按钮" 和 "窗口" 关联起来,实现 "点击按钮会使窗口关闭" 的效果。

信号的本质

信号是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时 Qt 对
应的窗口类会发出某个信号,以此对用户的操作做出反应。因此,信号的本质就是事件。如:
• 按钮单击、双击
• 窗口刷新
• 鼠标移动、鼠标按下、鼠标释放
• 键盘输入

那么在 Qt 中信号是通过什么形式呈现给使用者的呢?
• 我们对哪个窗口进行操作, 哪个窗口就可以捕捉到这些被触发的事件。
• 对于使用者来说触发了一个事件我们就可以得到 Qt 框架给我们发出的某个特定信号。
信号的呈现形式就是函数, 也就是说某个事件产生了, Qt 框架就会调用某个对应的信号函数, 通知使用者。

槽的本质

槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般的 C++ 函数是一样的,可以定义在类的任何位置( public、protected 或 private ),可以具有任何参数,可以被重载,也可以被直接调用(但是不能有默认参数)。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

说明
(1)信号和槽机制底层是通过函数间的相互调用实现的。每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数。例如: "按钮被按下" 这个信号可以用 clicked() 函数表示,"窗口关闭" 这个槽可以用 close() 函数表示,假如使用信号和槽机制-

实现:"点击按钮会关闭窗口" 的功能,其实就是 clicked() 函数调用 close() 函数的效果。

(2)信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:
• 信号函数用 signals 关键字修饰,槽函数用 public slots、protected slots 或者 private slots 修饰。signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数;
• 信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。

二、信号和槽的使用

2.1 连接信号和槽

在 Qt 中,QObject 类提供了一个静态成员函数 connect() ,该函数专门用来关联指定的信号函数和槽函数。

QObject 是 Qt 内置的父类. Qt 中提供的很多类都是直接或者间接继承自 QObject

connect() 函数原型:

connect (const QObject *sender,
        const char * signal ,
        const QObject * receiver ,
        const char * method ,
        Qt::ConnectionType type = Qt::AutoConnection )

代码示例: 在窗口中设置一个按钮,当点击 "按钮" 时关闭 "窗口" 

2.2 查看内置信号和槽

系统自带的信号和槽通常是通过 "Qt 帮助文档" 来查询

如上述示例,要查询 "按钮" 的信号,在帮助文档中输入:QPushButton,
• 首先可以在 "Contents" 中寻找关键字 signals,
• 如果没有找到, 继续去父类中查找. 因此我们去他的父类 QAbstractButton 中继续查找关键字signals

这里的 clicked() 就是要找的信号。槽函数的寻找方式和信号一样,只不过它的关键字是 slot 。

2.3 通过 Qt Creator 生成信号槽代码

Qt Creator 可以快速帮助我们生成信号槽相关的代码.

自定义槽函数

所谓的slot就是一个普通的成员函数

自定义一个槽函数,操作过程和自定义一个普通的成员函数,没啥区别

第一种方式:一个简单的代码

第二种方式:

  -> 

QT Creator 直接给我们生成好了一个函数;

在 "widget.h" 头文件中自动添加槽函数的声明;在 "widget.cpp" 中自动生成槽函数定义.

自定义信号

Qwidget :咱们的Widget虽然还没有定义任何信号,由于继承自QWidget和QObject这两类已经提供了一些信号量可以直接使用

所谓的QT信号,本质上也是一个“函数”,Qt 5及更高版本中,槽函数和普通成员函数之间,没啥区别

1. 信号是一类非常特殊的函数,程序员只需要写出函数声明,并告诉Qt这是一个信号即可。这个函数的定义是Qt在编译过程中自动生成的(自动生成的过程,程序员无法干预)

信号在Qt中是特殊的机制,Qt生成的信号函数实现要配合Qt框架做很多既定的操作

2. 作为信号函数,这个函数的返回值必须是void,有没有函数都可以,甚至也可以支持重载

signals:这个也是Qt自己扩展出来的关键字~

qmake的时候调用一些代码的分析/生成工具,扫描到类中包含signals这个关键字的时候,此时就会自动把下面的函数声明认为是信号,并且把这些信号函数自动的生成函数定义

举个栗子:

我们运行之后发现并窗口没有变化

这里qt提供了一个关键字emit,使用 "emit" 关键字发送信号


自定义信号和槽

2.4 带参数的信号和槽

Qt 的信号和槽也支持带有参数, 同时也可以支持重载.
此处我们要求, 信号函数的参数列表要和对应连接的槽函数参数列表一致.
此时信号触发, 调用到槽函数的时候, 信号函数中的实参就能够被传递到槽函数的形参当中.

传参可以起到复用代码的效果;有多个逻辑,逻辑上基本整体一致,但是涉及到的数据不同

就可以通过函数-参数来复用代码,并且在不同的场景中传入不同的参数即可~

举个栗子:

注意:带有参数的信号,要求信号的参数和槽的参数要一致;类型要一直,参数个数要满足信号的参数个数要多于槽的参数个数


三、信号与槽的连接方式

3.1 一对一

主要有两种形式,分别是:一个信号连接一个槽 一个信号连接一个信号

(1)一个信号连接一个槽

举个栗子:

1、在 "widget.h" 中声明信号和槽以及信号发射函数;

2、在 "widget.cpp" 中实现槽函数,信号发射函数以及连接信号和槽;

(2)一个信号连接另一个信号

举个栗子:

在上述示例的基础上,在 "widget.cpp" 文件中添加如下代码:

3.2 一对多

一个信号连接多个槽

举个栗子:

(1)在 "widget.h" 头文件中声明一个信号和三个槽;

(2)在 "widget.cpp" 文件中实现槽函数以及连接信号和槽;

3.3 多对一

多个信号连接一个槽函数

举个栗子:

(1)在 "widget.h" 头文件中声明两个信号以及一个槽;

(2)在 "widget.cpp" 文件中实现槽函数以及连接信号和槽;

四、信号与槽的连接

如果没有disconnect,就会构成一个信号绑定了两个槽函数,触发信号的时候就会两个槽函数都执行

使用disconnect来断开信号的连接,disconnect的使用方式和connect是非常类似的

五、使用 Lambda 表达式定义槽函数

Lambda表达式 的语法格式如下:

[ capture ] ( params ) opt -> ret {
Function body;
};

说明: 

举个栗子:

注意:

lambda为了解决上述问题,引入了“变量捕获”,通过变量捕获,获取到外层作用域中的变量,即将变量名称写到[ ]中

如过变量特别多课以写成[=],这个写法的含义就是把上层作用域中所有的变量名都给捕获进来!

注意lambda在捕获的时候一定要保证对象是可用的(注意生命周期)


总结:信号与槽的优缺点

优点: 松散耦合

信号发送者不需要知道发出的信号被哪个对象的槽函数接收,槽函数也不需要知道哪些信号关联了自己,Qt的信号槽机制保证了信号与槽函数的调用。支持信号槽机制的类或者父类必须继承于 QObject类。

缺点: 效率较低

与回调函数相比,信号和槽稍微慢一些,因为它们提供了更高的灵活性,尽管在实际应用程序中差别不大。通过信号调用的槽函数比直接调用的速度慢约10倍(这是定位信号的接收对象所需的开销;遍历所有关联;编组/解组传递的参数;多线程时,信号可能需要排队),这种调用速度对性能要求不是非常高的场景是可以忽略的,是可以满足绝大部分场景。


本篇完!

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

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

相关文章

MCP调研

什么是 MCP MCP(Model Context Protocol,模型上下文协议),是由 Anthropic 在 2024 年 11 月底推出的开放标准协议,旨在统一大型语言模型(LLM)与外部数据源、工具的通信方式。MCP 的主要目的在于…

TDengine 运维——巡检工具(定期检查)

背景 TDengine 在运行一段时间后需要针对运行环境和 TDengine 本身的运行状态进行定期巡检,本文档旨在说明如何使用巡检工具对 TDengine 的运行环境进行自动化检查。 安装工具使用方法 工具支持通过 help 参数查看支持的语法 Usage: taosinspect [OPTIONS]Check…

qwen 2.5 并行计算机制:依靠 PyTorch 和 Transformers 库的分布式能力

qwen 2.5 并行计算机制:依靠 PyTorch 和 Transformers 库的分布式能力 完整可运行代码: import torch import torch.nn.functional as F from transformers

MSTNet:用于糖尿病视网膜病变分类的多尺度空间感知 Transformer 与多实例学习方法|文献速递-深度学习医疗AI最新文献

Title 题目 MSTNet: Multi-scale spatial-aware transformer with multi-instance learning for diabetic retinopathy classification MSTNet:用于糖尿病视网膜病变分类的多尺度空间感知 Transformer 与多实例学习方法 01 文献速递介绍 糖尿病视网膜病变&#…

docker运行程序Killed异常排查

问题描述 我最近开发了一个C 多线程程序,测试没有问题,封装docker测试也没有问题,然后提交给客户了,然后在他那边测试有问题,不定时、不定位置异常中断,以前一直认为只要封装了docker就万事大吉&#xff0…

Excel 批量下载PDF、批量下载考勤图片——仙盟创梦IDE

在办公场景中,借助应用软件实现 Excel 批量处理考勤图片、电子文档与 PDF,具有诸多显著优势。 从考勤图片处理来看,通过 Excel 批量操作,能快速提取图片中的考勤信息,如员工打卡时间、面部识别数据等,节省…

PCIe-Error Detection(一)

下表为PCIe协议中给出的错误: 一、可纠正错误(Correctable Errors,8种)​​ ​​检错机制​​ ​​错误名称​​​​检测层级​​​​触发条件​​​​Receiver Error​​Physical接收端均衡器(EQ)监测到…

向量空间的练习题目

1.考虑 中的向量x1 和x2 求每一向量的长度 令x3x1x2,求x3的长度,它的长度与x1和x2的和有什么关系? 2.重复练习1,取向量 3.令C为复数集合,定义C上的加法为 (abi)(cdi)(ac)(bd)i 并定义标量乘法为对所有实数a (abi) a bi 证明&…

Leetcode 2123. 使矩阵中的 1 互不相邻的最小操作数

1.题目基本信息 1.1.题目描述 给你一个 下标从 0 开始 的矩阵 grid。每次操作,你可以把 grid 中的 一个 1 变成 0 。 如果一个矩阵中,没有 1 与其它的 1 四连通(也就是说所有 1 在上下左右四个方向上不能与其他 1 相邻)&#x…

MySQL高可用集群

https://dev.mysql.com/doc/mysql-shell/8.4/en/mysql-innodb-cluster.html 1 什么是MySQL高可用集群 MySQL高可用集群:MySQL InnoDB ClusterInnoDB Cluster是MySQL官方实现高可用读写分离的架构方案,包含以下组件 MySQL Group Replication:简…

day14 leetcode-hot100-27(链表6)

21. 合并两个有序链表 - 力扣(LeetCode) 1. 暴力法 思路 创建一个空节点,用来组装这两个链表,谁小谁就是下一个节点。 知识 创建空节点:ListNode n1 new ListNode(-1); 具体代码 /*** Definition for singly-l…

YOLOv5 :训练自己的数据集

- **🍨 本文为[🔗365天深度学习训练营](https://mp.weixin.qq.com/s/rnFa-IeY93EpjVu0yzzjkw) 中的学习记录博客** - **🍖 原作者:[K同学啊](https://mtyjkh.blog.csdn.net/)** 我们接着上一篇文章配置完YOLOv5需要的环境后&#…

flutter项目迁移空安全

重中之重 备份好项目文件,甚至连已经加载好的flutter库也可以备份。环境包升级 2.1 不要直接换成flutter:3.0以上的版本,这样做既有基本的库兼容问题,又有空安全下的语法问题(整个项目中需要增加 late、?、!的语法错误,一片报错的…

MySql(十二)

目录 MySql约束 1.添加主键约束 语法格式 1)创建一个带主键的表 查看表结构 2)创建表的时候指定主键名称 查看表结构 3)创建一个表然后,然后再使用alter为列添加主键 查看表结构 4)为表添加数据 1---正常数据 2---主键…

51c视觉~3D~合集3

我自己的原文哦~ https://blog.51cto.com/whaosoft/13954440 #SceneTracker 在4D时空中追踪万物!国防科大提出首个长时场景流估计方法 本篇分享 TPAMI 2025 论文​​SceneTracker: Long-term Scene Flow Estimation Network​​,国防科大提出首…

【2025年电工杯数学建模竞赛A题】光伏电站发电功率日前预测问题+完整思路+paper+源码

本人7年数学建模竞赛经验,历史获奖率百分之百。团队成员都是拿过全国一等奖的硕博,有需要数模竞赛帮助的可以私信我 本题主要涉及数据预测,数据分析,机器学习,时间序列等知识 1.问题背景与问题描述 2.解题思路分析 …

OpenCv高阶(十九)——dlib关键点定位

文章目录 一、什么是人脸关键点定位?二、关键点模型的下载及关键信息的理解三、dlib关键点定位的简单实现(1)导入必要的库(2)从指定路径读取图像文件(3)创建dlib的正面人脸检测器对象&#xff0…

BUUCTF之[ACTF2020 新生赛]BackupFile

打开环境就一句话 找出源文件! 结合题目名字&#xff1a;BackupFile 先用dirsearct扫描网站文件 发现一个index.php.bak ,拼接url下载 打开发现php代码 <?php include_once "flag.php";if(isset($_GET[key])) {$key $_GET[key];if(!is_numeric($key)) {exit…

头歌之动手学人工智能-Pytorch 之autograd

目录 第1关&#xff1a;Variable 任务描述 编程要求 测试说明 没有伟大的愿望&#xff0c;就没有伟大的天才。——巴尔扎克开始你的任务吧&#xff0c;祝你成功&#xff01; 第2关&#xff1a;Variable 属性 任务描述 编程要求 测试说明 真正的科学家应当是个幻想家&a…

Kafka集成Flume/Spark/Flink(大数据)/SpringBoot

Kafka集成Flume Flume生产者 ③、安装Flume&#xff0c;上传apache-flume的压缩包.tar.gz到Linux系统的software&#xff0c;并解压到/opt/module目录下&#xff0c;并修改其名称为flume Flume消费者 Kafka集成Spark 生产者 object SparkKafkaProducer{def main(args:Array[S…