QT->信号与槽详解下(概述、使用、自定义、连接方式、其他说明)

一、自定义信号和槽

1、基本语法

在Qt中,允许自定义信号的发送接收方以及接收方,即可以自定义信号函数和槽函数。但是对于自定义信号的信号函数和槽函数有一定的书写规则。

Qt中如果要让某个类能够使用信号槽(可以在类中定义信号和槽函数),则必须要在类最开始的地方写下Q_OBJECT宏(这个宏可以展开很多代码)。如果不加上这个宏,那么编译的时候就会报错。这个宏不需要我们自己手动添加,一般Qt create会帮助我们自动生成

(1)自定义信号函数书写规范

自定义信号在实际开发中很少需要用到,Qt内置的信号就足以应付大部分的开发场景

所谓Qt的信号,本质上也就是一个函数,在Qt5以及更高的版本中,槽函数和普通的成员函数之间没有什么差别。但是,信号是一类非常特殊的函数,我们只要写出函数声明,并告诉Qt这是一个信号即可。这个函数的定义是Qt在编译过程中自动生成的

1、自定义信号函数必须写到"signals"下

2、返回值为void,只需要声明,不需要实现

3、可以有参数,也可以发送重载

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

(2)自定义槽函数书写规范

所谓的自定义一个槽函数,其操作规律和自定义一个普通成员函数没有什么区别

1、早期的Qt版本要求槽函数必须写到"public slots"下,但是现在高级版本的Qt允许写到类的"public"作用域中或者全局下

2、返回值为void,需要声明,也需要实现

3、可以有参数,可以发生重载

槽声明的两种写法:

此处的slots是Qt自己扩展的关键字,不是C++标准中的写法。qmake构建Qt项目时,就会调用专门的扫描器,扫描代码中特定的关键字(比如slots),基于关键字自动生成一大堆相关代码

(3)发送信号

使用**"emit"**关键字发送信号。"emit"是一个空的宏。"emit"其实是可选的,没有什么含义,只是为了提醒开发人员

(4)示例

A.一

a.在widget.h中声明自定义的信号和槽

b.在widget.cpp中实现槽函数,并且关联信号和槽

首先关联信号和槽,一旦检测到信号发送之后就会立刻执行关联的槽函数。反之,若先发射信号,此时还没有关联槽函数,当信号发射之后槽函数就不会响应

B.二------当老师说"上课了",学生们就"回到座位,开始学习"

在源文件中新建两个类,一个是老师类,一个是学生类:首先选中项目名称,鼠标右键------>"add new..."

点击 add new 之后,出现如下界面

选择"choose"出现如下界面

注意:在Qt中新建类时,要选择新建类的父类

显然,当前项目中还没有什么类适合做新类的父类,同时新的类也不是一个"窗口"或者"控件",这种请款一般选择QObject作为基类。这样做的好处是这个新类的对象可以搭配Qt的对象树机制,便于对象的正确释放

选择"下一步",出现如下见面

对于"学生类"以上述同样的方式进行添加,添加完成之后,项目目录新增文件如下:

在 student.h 中声明槽函数:

在 widget.h 中实例化 "老师类对象" 和 "学生类对象":

在 student.cpp 中实现槽函数:

在 widget.cpp 中连接自定义信号和槽:

运行结果如下图所示:

C. 三 ------ 老师点击 "按钮" 触发学生上课

运行结果如下图所示:

2、带参数的信号和槽

Qt的信号槽也支持带有参数,同时也可以支持重载。要求:信号函数的参数列表要和对应连接的槽函数参数列表一致。(一致主要是要求类型,个数如果不一致也可以,但要求信号的参数个数比槽的参数个数多)

此时信号触发,调用到槽函数的时候,信号函数中的实参就能够被传递到槽函数的形参中。通过这样的机制就可以让信号给槽传递数据了

(1)重载信号槽

A. 在 "widget.h" 头文件中声明重载的信号函数以及重载的槽函数

B. 在 "Widget.cpp" 文件实现重载槽函数以及连接信号和槽

C. 执行结果

(2)信号槽参数列表匹配规则

A. 在 "widget.h" 头文件中声明信号和槽函数

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

其实信号的参数个数可以多于槽函数的参数个数,但是槽的参数个数不能多于信号参数个数。但是实际开发中最好还是保持参数个数也能匹配⼀致。

(3)信号的参数个数多于槽函数的参数个数

A. 在 "widget.h" 头文件中声明信号和槽函数

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

二、信号与槽的连接方式

1、一对一

主要有两种形式,分别是

1、一个信号连接一个槽

2、一个信号连接一个信号

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

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

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

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

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

2、一对多

一个信号连接多个槽:

在 "widget.h" 头文件中声明一个信号和三个槽:

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

3、多对一

多个信号连接一个槽函数

在 "widget.h" 头文件中声明两个信号以及一个槽:

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

4、多对多

多个信号连接多个槽函数:

在 "widget.h" 头文件中声明三个信号以及三个槽:

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

实际上,随着程序员经验越来越多,在GUI开发的过程中,"多对多"其实是个"伪需求",实际开发会很少用到,绝大部分情况来说,"一对一"就够用了

信号槽存在的意义:

  • 解耦合(写代码追求"高内聚,低耦合")
  • 多对多(非常类似于Mysql中的"多对多")
相关推荐
caimouse13 小时前
ReactOS 部分编译指南
开发语言
Chase_______13 小时前
【Java基础 | 13】IO 流(下):缓冲流、转换流、序列化与综合案例
java·开发语言
弹简特13 小时前
【零基础学Python-收尾】10-Python第三方库的安装介绍
开发语言·python
雪度娃娃13 小时前
ASIO异步通信——多线程模型
开发语言·网络·c++·php
luj_176813 小时前
残熵算法:风险缓冲与效率优化的融合
c语言·开发语言·网络·经验分享·算法
Legendary_00813 小时前
从 DC 圆口到 USB-C PD:LED 照明设备的供电升级逻辑
c语言·开发语言
SilentSamsara13 小时前
Python 微服务全链路:gRPC + 链路追踪 + 服务网格接入
开发语言·分布式·python·微服务·架构
一只积极向上的小咸鱼13 小时前
VS Code / Warp MCP 迁移到 Codex MCP 配置总结
开发语言
Cloud_Shy61814 小时前
解读《Effective Python 3rd Edition》:从练气到老魔(第三章 Item 21 - 24)
开发语言·人工智能·笔记·python·迭代器模式
多彩电脑14 小时前
Lua中的元表里的__index和__newindex
开发语言·lua