QVariant::UserType QVariant自定义数据类型的深入认识
1 /************************************************* 2 Copyright: zhm_xxbs@2022 3 Author: 张洪铭 4 Date: 2022年08月07日 5 Description:主要围绕QVariant类型,编写代码深入认识 QVariant::UserType。 6 总结: 7 1. 自定义枚举类型。 8 1)QVariant::type() 不能识别到 QVariant::UserType类型; 9 2)使用 Q_ENUM() 注册到元对象系统内的枚举类型,可以用QDebug()打印出值的名字; 10 11 2. 自定义类类型 12 1)紧邻类型声明后,使用 Q_DECLARE_METATYPE() 宏; 13 2)存入QVariant时,使用 QVariant::fromValue() 静态函数; 14 3)QVariant::type() 的结果不准确,函数返回 QVariant::QWidget*, 而非 QVariant::UserType。但是可以识别到 QVariant::UserType类型; 15 4)可以组合使用 QVariant::typeName() 和 value<T>(),进而得到自定义类类型的值; 16 17 3. 自定义容器类型::与自定义类类型行为一致 18 19 4. Qt提供的非QVariant默认支持的类类型 20 1)不需要使用 Q_DECLARE_METATYPE(); 21 2)前提条件:"it provides a public default constructor, a public copy constructor and a public destructor"。 22 3)如果满足条件“2)",可直接作为自定义类型数据使用; 23 4)如果不满足条件“2)",就是不满足 QMetaType 要求;只能使用类型的指针; 24 25 注意项: 26 1. QVariant::canConvert() 返回true,仅仅表示有转换为类型T能力,并不代表 QVariant::convert()就是true,要根据数据内容来决定。 27 2. QVariant 在类型转换时,原数据不动,新拷贝出一个临时对象进行转换。 28 因此,自定义的类类型,使用 QVariant 存储,一定要具备共有的默认构造函数,共有的拷贝构造函数,公有的析构函数。 29 30 问: 31 1. 怎样可以做到,自定义类型存入 QVariant 时,不需要使用 QVariant::fromValue() 静态函数,有可能吗? 32 2. 自定义类型 QVariant::type()函数返回 QVariant::QWidget*, 而非 QVariant::UserType,是哪里弄错了吗? 33 **************************************************/ 34 35 #ifndef STUDYQVARIANT_H 36 #define STUDYQVARIANT_H 37 38 #include <string> 39 #include <map> 40 41 #include <QObject> 42 #include <QVariant> 43 #include <QDebug> //可以打印注册到 “Qt meta type system” 的自定义类型 44 #include <QWidget> //提供GUI模块里的Qt类型 (代表:widgets模块) 45 #include <QLabel> //提供GUI模块里的Qt类型 (代表:widgets模块) 46 #include <QSharedMemory> //提供QObject子类Qt类型 (代表:core模块) 47 #include <QEvent> //提供非QObject子类的Qt类型 (代表:core模块) 48 #include <QPixmap> //提供非QObject子类的Qt类型 (代表:gui模块) 49 50 /* 51 * 自定义枚举类型如何用 QVariant 来存放 ("未注册元对象系统") 52 * Enum-Type:UserType_CountryEnum 53 */ 54 enum UserType_CountryEnum{China, Russia}; 55 //Q_ENUM(UserType_CountryEnum) "Q_ENUM must be placed in a class that has the Q_OBJECT or the Q_GADGET macro" 56 Q_DECLARE_METATYPE(UserType_CountryEnum) //makes the type known to QMetaType 57 58 59 /* 60 * 自定义类类型如何使用 QVariant 类存放("未注册元对象系统") 61 * Class_Type::UserType_SocialMan 62 */ 63 struct UserType_SocialMan{ 64 QString name = "zhm_xxbs"; 65 int age = 26; 66 }; 67 68 /* 69 * 自定义类类型如何使用 QVariant 类存放 ("注册元对象系统") 70 * Class_Type::UserType_Student 71 */ 72 struct UserType_Student{ 73 QString name = "zhm"; 74 int age = 21; 75 }; 76 Q_DECLARE_METATYPE(UserType_Student) //makes the type known to QMetaType 77 78 /* 79 * 自定义非Qt容器类型如何使用 QVariant 类存放("注册元对象系统") 80 * STL_Type:UserType_IDCard 81 */ 82 typedef std::map<std::string, std::string> UserType_IDCard; 83 Q_DECLARE_METATYPE(UserType_IDCard) 84 85 86 class StudyQVariant : public QObject 87 { 88 Q_OBJECT 89 public: 90 explicit StudyQVariant(QObject *parent = nullptr); 91 92 /* 93 * 自定义枚举类型如何用 QVariant 来存放("注册元对象系统") 94 * Enum-Type:UserType_SexEnum 95 * 96 */ 97 enum UserType_SexEnum{male, female}; 98 Q_ENUM(UserType_SexEnum) //"registers an enum type with the meta-object system" 99 Q_DECLARE_FLAGS(UserType_SexEnums, UserType_SexEnum) 100 101 private: 102 void storeUserTypeData(); //把各种用户自定义类型的值存放在 QVariant 里面 103 void printAllDatas(); //把存放在 QVariant 里面的各种用户自定义类型的值打印出来 104 105 private: 106 QVariantList userType_datas; //存放各种用户自定义数据 107 }; 108 Q_DECLARE_METATYPE(StudyQVariant::UserType_SexEnum) //makes the type known to QMetaType 109 110 #endif // STUDYQVARIANT_H
#include "StudyQVariant.h" StudyQVariant::StudyQVariant(QObject *parent) : QObject(parent) { storeUserTypeData(); printAllDatas(); } void StudyQVariant::storeUserTypeData() { int index = 0; qDebug()<<"把自定义类型数据逐个存入 QVariant 中||||||||||||||||||||||||||||||||||||||||||||"; qDebug()<<"第"<<++index<<"个:"<<"自定义枚举类型(\"未注册 Qt-meta-type-system\")"; userType_datas.push_back(UserType_CountryEnum::China); qDebug()<<"第"<<++index<<"个:"<<"自定义枚举类型(\"已注册 Qt-meta-type-system\")"; userType_datas.push_back(UserType_SexEnum::male); #if 0 //错误写法 qDebug()<<"自定义类类型(\"未注册 Qt-meta-type-system\")"; userType_datas.push_back(UserType_SocialMan()); qDebug()<<"自定义类类型(\"已注册 Qt-meta-type-system\")"; userType_datas.push_back(UserType_Student()); #else qDebug()<<"自定义类类型(\"未注册 Qt-meta-type-system\"), 不可以存入 QVariant"; //userType_datas.push_back(QVariant::fromValue(UserType_SocialMan())); qDebug()<<"第"<<++index<<"个:"<<"自定义类类型(\"已注册 Qt-meta-type-system\")"; userType_datas.push_back(QVariant::fromValue(UserType_Student())); #endif qDebug()<<"第"<<++index<<"个:"<<"自定义非Qt容器类型(\"已注册 Qt-meta-type-system\")"; userType_datas.push_back(QVariant::fromValue(UserType_IDCard{{"zhm", "0001"}})); qDebug()<<"第"<<++index<<"个:"<<"GUI模块里的类型 QColor (\"不用注册 Qt-meta-type-system\")"; userType_datas.push_back(QColor(110, 112, 119)); qDebug()<<"第"<<++index<<"个:"<<"Qt提供GUI模块里的类型 QPoint (\"不用注册 Qt-meta-type-system\")"; userType_datas.push_back(QVariant::fromValue(QPoint(0, 0))); qDebug()<<"Qt提供GUI模块里的类型 QLabel,没有 public-copy 不可以存入QVariant"; //userType_datas.push_back(QVariant::fromValue(QLabel("I'am a label gui"))); qDebug()<<"第"<<++index<<"个:"<<"Qt提供GUI模块里的类型 QLabel* (\"不用注册 Qt-meta-type-system\")"; userType_datas.push_back(QVariant::fromValue(new QLabel("I'am a label gui-pointer"))); qDebug()<<"Qt提供Qbject非控件子类类型 QSharedMemory,没有 public-copy 不可以存入QVariant"; //userType_datas.push_back(QVariant::fromValue(QSharedMemory("I'am a sharedMemory object"))); qDebug()<<"第"<<++index<<"个:"<<"Qt提供Qbject非控件子类类型 QSharedMemory* (\"不用注册 Qt-meta-type-system\")"; userType_datas.push_back(QVariant::fromValue(new QSharedMemory("I'am a sharedMemory object-pointer"))); qDebug(""); } void StudyQVariant::printAllDatas() { qDebug()<<"循环的打印用户自定义类型的数据类型、类型名称、转换为 QString值和数据值||||||||||||||||||||||||||||||||||||||||||||"; foreach (QVariant var, userType_datas) { static int index = 0; qDebug()<<"第"<<++index<<"个:"; qDebug()<<"type():"<<var.type(); ///[枚举类型-失败] [类类型-不准确] qDebug()<<"typeName():"<<var.typeName(); ///[枚举类型-失败] [类类型-成功] //注册到元对象系统的自定义类型,可以转换为对应的名称 qDebug()<<"toString():"<<var.toString(); ///[枚举类型-成功] [类类型-失败] switch (var.type()) { case QVariant::UserType: ///[枚举类型-失败] [类类型-不准确][类类型-能匹配上] qDebug()<<"用户自定义类型"; if (!strcmp(var.typeName(), "UserType_Student")) ///[类类型-成功] { auto _st = var.value<UserType_Student>(); qDebug()<<_st.name<<"; "<<_st.age; } if (!strcmp(var.typeName(), "UserType_IDCard")) { auto _idCard = var.value<UserType_IDCard>(); qDebug()<<QString::fromStdString(_idCard.begin()->first)<<"; "<<QString::fromStdString(_idCard.begin()->second); } if (!strcmp(var.typeName(), "QLabel*")) { qDebug()<<"第"<<index<<"个:"<<var.value<QLabel*>()->text(); } if (!strcmp(var.typeName(), "QSharedMemory*")) { qDebug()<<"第"<<index<<"个:"<<var.value<QSharedMemory*>()->key(); } break; default: qDebug()<<"非用户自定义类型"; break; } } qDebug(""); qDebug()<<"挨个针对性的打印用户自定义类型的值||||||||||||||||||||||||||||||||||||||||||||"; int index = 0; qDebug()<<"第"<<index<<"个:"<<userType_datas.at(index++).value<UserType_CountryEnum>(); ///[枚举类型-失败 (非Q_ENUM)] qDebug()<<"第"<<index<<"个:"<<userType_datas.at(index++).value<UserType_SexEnum>(); ///[枚举类型-成功 (Q_ENUM)] UserType_Student _st = userType_datas.at(index++).value<UserType_Student>(); UserType_Student _sstt = qvariant_cast<UserType_Student>(userType_datas.at(3)); qDebug()<<"第"<<index<<"个:"<<_st.name<<"; "<<_sstt.age; UserType_IDCard _idCard = userType_datas.at(index++).value<UserType_IDCard>(); qDebug()<<"第"<<index<<"个:"<<QString::fromStdString(_idCard.begin()->first)<<"; "<<QString::fromStdString(_idCard.begin()->second); qDebug()<<"第"<<index<<"个:"<<userType_datas.at(index++).value<QColor>(); QPoint _pt = userType_datas.at(index++).toPoint(); qDebug()<<"第"<<index<<"个:"<<_pt; QLabel* _label = userType_datas.at(index++).value<QLabel*>(); qDebug()<<"第"<<index<<"个:"<<_label->text(); delete _label; _label = nullptr; QSharedMemory *_shMe = userType_datas.at(index++).value<QSharedMemory*>(); qDebug()<<"第"<<index<<"个:"<<_shMe->key(); delete _shMe; _shMe = nullptr; qDebug(""); }