资料
- 英文剖析源码 http://woboq.com/blog/how-qt-signals-slots-work.html
- Qt豆子翻译版 https://www.devbean.net/2012/12/how-qt-signals-and-slots-work/
- Qt信号槽的简单实现 https://blog.csdn.net/fuyunzhishang1/article/details/48345381
相关宏定义
- 类定义时, 使用的moc相关的宏
Q_OBJECT
#define signals public
. Qt4中为 protected. Qt5为支持connect函数指针写法, 定义为 public.#define slots
- 连接信号槽使用的宏 (Qt4 的写法, 在函数名前添加数字, 用于标识[2]信号, [1]槽函数, [0]普通方法)
#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
- 发信号:
#define emit
过程概述
- 因为Qt5新增了允许将普通函数, lambda等连接到信号上, 再加上Qt4允许的信号, 槽函数. 所以在这里统称这些函数为目标函数.
- Qt 每个继承了 QObject, 并使用了 Q_OBJECT 的类在执行 moc 时, 会生成 moc_xxx.cpp 文件. 在该文件中有该类的内省表. 内省表记录了索引值 与各函数-信号-槽函数之间的对应关系. 在 Qt 中都是使用索引值来作为参数传递函数的.
- 每个类中的每个信号, 都维护了一个 ConnectionList, 用于存储连接到其上的目标函数.
- 在 connect 时, 需要提供 sender, signal func, receiver, call func. (当然还有连接方式, 不过和此处要讲的流程关系不大). connect 函数将 receiver 和 call func 打包成一个 Connection 节点, 并存储在 sender 的 singnal func 对应的 ConnectionList 中.
- 在 emit signal 时, 调用了
QMetaObject::activate()
, 该方法会根据传入的 sender 和 singnal func 对应的索引, 找到 ConnectionList. 并回调这些方法.
- Tips: 因为 receiver 在析构时, 需要 disconnect 所有已连接的信号. 所以每个 receiver 也应该维护一个列表, 用于保存已连接的 sender 和 signal.