Qt信号与槽原理

基本原理就是函数回调

1、增加自定义类,并继承QObjec,并加入Q_OBJECT宏。

2、在类中添加signals宏并添加信号;添加slots宏并添加槽函数。

3、执行qmake生成Makefile。

4、执行编译

moc【Qt的元对象编译器】先将类编译生成moc_xxx.cpp文件,为我们增加了使用信号槽时需要的一些函数,并识别signal宏,将信号转为对象【为啥slots不用呢?因为槽我们在自己的cpp中就定义了】

相关函数如下【没必要纠结这些函数有啥用,反正实现信号与槽时可能会调用这些函数】:

- void xxx::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
- const QMetaObject xxx::staticMetaObject
- const QMetaObject *xxx::metaObject()
- void *xxx::qt_metacast(const char *_clname)
- int xxx::qt_metacall(QMetaObject::Call _c, int _id, void **_a)

5、连接a对象的信号到b、c两个对象的槽里

使用conncet函数,如

a.connect(b);
a.connect(c);

此函数生成Connection对象,Connection对象里存储了槽函数的函数指针。

这里便生成了两个Connection对象,对象会存储在a内存的容器里。

6、发送信号并执行槽函数

通过emit a.signal()来发送信号,emit只是一个宏,没有啥作用,毕竟信号也只是一个函数,这里的发送信号就相当于调用了信号这个函数。

当调用信号函数后,a对象会遍历自己管理Connection的容器,然后根据不同调用类型依次处理存储的槽函数指针。

7、执行槽函数

这里便有一个概念,就是如何调用槽函数。

已知Qt的信号槽连接最后一个参数可选如下:

Qt::AutoConnection 自动连接【默认】
Qt::DirectConnection 直连
Qt::QueuedConnection 队列连接
Qt::BlockingQueuedConnection 阻塞队列连接
Qt::UniqueConnection 唯一连接

主要分为两种:直接调用、队列调用。

直接调用:a对象找到指定槽对象的槽函数,并直接回调此函数;

队列调用:a对象将此槽函数绑定到一个Qt的事件,当b、c对象接收到自己对应的事件后,再执行对应槽函数。

故:归根结底,信号与槽都是通过函数回调来实现的。

ps:

1、a对象disconnect槽函数后,就从自己的容器里删除对应的槽函数;

2、a对象disconnectall后,就从自己的容器里删除全部的槽函数;

3、connect槽对象

//连接槽函数
QObject::connect(p, SIGNAL(mySignal(double)), p, SLOT(mySlot(double)));
//连接拉姆达函数
auto lambdaSlot= [](double i){
    qDebug()<<"拉姆达槽函数"<<i;
};
QObject::connect(p, &Mos::mySignal, lambdaSlot);
//连接函数对象
std::function<void(double)> fSlot = lambdaSlot;
QObject::connect(p, &Mos::mySignal, fSlot);

参考:https://www.cnblogs.com/swarmbees/p/10816139.html

原文地址:https://www.cnblogs.com/judes/p/15534473.html