Qt中注册定义类型qRegisterMetaType和Q

您所在的位置:网站首页 qt自定义信号量 Qt中注册定义类型qRegisterMetaType和Q

Qt中注册定义类型qRegisterMetaType和Q

2024-01-21 07:04| 来源: 网络整理| 查看: 265

概述

如果想要我们自己自定义的类型也可以有 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");

若已经使用 Q_DECLARE_METATYPEQ 标记过该类型,可以使用其不带参数的版本:

qRegisterMetaType();

同样的,若对象包含在自定义的命名空间中时,注册时要带上完整的命令空间,如:

qRegisterMetaType("NSP::MyStruct");

若要用信号槽传递其引用值,也需要注册:

qRegisterMetaType("MyStruct&");

若要用信号槽传递其智能指针,也需要注册:

qRegisterMetaType("QSharedPointer");

总结

 在Qt中,想要使用signal/slot来传递自定义的类型时,需要使用qRegisterMetaType来注册。其原因是:当一个signal被放到队列中(queued)时,它的参数(arguments)也会被一起一起放到队列中(queued起来),这就意味着参数在被传送到slot之前需要被拷贝、存储在队列中(queue)中;为了能够在队列中存储这些参数(argument),Qt需要去construct、destruct、copy这些对象。用qRegisterMetaType对自定义的类型进行注册,就是为了告诉Qt如何去做这些事情。

      步骤:(以自定义MyDataType类型为例)

     1、自定MyDataType 类型,在这个类型的顶部包含:#include

     2、在类型定义完成后,加入声明:Q_DECLARE_METATYPE(MyDataType);

     3、在main()函数中注册这种类型:qRegisterMetaType("MyDataType");

     4、如果还希望使用这种类型的引用,可同样要注册:qRegisterMetaType("MyDataType&");

例:     

#include class MyDataType { public: MyDataType(); MyDataType(int, double); private: }; Q_DECLARE_METATYPE(MyDataType); int main(int argc, char *argv[]) { QApplication app(argc, argv); qRegisterMetaType("MyDataType"); qRegisterMetaType("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 ,构造函数中加入代码:qRegisterMetaType("MyDataType"); 3、Myclass的引用类型需单独注册:qRegisterMetaType("MyDataType&");

如果不实用这种方法,还有一种办法来使跨线程的signal/slot起作用,即使用connect函数的Qt::DirectConnection参数

connect(A,SIGNAL(sendA(MyDataType)),B,SLOT(getA(MyDataType)),Qt::DirectConnection);

但此方法官方不推荐使用,认为其不安全。不过在笔者实际使用过程中,未发现有不妥之处。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3