从库本身来说,qt的信号与槽退出后倍受业界赞许,它是Qt重要的特性。信号和槽是Qt特有的信息传输机制,是Qt程序设计的重要基础,可以让互不干扰的对象建立一种联系。不仅GUI界面项目可以用控制台项目也可以使用。
Qt为了方便事件的处理,引入了信号(Signal) 的概念,封装了一些事件操作的标准预处理,使得用户不必去处理底层事件,只需要处理信号即可,同时qt将信号概念更加广泛化,可以发送自定义信号。
信号与槽(Slot) 其实都是函数。
“三步使用法”:emit函数发射信号,slot函数实现功能,connect函数绑定连接起来。
当事件被触发时将发送一个信号,与之连接的槽函数则可以接收到并做出响应。
“相当于将军发出吹哨信号,士兵听到开始拿枪冲锋”。
信号发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用
连接(connect) 函数,意思是将想要处理的信号和自己的一个函数(槽)绑定来进行处理。也就是说,当信号发出时,被连接的槽函数会自动被回调。
槽的本质是类的成员函数,它的参数可以是任意类型,和普通C++成员函数几乎没有
区别,唯一的区别是:槽可以与信号连接(可理解为绑定)在一起,每当和槽连接的信号被发出时,就会调用这个槽。
1、信号
信号使用注意:
1、必须包含头文件
和元对象宏 Q_OBJECT 2、signals 关键字指出进入了信号声明区,随后即可声明自己的信号函数。也可以带任何形式的参数。
3、使用时emit发射即可;
2、槽函数
slots关键字指出进入了槽函数声明区,随后即可声明自己的槽函数。
#ifndef TEST_H
#define TEST_H
#include
#include
class test : public QObject
{
Q_OBJECT
public:
explicit test(QObject *parent = nullptr);
signals:
void close();
public slots:
void dostuff();
};
#endif // TEST_H
#include "test.h"
test::test(QObject *parent) : QObject(parent)
{
}
void test::dostuff()
{
qInfo() << "Doing stuff!";
emit close();
}
3、connect函数
connect归属于QObject,五个形参,一般只用四个,第五个默认。
简单理解为:谁发送,发送的什么信号,谁接收,接受后槽函数怎么处理
QObject::connect(&tests,&test::close,&a,&QCoreApplication::quit);
以下案例,使用第五个形参——类型type
这里tests发送,发送的是关闭信号,a接受,调用a预定义的槽函数,类型QueuedConnection。
1、当默认的话AutoConnection会被视为DirectConnection,槽函数运行在发送者内也就test内,会导致Exit mark:无法或者说没机会打印输出;
2、当被指定为QueuedConnection,槽函数运行在接收者内,也就a内。所以Exit mark:正常输出。
#include
#include "test.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
test tests;
QObject::connect(&tests,&test::close,&a,&QCoreApplication::quit,Qt::QueuedConnection);
tests.dostuff();
int mark=a.exec();
qInfo() << "Exit mark:" << mark;
return mark;
//return a.exec();
}
最后:
Qt的事件和信号与槽是不同的!!!。
1、信号由具体对象发出,然后会马上交给由connect()函数连接的槽进行处理。
2、事件,Qt使用一个事件队列对所有发出的事件进行维护;当新的事件产生时,会被追加到事件队列的尾部;前一个事件完成后,取出后面的事件接着进行处理。
过程:事件派发 notify-> 事件过滤eventFilter->事件分发event->事件处理
信号与槽的效率是非常高的,但是同真正的回调函数比较起来,由于增加了灵活性,因此在速度上还是有所损失,当然这种损失相对来说是比较小的,通过在一台 i586-133 的机器上测试是 10 微秒(运行 Linux),可见这种机制所提供的简洁性、灵活性还是值得的。