目录
一 为什么会有这个机制
二 信号与槽是什么
三 信号
四 槽
五 使用
1 最简单的
2 函数指针
3 用Lambda表达式实现
一 为什么会有这个机制
我们平时的一个网页,如果点击网页上不同的部分会有不同的相应动作。比如点击超链接就会实现网页的跳转,比如点击右上角的×就会退出关闭窗口。如果一个按钮被孤立的创建出来没有功能的话,是没有意义的。其实通过这个机制也让类之间进行交流,实现了交互。
以上是我自己的理解,但是最重要的应该是实现了松散耦合。也就是说两个类是独立的,稳定的。但是可以通过connect建立类之间的关系。不需要这个联系了也可以直接拆散,并不会对之前的类造成什么影响
二 信号与槽是什么
举一个生活中的例子,这个相当于对外界的信号做出的反映。比如比如我叫了你的名字,你回头看我。
可以这样理解:这个事件是发生在对象之间的,最简单的就是两个对象之间。那么就从两个对象入手。
两个对象:我和你
动作:我叫你,你回头。我叫你相当于我给你发的一个信号(一般生活中有事情或者打招呼的时候会叫别人),你回头(是因为我叫你这个信号导致的反应)。
当然一个信号可以和多个槽函数连接,也就是相当于你对我的这个信号可能会有多种不同的响应。
三 信号
这里从老师饿了,发出信号,学生请客吃饭这个案例入手
在类中signals:标识的函数就是信号
1 返回值是void
2 参数可以是0个也可以是多个(个数),但是无论是多少个参数的类型都要和槽匹配
3 没有实现
4 可以重载
四 槽
同理,用slots:标识的就是槽函数,也可以不表示写在public下。
1 返回值是void
2 参数要和signal匹配 可以是0个或者多个
3 有实现
4 可以重载
五 使用
了解了信号和槽是什么,为什么有信号和槽机制之后,我们来了解一下该如何使用这个机制:
连接+emit
信号需要和槽进行链接,使用connect函数
这个函数有四个参数,分别标识对象和信号+槽。第一个位置表示发出信号的对象,第二个位置是信号,第三个位置是接受信号的对象,第四个位置是槽函数。
根据之前的二也很好理解为什么会有四个参数
设置了连接之后还要进行emit才能成功被调用
1 最简单的
这个是没有其他的信号函数和槽函数,在teacher和student中都只有一个。
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
this->s=new Student;//创建student和teacher的对象
this->t=new Teacher;
connect(t,&Teacher::hungry,s,&Student::treat);
ClassOver();
}
void Widget::ClassOver()
{
emit t->hungry();
}
2 函数指针
如果我们进行了重载,可以用函数指针的方式定义信号。因为如果不指定的话就无法确定是调用哪个
void(Student::*sSlot)(QString)=&Student::treat;
void(Teacher::*tSignal)(QString)=&Teacher::hungry;
connect(t,tSignal,s,sSlot);
老版本的Qt是这样连接的
connect(t,SIGNAL(hungry()),s,SLOT(treat()));
这样就导致了重载的时候不知道去调用哪个的问题
3 用Lambda表达式实现
connect(b,&QPushButton::clicked,[=](){emit t->hungry("hot pot!");});
第三个参数如果是this的话,可以省略直接写成这样子的
其他
信号可以连接信号
//信号连接信号
void(Student::*sSlot)(QString)=&Student::treat;
void(Teacher::*tSignal)(QString)=&Teacher::hungry;
QPushButton* b=new QPushButton("treat me!",this);
connect(t,tSignal,s,sSlot);
connect(b,&QPushButton::clicked,t,tSignal);
一个信号可以连接多个槽函数,多个信号也可以连接同一个槽函数
用disconnect就可以断开连接