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("");
}