Qt QVariant详细用法
一、简介QVariant可以存储各种数据类型,QVariant行为类似于C/C++的union, 但在Qt中比union强大很多, QVariant内置支持所有QMetaType::Type里声明的类型如:int,QString,QFont,QColor等,甚至QList,QMap<QString, QVariant>等组成的任意复杂类型。简单的说QVariant可以存储任意数据类型,
一、简介
QVariant可以存储各种数据类型,QVariant行为类似于C/C++的union, 但在Qt中比union强大很多, QVariant内置支持所有QMetaType::Type里声明的类型如:int,QString,QFont,QColor等,甚至QList,QMap<QString, QVariant>等组成的任意复杂类型。简单的说QVariant可以存储任意数据类型,表现的类似弱语言,如JS中的var如,包括容器类型的值,如QStringlist。Qt的很多功能都是建立在QVariant类的基础之上的,如Qt对象属性及数据库功能等,在代码片段中主要分两种情况讨论QVariant的应用:
二、代码片段
//一.基本数据类型
QVariant number(27); //定义一个名为number的QVariant变量,并初始值为27,那么在这里相当于int型
qDebug()<<number;//打印结果:QVariant(int, 27)
qDebug()<<number;
QStringList strList;
strList.append("who");
strList.append("are");
strList.append("you");
QMap<QString,QVariant> myMap;
myMap.insert("one",45); //int
myMap.insert("two","hello"); //qstring
myMap.insert("three",QColor(0,0,0)); //qcolor
myMap.insert("four",strList); //QStringList 类型,就是所谓的容器类型值
// myMap.insert("five",map); //尝试了一下,结果这里无法转化,可能是不支持这种数据类型吧,map为QMap类型
QMapIterator<QString,QVariant> x(myMap);
for(;x.hasNext();)
{
qDebug()<<x.key()<<x.next().value();
#if 0
if(x.next().value().type() == QVariant::StringList) //判断QVariant类型,这里是判断是否为QStringList,更多的可以找手册查询一下
{
// qDebug()<<x.key();
QString str=QString("%1").arg(x.key()); //找到数据类型为QStringList的值对应的键,再通过键找到值,这里不能直接用x.next().value(),因为next会跳到下一个键值对
qDebug()<<str;
QStringList myList=myMap[str].toStringList(); //必要的转化
for(int m=0;m<myList.size();m++) //遍历QStringList
{
qDebug()<<myList[m];
}
}
#endif
// qDebug()<<x.next().value().type();
}
//二.自定义数据类型
因为自定义数据类型是系统中不存在的,即使创建,也需要注册一下,方便编译器识别
struct myStruct //自定义的数据类型
{
int age;
char name[10];
};
Q_DECLARE_METATYPE(myStruct) //注册,必不可少
//上面这部分代码一般在头文件中完成
// myStruct stu= //结构体初始化
// {
// 100,
// "wangLei"
// };
myStruct stu;
stu.age = 100;//也可以先定义变量后这样赋值
strcpy(stu.name,"Hello./n");
QVariant v;
v.setValue(stu); //设置QVariant的值
qDebug()<<"v:"<<v;
myStruct s; //这部分代码主要是将QVariant类再转化为myStruct类,其他QVariant类转化成其他类也可用这种方法
s=v.value<myStruct>();
qDebug()<<"s:"<<s.age<<s.name;
如果要使自定义类型或其他非QMetaType内置类型在QVariant中使用,必须使用该宏Q_DECLARE_METATYPE
如果非QMetaType内置类型要在信号与槽中使用,必须使用qRegisterMetaType。
三、源码赏析
1.数据成员
QVariant的数据成员很简单,只有一句:
Private d;
Private 定义:
struct Private
{
union Data
{
char c;
uchar uc;
short s;
signed char sc;
ushort us;
int i;
uint u;
long l;
ulong ul;
bool b;
double d;
float f;
qreal real;
qlonglong ll;
qulonglong ull;
QObject *o;
void *ptr;
PrivateShared *shared;
} data;
uint type : 30;
uint is_shared : 1;
uint is_null : 1;
};
Private是一个结构体,核心数据成员是data,是一个union数据类型,可以存储各种整型,浮点型,QObject类指针,任意指针,共享数据指针。type指示了data中存储的数据类型,is_shared代表数据是否是共享的,is_null代表data是否为空。
那么看看type可以指示的类型有哪些:
enum Type {
Invalid = QMetaType::UnknownType,
Bool = QMetaType::Bool,
Int = QMetaType::Int,
UInt = QMetaType::UInt,
LongLong = QMetaType::LongLong,
ULongLong = QMetaType::ULongLong,
Double = QMetaType::Double,
Char = QMetaType::QChar,
Map = QMetaType::QVariantMap,
List = QMetaType::QVariantList,
String = QMetaType::QString,
StringList = QMetaType::QStringList,
ByteArray = QMetaType::QByteArray,
BitArray = QMetaType::QBitArray,
Date = QMetaType::QDate,
Time = QMetaType::QTime,
DateTime = QMetaType::QDateTime,
Url = QMetaType::QUrl,
Locale = QMetaType::QLocale,
Rect = QMetaType::QRect,
RectF = QMetaType::QRectF,
Size = QMetaType::QSize,
SizeF = QMetaType::QSizeF,
Line = QMetaType::QLine,
LineF = QMetaType::QLineF,
Point = QMetaType::QPoint,
PointF = QMetaType::QPointF,
RegExp = QMetaType::QRegExp,
RegularExpression = QMetaType::QRegularExpression,
Hash = QMetaType::QVariantHash,
EasingCurve = QMetaType::QEasingCurve,
Uuid = QMetaType::QUuid,
ModelIndex = QMetaType::QModelIndex,
PersistentModelIndex = QMetaType::QPersistentModelIndex,
LastCoreType = QMetaType::LastCoreType,
Font = QMetaType::QFont,
Pixmap = QMetaType::QPixmap,
Brush = QMetaType::QBrush,
Color = QMetaType::QColor,
Palette = QMetaType::QPalette,
Image = QMetaType::QImage,
Polygon = QMetaType::QPolygon,
Region = QMetaType::QRegion,
Bitmap = QMetaType::QBitmap,
Cursor = QMetaType::QCursor,
KeySequence = QMetaType::QKeySequence,
Pen = QMetaType::QPen,
TextLength = QMetaType::QTextLength,
TextFormat = QMetaType::QTextFormat,
Matrix = QMetaType::QMatrix,
Transform = QMetaType::QTransform,
Matrix4x4 = QMetaType::QMatrix4x4,
Vector2D = QMetaType::QVector2D,
Vector3D = QMetaType::QVector3D,
Vector4D = QMetaType::QVector4D,
Quaternion = QMetaType::QQuaternion,
PolygonF = QMetaType::QPolygonF,
Icon = QMetaType::QIcon,
LastGuiType = QMetaType::LastGuiType,
SizePolicy = QMetaType::QSizePolicy,
UserType = QMetaType::User,
LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
};
不仅包含了基本数据类型Bool、Int、Double等,还包含了core中的数据类型QChar、QPoint、QSize、QRect、QDateTime、QString,容器类型QMap、QList、QHash,gui中的数据类型QColor、QFont、QPalette、QImage、QVector、QMatrix等,还可以添加自定义类型QMetaType::User
2. 构造函数
可以存储Type中的数据类型,构造函数重载自然很多,随便列举些:
QVariant(bool b);
QVariant(double d);
QVariant(const QString &string);
QVariant(const QList<QVariant> &list);
QVariant(const QMap<QString,QVariant> &map);
QVariant(const QHash<QString,QVariant> &hash);
QVariant(const QVariant &other);
也可以通过setValue赋值
template<typename T>
inline void setValue(const T &value);
3. 取值
在已知存储类型的情况下,可以直接使用如下函数:
int toInt(bool *ok = Q_NULLPTR) const;
uint toUInt(bool *ok = Q_NULLPTR) const;
qlonglong toLongLong(bool *ok = Q_NULLPTR) const;
qulonglong toULongLong(bool *ok = Q_NULLPTR) const;
bool toBool() const;
double toDouble(bool *ok = Q_NULLPTR) const;
float toFloat(bool *ok = Q_NULLPTR) const;
qreal toReal(bool *ok = Q_NULLPTR) const;
QByteArray toByteArray() const;
QBitArray toBitArray() const;
QString toString() const;
QStringList toStringList() const;
QChar toChar() const;
QDate toDate() const;
QTime toTime() const;
QDateTime toDateTime() const;
QList<QVariant> toList() const;
QMap<QString, QVariant> toMap() const;
QHash<QString, QVariant> toHash() const;
#ifndef QT_NO_GEOM_VARIANT
QPoint toPoint() const;
QPointF toPointF() const;
QRect toRect() const;
QSize toSize() const;
QSizeF toSizeF() const;
QLine toLine() const;
QLineF toLineF() const;
QRectF toRectF() const;
#endif
QLocale toLocale() const;
#ifndef QT_NO_REGEXP
QRegExp toRegExp() const;
#endif // QT_NO_REGEXP
#ifndef QT_BOOTSTRAPPED
#ifndef QT_NO_REGULAREXPRESSION
QRegularExpression toRegularExpression() const;
#endif // QT_NO_REGULAREXPRESSION
QUrl toUrl() const;
QEasingCurve toEasingCurve() const;
QUuid toUuid() const;
QModelIndex toModelIndex() const;
QPersistentModelIndex toPersistentModelIndex() const;
QJsonValue toJsonValue() const;
QJsonObject toJsonObject() const;
QJsonArray toJsonArray() const;
QJsonDocument toJsonDocument() const;
#endif // QT_BOOTSTRAPPED
未知情况下,可以先使用canConvert进行查询是否可以转化,然后调用对应toXXX。
bool canConvert(int targetTypeId) const;
template<typename T>
bool canConvert() const;
自定义数据类型可使用value取值
template<typename T>
inline T value() const
{ return qvariant_cast<T>(*this); }
更多推荐
所有评论(0)