目录
基础使用
- 信号和槽机制是 Qt 的核心机制,可以让编程人员将互不相关的对象绑定在一起,实现对象之间的通信。
- 所有从 QObject 或其子类 ( 例如 Qwidget ) 派生的类都能够包含信号和槽。因为信号与槽的连接是通过 QObject 的 connect() 成员函数来实现的。
connect(sender, SIGNAL(signal), receiver, SLOT(slot));
- 其中 sender 与 receiver 是指向对象的指针,SIGNAL() 与 SLOT() 是转换信号与槽的宏。
- 一个信号可以连接多个槽,当信号发出时,会以不确定的顺序逐一调用槽函数
- 信号可以连接信号,第一个信号发出后引起第二信号发出
- 连接可以移除,因为在对象删除时会自动移除所以较少使用
disconnect(sender, SIGNAL(signal), receiver, SLOT(slot));
- 如果信号槽连接两次,那么信号发生时,槽函数将调用两次
- signals前面不可加public、private和protected进行修饰;slots前面可以加,因为Qt说槽函数可以当普通函数使用
- signals区域的函数必须是void类型,而且这些信号函数没有函数体,也就是说不可以自己定义这些信号函数
- 宏定义和函数指针不能用于信号和槽的参数,信号和槽也不能有缺省参数
connect函数的第五个参数
注意问题
连接失败
信号槽发送不成功可能是connect连接失败了,connect返回true表示连接成功
- 信号槽函数的参数类型或参数个数不一致,导致连接会失败
- 信号槽函数经过SIGNAL() 与 SLOT() 转换宏包裹后再元对象系统中为字符串不会检查错误推荐QT5以上使用新的写法
- 信号槽函数中消息类型没有注册在元对象系统,此时connect函数也会返回false。可以单步跟踪QT代码。注册消息需要添加类似
qRegisterMetaType<QList<CDPSlaBaseInfo>>("QList<CDPSlaBaseInfo>");
跨线程使用
- QT中跨线程推荐使用信号槽的方式传递信息,如果访问信息速度很频繁数据很大推荐用指针直接访问的方式。
- 跨线程请指定连接方式Qt::QueuedConnection,调试QT4.8.6时发现跨线程connect默认应该是Auto跨线程也就是Qt::QueuedConnection的连接方式,connect返回成功但信息实际上并没有发送过去!指定Qt::QueuedConnection的连接方式连接后connect返回false,也就是说auto的连接并没有在跨线程中默认为Qt::QueuedConnection,所以最好手动指定。
设计模式思考
- 信号槽代替了函数指针,用统一的方式实现了回调函数、对象间的消息的传递、跨线程的消息传递,使程序更简洁,是MVC设计模式的通信基础。
- 但是在有些场景下,这样传递消息是比较麻烦的,而且过多的信号槽连接增加了程序调试的困难,过多的消息传递让MVC代码不够优雅。
- React/redex前端的单一数据流结构属于发布订阅的设计模式,就很清晰不会漏发消息。