大家好,欢迎来到IT知识分享网。
一、QVariant的概述
QVariant是Qt中一个强大的变体类,提供了一种通用的方式来存储Qt对象及其他类的值,可以以类似于指针的方式存储任意类型的值。
由于QVariant是一个通用的类型,因此可以在不丢失语义的情况下存储几乎所有数据类型。作为一个变体类型,它支持自我描述、值类型检查和动态转换等特性,具有安全性和利用性。
它可以存储任何数据类型的值,并提供了一些方便的方法来转换这些值,同时也可以在Qt中使用信号和槽机制传递任何类型的数据。
QVariant 这个类型充当着最常见的数据类型的联合。QVariant 可以保存很多Qt的数据类型,包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、 QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize和QString,并且还有C++基本类型,如 int、float等。
当然,如果支持的类型没有想要的,没关系,QVariant也可以支持自定义的数据类型。被QVariant存储的数据类型需要有一个默认的构造函数和一个拷贝构造函数。为了实现这个功能,首先必须使用Q_DECLARE_METATYPE()宏。通常会将这个宏放在类的声明所在头文件的下面:
Q_DECLARE_METATYPE(MyClass)
注意:千万别想着一步到位,QVariant存入的是什么类型,就将其转出什么类型!!!
二、QVariant的使用
1、QVariant的使用方法
QVariant var = 123; int intValue = var.toInt(); // 将QVariant 转换为int类型 QString strValue = var.toString(); // 将QVariant 转换为QString类型 QVariant var; var.setValue(42); // 存储整数 42 int i = var.toInt(); // 获取整数 42 var.setValue("Hello"); // 存储字符串 "Hello" QString str = var.toString(); // 获取字符串 "Hello" var.setValue(QColor(Qt::red)); // 存储 QColor QColor color = var.value<QColor>(); // 获取 QColor
2、QVariant存储的类型判断
可以使用QVariant::type()函数,返回QVariant存储的值的类型,常用类型还可以使用相应的函数进行判断,例如:
QVariant var = "Hello, World"; if(var.type() == QVariant::String){ qDebug() << "The QVariant stored a string value!"; }
3、QVariant的类型转换
QVariant也支持用于显式转换的类型强制转换操作符。如果无法进行统一的操作,则转换失败,这时可以使用canConvert()函数进行转换:
QVariant var = 999; if(var.canConvert()){ QString str = var.value(); } QVariant var; var.setValue(42); // 存储整数 42 if (var.canConvert<int>()) { int value = var.value<int>(); // 将 QVariant 对象转换为 int 类型 qDebug() << "Value is: " << value; } else { qDebug() << "Cannot convert to int!"; }
4、QVariant跟list之间的转换
任何的qt的类型要转成QVariant都需要先看下qt的帮助文档,查看该qt类型是否是一个基本的类型。例如
QVariantList--实际上就是--》QList<QVariant> QVariantMap--实际上就是--》QMap<QString, QVariant>
将一个QList转成一个QVariant类型:
Qlist<QVariant> list; list<<QVariant::fromValue(90)<<QVariant::fromValue(89)<<QVariant::fromValue(67); QVariant temp1; temp1 = QVariant::fromValue(list);
5、放在 Qmap 当中使用:
QMap<QString, QVariant> qmap; qmap["int"] = 2000; qmap["double"] = 99.22; qmap["string"] = "hello"; qmap["color"] = QColor(1,2,3); qDebug() << qmap["int"] << qmap["int"].toInt(); // QVariant(int, 2000) 2000 qDebug() << qmap["double"] << qmap["double"].toDouble(); // QVariant(double, 99.22) 99.22 qDebug() << qmap["string"] << qmap["string"].toString(); // QVariant(QString, "hello") "hello" qDebug() << qmap["color"] << qmap["color"].value<QColor>(); // QVariant(QColor, QColor(ARGB 1, 0.00, 0.00, 0.0)) QColor(ARGB 1, 0.00, 0.00, 0.0)
6、示例
支持的类型。对于QVariant支持的类型,可直接赋值,但是取值时,对于存入的是什么类型,取出也要为这个类型。
QVariant var; var.setValue(12); int data=var.toInt(); QVariant var=12; int data=var.toInt();
对于不支持的C++基础数据类型,如 short char,先通过toInt()转化为int类型,然后再将int转为其原本的数据类型。
//-------------------------------char-------------------------- //char -> QVariant QVariant var='B'; qDebug()<<var; //QVariant(int, 66) // QVariant ->char char channel=var.toInt(); //------------------------------short-------------------------- //short -> QVariant short dataType=12; QVariant var2=dataType; qDebug()<<var2; //QVariant(int, 12) //QVariant -> short short temp=(short)var2.toInt();
保存指针,感觉这个比较强大,也比较容易用到。如
//保存 QVariant var=QVariant::fromValue((void*)event); //获取 QPaintEvent* e=(QPaintEvent*)var.value<void*>();
三、QVariant存储自定义类型
QVariant可以存储自定义类型,只需要实现该类型的QDataStream插入和提取操作符,然后调用Q_DECLARE_METATYPE()宏为该类型添加元数据:
class MyCustomType { public: MyCustomType() {} MyCustomType(int i, QString str) : m_i(i), m_str(str) {} int m_i; QString m_str; }; Q_DECLARE_METATYPE(MyCustomType); QDataStream& operator<<(QDataStream &out, const MyCustomType &val) { out << val.m_i << val.m_str; return out; } QDataStream& operator>>(QDataStream &in, MyCustomType &val) { in >> val.m_i >> val.m_str; return in; }
struct MyClass{ int id; QString name; }; Q_DECLARE_METATYPE(MyClass) //存储数据 MyClass myClass; myClass.id=0; myClass.name=QString("LiMing"); data[0]=QString("ddd"); data[1]=123; data[3]=QVariant::fromValue(myClass); //获取数据 QString str=data.value(0).toString(); int val=data.value(1).toInt(); if(data[3].canConvert<MyClass>()) { MyClass myClass=data[3].value<MyClass>(); int id=myClass.id; QString name=myClass.name; }
结构体跟QVariant之间的转换
struct tytemp { unsigned int target; unsigned int current; }; Q_DECLARE_METATYPE(tytemp) /*将结构体变成QVariant*/ QVariant temp1; tytemp info; info.target = 90; info.current = 100; temp1 = QVariant::fromValue(info); /*将QVariant变成结构体*/ tytemp tempinfo= temp1.value<tytemp>()
使用自定义的枚举作为参数
enum CusType { TYPE_ONE = 1, TYPE_TWO = 2, TYPE_THREE = 3 }; Q_DECLARE_METATYPE(CusType) void MainWindow::dealType() { bool ok = false; //QVariant 转换为 QMeataType类型 QVariant v1(123); qDebug() << "v1.typeName = " << v1.typeName() << ", canConvert<int>() = " << v1.canConvert<int>() << ", int = " << v1.toInt(&ok) << ", ok = " << ok; QVariant v2("123"); qDebug() << "v2.typeName = " << v2.typeName() << ", canConvert<int>() = " << v2.canConvert<int>() << ", int = " << v2.toInt(&ok) << ", ok = " << ok; QVariant v3("123s"); qDebug() << "v3.typeName = " << v3.typeName() << ", canConvert<int>() = " << v3.canConvert<int>() << ", int = " << v3.toInt(&ok) << ", ok = " << ok; QString str3 = v3.value<QString>(); QVariant v4(tr("123")); qDebug() << "v4.typeName = " << v4.typeName() << ", canConvert<int>() = " << v4.canConvert<int>() << ", int = " << v4.toInt(&ok) << ", ok = " << ok; //自定义类型转换为 QVariant QVariant v5 = QVariant::fromValue(CusType::TYPE_ONE); qDebug() << "v5.typeName = " << v5.typeName() << ", canConvert<int>() = " << v5.canConvert<int>() << ", int = " << v5.toInt(&ok) << ", ok = " << ok; //QVariant 转换为 自定义类型 int i5 = v5.value<CusType>(); qDebug() << "i5 = " << i5; // i5=1 }
四、QVariant实现模板函数
QVariant还可以使用模板函数,实现任意类型转换:
template inline QVariant toVariant(const T &value){ return QVariant::fromValue(value); }
使用方法:
int intValue = 123; QVariant var1 = toVariant(intValue); QVariant var2 = toVariant(QString("Hello, World"));
五、Json转为QVariant
QJsonObject转为QVariant,QVariant的构造函数是包含这些类型的。
QJsonObject obj; obj.insert("name1","val1"); obj.insert("name2","val2"); obj.insert("name3","val3"); QJsonArray arr; for(int i=0;i<5;i++) arr.append(i); obj.insert("name4",arr); QVariant var(obj); //QJsonArray转为QVariant也是一样的 QVariant var2(arr); //QJsonDocument转为QVariant QVariant var3(QJsonDocument(obj));
一般为了方便本地调用,是直接将其转化为QVariantMap、QVariantHash或QVariantList
QVariantList varList=arr.toVariantList(); QVariantMap varMap=obj.toVariantMap(); QVariantHash varHash=obj.toVariantHash();
使用的时候,直接调用
qDebug()<<"varName_1="<<varMap.value("name1").toString(); qDebug()<<"varName_2="<<varHash.value("name2").toString(); for(int i=0;i<varList.count();i++){ qDebug()<<varList.at(i).toInt(); }
六、QVariant转为Json
这个只需要直接转换就可以了,前提是QVariant原本存入是类型就是Json
const QJsonObject& _obj=var.toJsonObject();
若存入QVariant的类型是QVariantMap,那么就要多一个步骤了
QVariant var4(obj.toVariantMap()); const QJsonObject& __obj=QJsonObject::fromVariantMap(var4.toMap()); qDebug()<<__obj.value("name1").toString();
七、QVariant转为QByteArray
看帮助文档,可以看出QVariant有方法可以直接转化成QByteArray,就直接将其转换为QByteArray,那么你拿到的QByteArray很可能就是空的~
我还是强调存入QVariant的是什么,你就要直接将其转换为什么,至于其他的类型,再继续转换。
若存入QVariant的是QJsonObject之类
qDebug()<<QJsonDocument(var.toJsonObject()).toJson(QJsonDocument::Compact);
若存入的是QVariant的是QVariantMap之类
qDebug()<<QJsonDocument::fromVariant(var4).toJson();
若存入的是QByteArray,那么什么好说的,当然直接转换,当然,出来的结果不是空的,除非你存入的是空的字节数组
QJsonDocument doc(obj); QVariant var5(doc.toJson(QJsonDocument::Compact)); qDebug()<<var5.toByteArray();
八、应用场景
九、QVariant的性能分析
使用QVariant需要注意一些性能问题,QVariant不同于其他基础数据类型,因此不要将其用于高性能的应用程序或过于频繁的任务。
QVariant的存储需要占用一定的内存,因此在存储某些类型时应格外小心。理论上,QVariant存储的值的大小没有任何限制,但是如果存储的值太大,移动和复制操作可能会产生显著的开销。
QVariant本身的使用也可以产生性能影响,包括类型检查、值提取和转换等。因此,在性能要求高的场景中可以使用原始的基础数据类型来替代QVariant,或者使用QVariant来存储类型稳定的小型数据结构。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/112544.html
