更多参考文章链接如下:
Qt对象模型之一:信号和槽
信号和槽知识点总结
信号和槽函数介绍
信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。信号的本质就是事件。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。
槽的本质是类的成员函数,其参数可以是任意类型的。和普通C++成员函数几乎没有区别,它可以是虚函数;也可以被重载;可以是公有的、保护的、私有的、也可以被其他C++成员函数调用。唯一区别的是:槽可以与信号连接在一起,每当和槽连接的信号被发射的时候,就会调用这个槽。之所以称之为槽函数是因为它的职责就是对Qt框架中产生的信号进行处理。在Qt中槽函数的所有者也是某个类的实列对象。
**早期,对象间的通信采用回调来实现。回调实际上是利用函数指针来实现,当我们希望某件事发生时处理函数能够获得通知,就需要将回调函数的指针传递给处理函数,这样处理函数就会在合适的时候调用回调函数。**回调有两个明显的缺点:
- 它们不是类型安全的,我们无法保证处理函数传递给回调函数的参数都是正确的。
- 回调函数和处理函数紧密耦合,源于处理函数必须知道哪一个函数被回调。
自定义信号:只需要声明,不需要实现,返回值是void类型,可以有参数,可以重载,要写在类中的Signal关键字下,在程序中发射自定义信号,其本质就是调用信号函数,习惯性在信号函数前加关键字:emit,但是可以省略不写,emit只是显示的声明一下信号要被发射了,没有特殊含义,底层 emit = #define emit,信号参数的作用就是数据传递,谁调用信号函数就指定实参,实参最终会被传递给槽函数。
自定义槽函数:既需要声明,也需要实现,返回值是void类型,可以参数,可以重载,早期版本必须写到Public Slots关键字下,高级版本就可以写到Public或者全局函数。
注意:signal的代码会由 moc 自动生成,开发人员不能在自己的C++代码中实现它。反之,槽应该由开发人员来实现。
当自定义信号和槽函数出现重载,需要利用函数指针(格式:返回值类型(作用域类型*变量名)(参数类型))明确指向函数的地址,尤其要注意作用域类型不能忘记。
信号槽函数无参和有参举例如下:
//连接无参数的信号和槽
void(Teacher::* teacherSignal1)()=&Teacher::hungry;
void(Student::* studentSlot1)()=&Student::treat;//函数指针要明确归属类
connect(teacher,teacherSignal1,student,studentSlot1);//连接老师饿了的信号和学生请吃饭的槽函数
classIsOver1();//利用下课了触发老师饿了的信号,函数内部有emit触发
//连接带参数的信号和槽(信号和槽函数的类型索引必须一一对应)
void(Teacher::* teacherSignal2)(QString)=&Teacher::hungry;
void(Student::* studentSlot2)(QString)=&Student::treat;
connect(teacher,teacherSignal2,student,studentSlot2);
classIsOver2();
在Qt中自定义信号槽,需要满足一些条件,并且有些事项需要注意:
1)要编写新的类并且让其继承Qt的某些标准类;
2)这个新的子类必须从QObject类或者是QObject子类进行派生;
3)在定义类的头文件中加入 Q_OBJECT 宏;