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中的"多对多")
相关推荐
用户805533698034 小时前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner4 小时前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz5 天前
QML Hello World 入门示例
qt
xcyxiner8 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner9 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner9 天前
DicomViewer (添加模型类)3
qt
xcyxiner10 天前
DicomViewer (目录调整) 2
qt
xcyxiner10 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00612 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术12 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript