信号和槽机制
目录
前言:
信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。
1.系统自带的信号和槽
前提条件:创建了窗口,窗口内包含按钮 需求(功能):通过点击按钮将窗口关闭
实现: connet(信号发送者,信号(地址),信号接受者,槽函数(地址))
信号格式: &信号发送者所属类::信号 其中信号为系统为信号所属类创建的系统信号
槽函数格式: &信号接受者所属类别::信号接受者处理信号的槽函数 其中槽函数为系统为信号接收者所属类创建的系统信号
代码实现:
//connect()函数最常用的一般形式:
connect(sender, signal, receiver, slot);
//第一行代码创建一个关闭按钮
//第二行就是信号槽的使用方式
QPushButton * quitBtn = new QPushButton("关闭窗口",this);
connect(quitBtn,&QPushButton::clicked,this,&MyWidget::close)
如何查找系统自带的信号和槽(如何使用帮助文档)
在帮助文档中输入QPushButton,首先我们可以在Contents中寻找关键字 signals,信号的意思,但是我们发现并没有找到,这时候我们应该想到也许这个信号的被父类继承下来的,因此我们去他的父类QAbstractButton中就可以找到该关键字,点击signals索引到系统自带的信号有如下几个
这里的clicked就是我们要找到,槽函数的寻找方式和信号一样,只不过他的关键字是slot。
2.自定义信号和槽
使用connect()可以让我们连接系统提供的信号和槽。但是,Qt 的信号槽机制并不仅仅是使用系统提供的那部分,还会允许我们自己设计自己的信号和槽。
(1)创建Teacher类和Student类
(2)自定义信号:
写在头文件中类的signals里面;信号返回值为void类型;信号只需要声明不需要实现;可以有参数,可以重载
(3)自定义槽函数:
写在头文件的类的public slots里面或者写在public 或者全局下;返回值为void类型;需要声明也需要实现;可以有参数,可以重载
(4)自定义信号&自定义槽函数的连接
在窗口中, 使用槽函数和信号:首先创建信号发送者和信号接受者;然后通过connect建立连接;最后使用emit关键字触发信号,信号将通过连接传给信号接受者启动槽函数(头文件和源文件的相关代码)
在窗口中声明一个公共方法下课,这个方法的调用会触发老师饿了这个信号,而响应槽函数学生请客
3.重载的自定义信号&槽发生重载的解决
1.需要利用函数指针 明确指向函数的地址
2.void( Teacher:: * tSignal )( QString ) =&Teacher::hungry;
3.QString 转成 char *
3.1.ToUtf8() 转为 QByteArray
3.2.Data() 转为 Char *
使用有参的槽函数和信号:需要明确(重载)信号和(重载)槽函数的地址:例 void (Teacher::teacherSignal )(QString)=&Teacher::hungry---------》代表参数为QString的重载函数的地址 代码:connect(信号发送者,有参信号(地址),信号接受者,有参槽函数(地址))
QString 转成 char *
4.信号连接信号
代码:connect(信号发送者,信号(地址),信号接受者,信号(地址)) 流程:一个按钮点击信号——>触发第一个连接的信号——>该信号触发另一个连接的槽函数
断开信号:
5.Qt4版本信号槽连接
拓展
(1)一个信号可以和多个槽相连
如果是这种情况,这些槽会一个接一个的被调用,但是它们的调用顺序是不确定的。
(2)多个信号可以连接到一个槽
只要任意一个信号发出,这个槽就会被调用。
(3)一个信号可以连接到另外的一个信号
当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别。
(4)槽可以被取消链接
这种情况并不经常出现,因为当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽。
(5)信号槽可以断开 利用disconnect关键字是可以断开信号槽的
Qt4版本写法
connect(zt,SIGNAL(hungry(QString)),st,SLOT(treat(QString)));
这里使用了*SIGNAL和SLOT这两个宏,将两个函数名转换成了字符串*。注意到connect()函数的 signal 和 slot 都是接受字符串,一旦出现连接不成功的情况,Qt4是没有编译错误的(因为一切都是字符串,编译期是不检查字符串是否匹配),而是在运行时给出错误。这无疑会增加程序的不稳定性。
Qt5在语法上完全兼容Qt4,而反之是不可以的。
6.信号和槽的小结