自定义信号和槽
基本语法
在Qt中,允许自定义信号的发送方以及接收方,即可以自定义信号函数和槽函数。但是对于自定义的信号函数和槽函数有一定的书写规范。
1、自定义信号函数书写规范
(1)自定义信号函数必须写到"signals"下;
(2)返回值为void,只需要声明,不需要实现 ;
(3)可以有参数,也可以发生重载;
2、自定义槽函数书写规范
(1)早期的Qt版本要求槽函数必须写到"public slots"下,但是现在高级版本的Qt允许写到类的"public"作用域中或者全局下;
(2)返回值为void,需要声明,也需要实现;
(3)可以有参数,可以发生重载;
3、发送信号
使用"emit"关键字发送信号。"emit"是一个空的宏。"emit"其实是可选的,没有什么含义,只是为了提醒开发人员。
示例1 :
1、在widget.h中声明自定义的信号和槽,如图所示:

2.在widget.cpp中实现槽函数,并且关联信号和槽。
注意:图中的①和②的顺序不能颠倒。
原因是,首先关联信号和槽,一旦检测到信号发射之后就会立马执行关联的槽函数。反之,若先发射信号,此时还没有关联槽函数,当信号发射之后槽函数不会响应。

示例2 :
当老师说"上课了",学生们就"回到座位,开始学习"。
1、在源文件中新建两个类,一个是老师类,一个是学生类;首先选中项目名称,鼠标右键----->"add new..."

选择"choose"出现如下界面。

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

在teacher.h中声明信号函数:

在student.h中声明槽函数:

在widget.h中实例化"⽼师类对象"和"学⽣类对象";

在student.cpp中实现槽函数:

在widget.cpp中连接⾃定义信号和槽;

带参数的信号和槽
Qt的信号和槽也支持带有参数,同时也支持重载。
此处要求,信号函数的参数列表要和对应连接的槽函数参数列表一致。
信号触发并调用槽函数时,信号函数中的实参能够传递到槽函数的形参当中。
借助该机制,便可实现信号向槽传递数据 。
示例1 :给自定义信号传参一个字符串,信号会将这个字符串传递给槽函数,进而显示在窗口标题上。




调用过程:首先按钮1被按下,此时Qt的内置信号clicked被发出(发出内置信号的代码已经内置到了Qt的框架中),所以此时就会执行按钮1对应的自定义槽函数,在自定义槽函数中会使用emit发出自定义信号MySignal给参数text传入标题1,此时自定义信号MySignal被发出,会执行对应的自定义槽函数,进而就会使用this指针调用setWindowTitle将形参text设置进去,此时标题1就被设置好了,标题2同理。
对于自定义信号函数的参数和自定义槽函数的参数,要求参数的类型和顺序必须一致 。
参数的个数不一致也可以,若参数个数不一致,要求自定义信号函数的参数个数必须大于自定义槽函数的参数个数 。
很多Qt的内置信号也带有参数,这些参数不是我们传递的,而是由Qt框架传递,例如clicked就重载了带有参数的版本。
**示例二:**验证信号函数的参数个数如果大于槽函数参数个数仍然可以使用。
给信号函数加上第二个参数const QString& text2:


信号函数的形参个数小于槽函数时:会报错

因为一个槽函数,有可能会被多个信号函数绑定。若要求信号函数的参数个数大于等于槽函数的参数个数,则多个参数的的信号函数也可以绑定同一个槽函数。
原理:
为什么我们可以使用Qt中的信号和槽?
由于Widget中的宏Q_OBJECT的存在。Qt中硬性规定,Qt中如果要让某个类可以使用信号槽(即可以在类中定义信号函数和槽函数),则必须在类开始的地方写下Q_OBJECT这个宏。默认Qt帮我们自动生成的代码中都会带这Q_OBJECT这个宏,它能展开很多代码。