基本原理就是函数回调
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