Qt中注册定义类型qRegisterMetaType和Q |
您所在的位置:网站首页 › qt自定义信号量 › Qt中注册定义类型qRegisterMetaType和Q |
概述
如果想要我们自己自定义的类型也可以有 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 |