QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类
一般情况下信号槽直接连接方式不会出现问题,但是如果信号与槽在不同线程或Qt::QueuedConnection方式连接,可能会在连接期间报以下类似问题,如:
QObject::connect: Cannot queue arguments of type 'ThreadSignal'
(Make sure 'ThreadSignal' is registered using qRegisterMetaType().)
或者
QObject::connect: Cannot queue arguments of type 'BYTE[5]'
(Make sure 'BYTE[5]' is registered using qRegisterMetaType().)
或者
QObject::connect: Cannot queue arguments of type 'QMap<QString,CommDevice*>'
(Make sure 'QMap<QString,CommDevice*>' is registered using qRegisterMetaType().)
出现如此问题,在于QT对数据类型未知,按照此提示在连接信号与槽之前,调用 qRegisterMetaType()解决。直接上代码,如下:
qRegisterMetaType<ThreadSignal>("ThreadSignal");
或者
qRegisterMetaType<BYTE * >("BYTE[5]"); //请注意这一行,关于如何注册数组类型
或者
这种情况有点复杂,由于QMap<QString,CommDevice*> 在qRegisterMetaType<QMap<QString,CommDevice*>>("QMap<QString,CommDevice*>")会报错,无法识别,故可才采用别名的方式:
typedef QMap<QString,CommDevice*> MP_COMMDEVICES;
然后注册采用
qRegisterMetaType<MP_COMMDEVICES>("MP_COMMDEVICES");即可注册成功。
关键点:此处的注册语句qRegisterMetaType()一定要在connect之前执行。如果是信号槽在不同线程的情况下,则需要采用以下方式先利用信号槽调用qRegisterMetaType()注册,然后再利用信号槽建立connect,而不是在构造函数中简单的将qRegisterMetaType语句放在connect语句之前执行这么简单,因为构造函数是在生成该对象的线程中执行的。具体参考以下代码:
TcpConnectManage.h #ifndef TCPCONNECTMANAGE_H
#define TCPCONNECTMANAGE_H #include <QObject>
#include <QThread>
#include "Protocol.h" typedef QMap<QString,CommDevice*> MP_COMMDEVICES;//QMap<QString,CommDevice*>无法在qRegisterMetaType中识别,故采用别名方式 class TcpConnectManage : public QObject
{
Q_OBJECT
public:
explicit TcpConnectManage(QObject *parent = );
......
void connectKeep(QMap<QString, Protocol *> *protocols, MP_COMMDEVICES comm_devices);
......
///
/// \brief registerReflex 注册反射类
///
void registerReflex();
///
/// \brief createConnect 本函数配合对应的信号槽的目的主要是,为了注册
///
void createConnect(); signals:
void sigConnectKeep(QMap<QString, Protocol *> *protocols, MP_COMMDEVICES comm_devices);
void sigRegisterReflex();
void sigCreateConnect();
public slots:
void sltConnectKeep(QMap<QString, Protocol *> *protocols, MP_COMMDEVICES comm_devices);
void sltRegisterReflex();
void sltCreateConnect();
}; #endif // TCPCONNECTMANAGE_H
#include "TcpConnectManage.h" TcpConnectManage::TcpConnectManage(QObject *parent) :
QObject(parent)
{
connect(this,SIGNAL(sigRegisterReflex()),this,SLOT(sltRegisterReflex()));
connect(this,SIGNAL(sigCreateConnect()),this,SLOT(sltCreateConnect()));
} ...... void TcpConnectManage::registerReflex()
{
emit sigRegisterReflex();
} void TcpConnectManage::createConnect()
{
emit sigCreateConnect();
} ...... void TcpConnectManage::sltRegisterReflex()
{
//信号槽中使用的自定义类型注册
qRegisterMetaType<MP_COMMDEVICES>("MP_COMMDEVICES"); //类注册
......
} void TcpConnectManage::sltCreateConnect()
{
connect(this,SIGNAL(sigConnectKeep(QMap<QString,Protocol*>*,MP_COMMDEVICES)),
this,SLOT(sltConnectKeep(QMap<QString,Protocol*>*,MP_COMMDEVICES)));
}
注意:此处
typedef QMap<QString,CommDevice*> MP_COMMDEVICES;//QMap<QString,CommDevice*>无法在qRegisterMetaType中识别,故采用别名方式
不能为
typedef QMap<QString,CommDevice*>& MP_COMMDEVICES;//QMap<QString,CommDevice*>无法在qRegisterMetaType中识别,故采用别名方式
即参数为引用类型,会报以下错误

原因:template argument deduction/substitution failed 模板函数的参数类型不能通过表达式推导
关于模板参数的推导,参考:【C++】模板参数推导(template argument deduction)http://www.cnblogs.com/visayafan/archive/2011/11/27/2265400.html
其实在信号槽连接方式使用Qt:QueuedConnection时,其中的参数完全没有必要使用引用类型,因为此种方式下,信号参数为引用类型,则还是会另外复制一份的。

http://www.dushibaiyu.com/2015/07/qt-signals-slots-connect.html
QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类的更多相关文章
- QT信号槽connect的第五个参数
用过QT的小伙伴都知道连接信号槽的connect方法,但是这个方法有第五个参数,一般都是用的默认的 connect(th,SIGNAL(started()),tmpmyobject,SLOT(show ...
- QT信号槽的六个优点(虽然直接调用函数也可解决问题,但要在具体的函数中传递指针,多对一和解除关系也够麻烦的)
信号槽是Qt中特有的概念.它使得程序员将不同的object绑定起来,而object对象间并不需要对相互了解. Slots也是普通的c++方法,它们可以是virtual;可以被重载;可以使private ...
- 如何在Qt中使用自定义数据类型
这里我们使用下面这个struct来做说明(这里不管是struct还是class都一样): struct Player { int number; QString firstName; QString ...
- QT为QLabel添加Click事件(如果我们使用组件,我们关心的是信号槽;如果我们自定义组件,我们关心的是事件)
其实就是改写了一个函数:mouseReleaseEvent,当在QLabel放开鼠标的时,就发射点击信号. #ifndef CLICKEDLABEL_H_ #define CLICKEDLABEL_H ...
- QT信号槽详解
1 QT信号槽详解 1.1 信号和槽的定义 信号是触发信号,例如按钮的点击触发一个clicked信号,槽是用来接收信号,并处理信号,相当于信号响应函数.一个信号可以关联多个槽函数,信 ...
- Qt信号槽-原理分析
目录 一.问题 二.Moc 1.变量 2.Q_OBJECT展开后的函数声明 3.自定义信号 三.connect 四.信号触发 1.直连 2.队列连接 五.总结 六.推荐阅读 一.问题 学习Qt有一段时 ...
- QT源码之Qt信号槽机制与事件机制的联系
QT源码之Qt信号槽机制与事件机制的联系是本文要介绍的内容,通过解决一个问题,从中分析出的理论,先来看内容. 本文就是来解决一个问题,就是当signal和slot的连接为Qt::QueuedConne ...
- Qt信号槽源码剖析(一)
大家好,我是IT文艺男,来自一线大厂的一线程序员 大家在使用Qt开发程序时,都知道怎么使用Qt的信号槽,但是Qt信号槽是怎么工作的? 大部分人仍然不知道:也就是说大家只知道怎么使用,却不知道基于什么原 ...
- Qt信号槽的一些事(第一次知道信号还有返回值,以及Qt::UniqueConnection)
注:此文是站在Qt5的角度说的,对于Qt4部分是不适用的. 1.先说Qt信号槽的几种连接方式和执行方式. 1)Qt信号槽给出了五种连接方式: Qt::AutoConnection 0 自动连接:默认的 ...
随机推荐
- sql server 高级查询
--in和not in子查询 --采用in子查询获得参加考试的在读学生名单select StudentId,StudentName from Student where StudentId in(se ...
- [CF528D]Fuzzy Seach
Description: 有两个基因串S和T,他们只包含AGCT四种字符.现在你要找出T在S中出现了几次. 有一个门限值k≥0.T在S的第i(1≤i≤|S|-|T|+1)个位置中出现的条件如下:把T的 ...
- C++程序设计方法3:对象组合
对象组合 包含其他类的对象 可以在类中使用其他类来定义数据成员,通常称为“子对象”:这种包含与被包含的对象间的关系称为“组合”,组合关系可以嵌套. 子对象构造时若需要参数,则应当在当前类的构造函数的初 ...
- Java 适配器模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述适配器(Adapter)模式的: 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能 ...
- Jmeter接口测试实例3-登录
Jmeter实例3:登录 添加http协议—添加IP.路径.方法,察看结果树,运行 登录成功
- Django REST framework API开发
RESTful设计方法 1. 域名 应该尽量将API部署在专用域名之下. https://api.example.com 如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下. https:/ ...
- openstack之Neutron网络虚拟化
第一:为什么需要网络虚拟化? 一.数据中心的现有网络不能满足云计算的物理需求: 互联网行业数据中心的基本特征就是服务器的规模偏大.进入云计算时代后,其业务特征变得更加复杂,包括:虚拟化支持.多业务承载 ...
- 主流CTR预估模型的演化及对比
https://zhuanlan.zhihu.com/p/35465875 学习和预测用户的反馈对于个性化推荐.信息检索和在线广告等领域都有着极其重要的作用.在这些领域,用户的反馈行为包括点击.收藏. ...
- jvm理论-字节码指令
Java虚拟机的指令由一个字节长度的.代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成. 基本数据类型 1.除了l ...
- grid - 隐式地命名网格区域名称
通常可以将网格线命名成任何你想命名的名称,如果网格线名称添加-start和-end的后缀,其实也隐式的创建一个网格区域,可以用来设置网格项目的位置. 在这个示例中,行和列都具有inner-start和 ...