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中的"多对多")
相关推荐
小短腿的代码世界41 分钟前
KDDockWidgets深度解析:Qt停靠布局的工业级解决方案
qt
橘颂TA1 小时前
【Linux】自旋锁
linux·开发语言·数据库·c++
一诺加油鸭1 小时前
若依后端系统集成 Swagger 接口文档功能
java·开发语言
ECT-OS-JiuHuaShan1 小时前
功夫不负匠心人,渡劫代谢舞沧桑
android·开发语言·人工智能·算法·机器学习·kotlin·拓扑学
knight_9___1 小时前
LLM工具调用面试篇1
开发语言·人工智能·python·面试·agent
一脸dio样7541 小时前
第5章 保护模式进阶,向内核迈进
linux·开发语言
小叮当⇔1 小时前
M4A 转 MP3 桌面转换器(PyQt5 + FFmpeg)
开发语言·qt·ffmpeg
aq55356001 小时前
Laravel9.x新特性全解析
java·开发语言·数据库
珹洺1 小时前
C++AI多模型聊天系统(三)AI多模型(豆包/Kimi/千问)接入与实现
开发语言·c++·人工智能
Bat U2 小时前
JavaEE|多线程(五)
java·开发语言·jvm