一、信号和槽的简介
信号和槽相当于 观察者模式 ,信号的发送方在发送信号的时候并不知道接收者是谁,类似于广播的形式。而信号的接收方也不关心信号是由谁发出的,只要对象对该信号有兴趣就会使用connect
函数来在两者之间建立连接,接收方通过槽函数来对收到的信号进行处理。接受方会一直监听,只要发送方发送了指定的信号,接受方就会立刻接受到。主要用于不同控件之间的沟通
1、需要四个参数:以点击按钮关闭窗口来进行演示
- 信号的发送者:相当于按钮
- 发送的具体信号内容:相当于点击的动作
- 信号的接收方:相当于该窗口
- 对信号进行处理操作(就是指槽):相当于关闭窗口
2、需要connect
进行连接
信号发送方和信号接收方之间本身是没有关联的。信号槽的优点就在于松散耦合的方式,因此需要connect
来进行连接,将两端进行耦合在一起。
3、通过点击关闭窗口来进行演示
#include "mywidget01.h"
#include"mypushbutton.h" //将自定义类的头文件添加进来
myWidget01::myWidget01(QWidget *parent)
: QWidget(parent)
{
myPushButton *myBtn=new myPushButton;
myBtn->setParent(this);
myBtn->setText("关闭窗口");
myBtn->move(10,20);
/*
参数1:信号的发送者,就是该按钮;参数2:发送的信号内容,就是点击事件,在此传入的就是事件函数地址
参数3:信号的接受方,就是该应用窗口;参数4:就是槽,也即信号的处理操作
*/
connect(myBtn,&myPushButton::clicked,this,&myWidget01::close);
/*
// 由于myPushButton继承自QPushButton,myWidget01继承自QWidget。所以可以直接使用其父类来代替子类。
connect(myBtn,&QPushButton::clicked,this,&QWidget::close);
*/
}
myWidget01::~myWidget01()
{
}
二、自定义信号和槽
1、具体场景
- 下课后老师触发一个信号:信号发送者;
- 饿了:信号具体内容 ;
- 学生响应信号:信号接收者 ;
- 去吃饭:信息处理,即槽函数
2、具体实现过程
1)、分别创建两个类Teacher
和Students
,(注:在QtCreator中创建类的时候会默认同时创建对应的.h
文件和.cpp
文件)。其中Teacher
为信号方,Students
是信号处理者,即为槽函数。
2)、 生成的文件结构如下
3)、teacher.h
文件中 :由于Teacher类是信号方,所以需要将对应函数写在信号 signals: 下面。由于信号函数只需要声明,无需定义,所以teacher.cpp
文件无需任何改变
4)、students.h
文件为信号接收处理方,在其中写槽函数的声明。在students.cpp
文件中来写槽函数的实现。
5)、widget.h
文件中声明老师和学生的对象,并声明一个下课的函数
6)、widget.cpp
文件中进行实现对应的操作
触发信号可以用 emit
7)、运行结果如下
三、自定义信号和槽发生重载
1、当自定义的信号和槽发生重载时,需要用函数指针来指向函数地址,来明确告诉connect
要调用的是哪一个函数。
运行结果如下
四、通过按钮来触发饿了的信号
对应代码如下:
运行结果如下:
五、Lambda
表达式相关
用lambda
表达式来充当槽函数,关闭窗口。其好处是可以在其中调用其他的函数,而不仅仅执行对应的槽函数。
如通过点击按钮来关闭窗口
QPushButton *btn02=new QPushButton;
btn02->setText("CloseWindow");
btn02->setParent(this);
btn02->move(300,0);
// lambda 表达式当槽函数,在此除了可以关闭窗口之外,还可以打印调试信息
connect(btn02,&QPushButton::clicked,this,[=]{Widget::close();qDebug()<<"just Test"<<endl;});
六、Qt4和Qt5中信号槽的不同用法
1、Qt4
中信号槽的写法
QPushButton *btn01 = new QPushButton("btn of Qt4", this);
connect(btn01, SIGNAL(clicked()), this, SLOT(close()));
2、Qt5
中信号槽的写法
QPushButton *btn02 = new QPushButton("btn of Qt5", this);
connect(btn02, &QPushButton::clicked, this, &QtPractice03::close);
/* 或者使用如下的Lambda写法
connect(btn02, &QPushButton::clicked, this, [=] {this->close(); });
*/
Qt5
中的信号槽会增加编译阶段的检测功能,会更加安全。且Qt5
会向下兼容Qt4
信号的写法
七、拓展内容
- 信号可以连接信号
- 一个信号可以连接多个槽函数
- 多个信号可以连接同一个槽函数
- 信号和槽函数的参数必须类型一一对应的
- 信号和槽函数的参数个数可以不一致,如信号的个数可以多余槽函数的个数,反之则不行