Qt全局信号通信

应用场景分析

Qt开发中经常会遇到作用域跨度比较大的对象间通信的场景,如果直接使用信号槽通过对象指针直接连接,首先需要将对象指针互相暴露出来,其中可能涉及到各种复杂的传递过程,导致程序混乱。一种解决方案是建立全局的信号中转站,实现全局范围内的便捷通信。

功能实现1

设现有对象A,需要将信号signalA()发送给对象B。

  1. 建立单例类class SIgnalStation。
  2. 在单例类中定义中转信号void transSignalA()。
  3. 在A的代码中,将A的信号与信号中转的信号连接:
    A:: connect(this, SIGNAL(signalA()), SIgnalStation::instance(), SIGNAL(transSignalA()));
  4. 在对象B中连接中转信号:
    B::connect(SignalStation::instance(), SIGNAL(transSignalA()), this, SLOT(…));

这样就实现了进程中任何对象间信号传递。

功能实现2

此种实现是用ID或字符串来实现对信号的索引,如下表所示:

信号标识信号签名
const char *MSG_ID_START = “MSG_ID_START”(任意可以标识的字符串)void sigStart(char *info)
const char *MSG_ID_END = “MSG_ID_END”(任意可以标识的字符串)void sigEnd(char *info)

通过这样的映射,可以实现更低的耦合,映射由一个管理器管理,如GlobalMsgMgr类。此类提供两个接口:

addEmit(const char *msg_id(信号ID), const char *signal(信号签名)):用于将本地信号绑定到信号ID上,本地信号触发时,自动触发所有连接到此信号ID上的槽。
addSlot(const char *msg_id(信号ID), const char *slot(槽签名)):用于将本地槽绑定到信号ID上,任意信号触发源触发此信号时,本地槽会被调用。

综上,
实现2比实现1的耦合程度更低,单从ID上看不出信号参数类型;好处是可以通过ID实现更松的耦合,甚至可以实现信号ID的比较运算。
实现1、实现2在触发信号时稍微麻烦一点,因为触发信号时,需要定义本地的信号。

功能实现3

参考:Qt使用信号槽模拟全局广播
这种方式在发送信号时较为简单,但是在定义和编译时略复杂。

个人建议,在简单应用下,使用功能实现1;在复杂应用下,使用功能实现2。

FAQ

为什么不用回调函数呢,因为信号槽可以很容易实现跨线程通信,回调函数跨线程调用需要处理竞争同步的问题。

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

撬动未来的支点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值