Qt中注册定义类型qRegisterMetaType和Q_DECLARE_METATYPE的总结
概述
如果想要我们自己自定义的类型也可以有 Qt 自己类型的功能的话,就必须注册我们的类型到 Qt 中,这样才可以在信号和槽的通讯机制中使用我们的自定义的类型。
Q_DECLARE_METATYPE
被 Q_DECLARE_METATYPEQ 标记的类型可以让Q MetaType 查询到类型,也可以让QVariant识别到。
struct MyStruct {QString name;
};
Q_DECLARE_METATYPE(MyStruct)
若对象包含在自定义的命名空间中时,注册时要带上完整的命令空间
Q_DECLARE_METATYPE(NSP::MyStruct)
qRegisterMetaType
使用 qRegisterMetaType 注册自定义类型到元对象系统中主要作用为 QObject 的属性系统(信号槽)中使用该自定义类型。
一般在第一次定义信号槽连接 connect 前进行注册,参数建议为同名字符串参数:
qRegisterMetaType<MyStruct>("MyStruct");
若已经使用 Q_DECLARE_METATYPEQ 标记过该类型,可以使用其不带参数的版本:
qRegisterMetaType<MyStruct>();
同样的,若对象包含在自定义的命名空间中时,注册时要带上完整的命令空间,如:
qRegisterMetaType<NSP::MyStruct>("NSP::MyStruct");
若要用信号槽传递其引用值,也需要注册:
qRegisterMetaType<MyStruct>("MyStruct&");
若要用信号槽传递其智能指针,也需要注册:
qRegisterMetaType<QSharedPointer<MyStruct>>("QSharedPointer<MyStruct>");
总结
在Qt中,想要使用signal/slot来传递自定义的类型时,需要使用qRegisterMetaType来注册。其原因是:当一个signal被放到队列中(queued)时,它的参数(arguments)也会被一起一起放到队列中(queued起来),这就意味着参数在被传送到slot之前需要被拷贝、存储在队列中(queue)中;为了能够在队列中存储这些参数(argument),Qt需要去construct、destruct、copy这些对象。用qRegisterMetaType对自定义的类型进行注册,就是为了告诉Qt如何去做这些事情。
步骤:(以自定义MyDataType类型为例)
1、自定MyDataType 类型,在这个类型的顶部包含:#include <QMetaType>
2、在类型定义完成后,加入声明:Q_DECLARE_METATYPE(MyDataType);
3、在main()函数中注册这种类型:qRegisterMetaType<MyDataType>("MyDataType");
4、如果还希望使用这种类型的引用,可同样要注册:qRegisterMetaType<MyDataType>("MyDataType&");
例:
#include <QMetaType>
class MyDataType{ public: MyDataType(); MyDataType(int, double);
private:
};
Q_DECLARE_METATYPE(MyDataType); int main(int argc, char *argv[])
{
QApplication app(argc, argv); qRegisterMetaType<MyDataType>("MyDataType"); qRegisterMetaType<MyDataType>("MyDataType&");
}
不跨线程的话,使用自定义的类型使用signal/slot来传递,没有什么问题。
但如果是跨线程的使用,则没有这么简单。
直接使用的话,会产生下面这种错误:(假定自定义类为MyClass)
QObject::connect: Cannot queue arguments of type 'MyDataType' (Make sure 'MyDataType' is registed using qRegisterMetaType().)
实际运行中也会发现,该信号槽没有起作用。
其实解决方法在错误提示中已经给出了:Make sure 'MyDataType' is registed using qRegisterMetaType().
即使用qRegisterMetaType()将自定义类型进行注册
这里总结使用方法如下:
1、注册位置:在第一次使用此类链接跨线程的signal/slot之前,一般在当前类的构造函数中进行注册;
2、注册方法:在当前类的顶部包含:#include <QMetaType>,构造函数中加入代码:qRegisterMetaType<MyDataType>("MyDataType");
3、Myclass的引用类型需单独注册:qRegisterMetaType<MyDataType>("MyDataType&");
如果不实用这种方法,还有一种办法来使跨线程的signal/slot起作用,即使用connect函数的Qt::DirectConnection参数
connect(A,SIGNAL(sendA(MyDataType)),B,SLOT(getA(MyDataType)),Qt::DirectConnection);
但此方法官方不推荐使用,认为其不安全。不过在笔者实际使用过程中,未发现有不妥之处。
Qt中注册定义类型qRegisterMetaType和Q_DECLARE_METATYPE的总结相关推荐
- Qt中的项目类型(二)
使用Qt进行软件开发,第一个要考虑的问题就是为需要开发的软件,选择一个合适的Qt项目类型. Qt中的项目类型有: Application: "应用"项目,项目编译结果是可执行程序. ...
- java中已定义类型car_Java 8 习惯用语(8):Java 知道您的类型
Java™8 是第一个支持类型推断的 Java 版本,而且它仅对 lambda 表达式支持此功能.在 lambda 表达式中使用类型推断具有强大的作用,它将帮助您做好准备以应对未来的 Java 版本, ...
- C++/C++11中用于定义类型别名的两种方法:typedef和using
类型别名(type alias)是一个名字,它是某种类型的同义词.使用类型别名有很多好处,它让复杂的类型名字变得简单明了.易于理解和使用,还有助于程序员清楚地知道使用该类型的真实目的.在C++中,任何 ...
- (2)Qt中的字符串类型
字节数组(QByteArray) 在Qt中QByteArray可以看做是C语言中 char*的升级版本.我们在使用这种类型的时候可通过这个类的构造函数申请一块动态内存,用于存储我们需要处理的字符串数据 ...
- Qt中重定义的解决方案
利用Qt Creator开发时可能会遇到明明只是定义一次的变量或函数,偏偏报错重定义了! 可能原因: 1. 变量真正重定义了 2. 文件重复包含 3. 自己手动删除了旧文件,使用新文件替换了,但是pr ...
- linux创建自定义组件qt,QT中的元对象系统:创建自定义的QT类型
原创文章,转载请注明出处,谢谢! 作者:清林,博客名:飞空静渡 QVariant可以表示QT中的大部分类型,它和pascal中的variant类型或c中的void类型有点相似,不过它的使用和c中的un ...
- Qt 从C ++定义QML类型(二)
前言 在上一篇文章中介绍了如何注册一个C++的可实例化的对象类型供 QML 中使用,那么今天继续之前的文章介绍. 正文 注册不可实例化类型 有时候QObject派生类可能需要在QML类型系统中注册,但 ...
- 【Qt】 Qt中实时更新UI程序示例
00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 实时更新UI(非信号与槽) 04. 实时更新UI(信号与槽) 05. 源码下载 06. 附录 01. 概述 Qt在运行时会 ...
- Qt中的消息通知和事件发送
Qt 中的信号和槽机制.事件机制是其具有特色的两大机制.利用这两种机制可以轻松地实现需要的消息通知和事件通知. 1.信号和槽机制 充分使用 Qt 库中已经定义和实现好的对象的信号和槽函数,如按钮的 c ...
最新文章
- PHP 函数 ignore_user_abort定时执行任务的实现
- 分区硬盘Lvm 折腾小记
- 解决QT出现XXXX.dll不能加载问题
- ArrayList实现原理
- 像素画高级教程:怎样画流动的水
- maven nexus 说明
- WEB前端开发职业学习路线初级完整版
- 【干货】2020顶级数据团队建设全景报告-清华大学.pdf(附下载链接)
- jquery学习笔记(-)
- Collectors.toMap()
- QCC304x系列开发教程(实战篇) 之7.2 QCC3040之主副耳切换过程详解
- 模拟CMOS集成电路放大器总结(1)
- 2022年中国汽车维修设备市场现状研究分析
- Visual Studio完成并换行快捷键
- OC继承详解与使用规则
- linux设备驱动归纳总结(十):1.udevmisc
- 怎样打印微信文档文件?
- 数据治理:数据质量管理策略!
- 微信小程序的事件处理,已整理成文档
- Idea开发springBoot 中使用 thymeleaf 模板$表达式报红波浪线解决方案