Qt专栏:http://t.csdnimg.cn/LE2Lx
目录
1.问题
2.原因
2.1.没有继承QObject,声明Q_OBJECT宏
2.2.信号槽参数不匹配
2.3.信号函数未声明为 signals
2.4.访问权限
2.5.注意connect的位置,信号在创建信号槽连接前使用,则无法触发槽函数
2.6.连接方式为Qt::QueuedConnection时参数类型没有注册
2.7.对象生命周期
2.8.事件循环被阻塞导致信号未能发出
2.9.连接类型
2.10.跨线程
2.11.未定义的行为
3.总结
1.问题
昨天在调试Qt程序的时候,信号和槽的参数用到了std::uint64_t,当信号发出了,槽函数再怎么都不响应,程序也没有报什么错,这个是为什么呢?过了一会才想起是不是系统没有注册std::uint64_t类型哦,于是在系统初始化的地方增加了:
qRegisterMetaType<std::uint64_t>("std::uint64_t");
再次调试,槽函数响应了,原来是这个问题。
其实出现类似槽函数不响应的原因还有一些,今天就列举一下,供大家查阅。
2.原因
2.1.没有继承QObject,声明Q_OBJECT宏
因为信号槽机制是需要依赖Qt的反射机制的,如果不继承Object,编写信号和槽函数的时候就会直接报错的。
2.2.信号槽参数不匹配
信号槽的参数必须匹配。如果信号有参数,槽也必须具有相同数量和类型的参数。需要特别指出的是,在参数类型属于某命名空间时,要把命名空间写完整。
2.3.信号函数未声明为 signals
2.4.访问权限
定义信号signals不需要指定类型,默认就是public的。但是槽函数可以定义为pubic slots或 private slots或 protected slots。有时,私有信号和槽不能被外部对象连接。
2.5.注意connect的位置,信号在创建信号槽连接前使用,则无法触发槽函数
2.6.连接方式为Qt::QueuedConnection时参数类型没有注册
信号槽的参数是自定义的,这时需要用qRegisterMetaType注册一下这种类型。需要使用
#include <QMetaType> qRegisterMetaType<此处为变量类型名称>("此处为变量类型名称")
来注册。 在Qt帮助手册中搜索qRegisterMetaType,有相关说明。 注意在调用connect时指定连接方式为Qt::DirectConnection(阻塞式触发),不会存在此问题。因为阻塞式触发,只需要将参数进行值传递,拷贝过去即可。而以Qt::QueuedConnection(消息队列式)连接的情况下,需要将变量转成通用数据类型QVariant存储,而用QVariant存储,必须要注册此类型。
2.7.对象生命周期
如果尝试连接的对象在连接时已经被销毁,那么连接就不会成功。确保对象在连接期间是有效的。
2.8.事件循环被阻塞导致信号未能发出
2.9.连接类型
使用适当的连接类型。Qt提供了几种不同的连接类型,包括Qt::DirectConnection、Qt::QueueConnection、Qt::AutoConnection等。
2.10.跨线程
如果信号和槽跨越不同的线程,则需要使用合适的连接类型来确保线程安全性。通常情况下,当信号和槽跨越不同的线程时,应该使用Qt::QueueConnection连接类型。
2.11.未定义的行为
在连接信号和槽时,确保在运行时信号和槽都是有效的。如果信号或槽未定义,连接操作可能会失败。
3.总结
遇到问题,根据上面列举的原因一一排查,具体现象具体分析,通常都能解决信号槽响应不了的情况。