一、簡述
QVariant,是Qt中的一個變量類,屬于Qt的底層核心之一,很多子產品都是基于此類。可以支援N多的類型,具體支援多少,請看其類中定義的枚舉:
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,
#if QT_CONFIG(itemmodel)
ModelIndex = QMetaType::QModelIndex,
PersistentModelIndex = QMetaType::QPersistentModelIndex,
#endif
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
};
讓我們來捋一捋,它除了支援int、double、bool等基本類型外,還支援QVariantMap、QVariantHash、QVariantList、QStringList等容器類型,還有一些類似QDateTime、QSize、QRect、QLine、QBitmap、QTransform、QIcon、QBrush、QColor、QFont等各種類型。
除此以外,它還支援自定義類型,真是有個博大的胸襟!!!
似乎Qt自己的類型全部都支援了,不過好像沒有QObject。
是以,遇到類型問題,不要着急,試着往QVariant裡面塞,看看是否已經支援了。
二、用QVariant儲存任意類型與層次資料
我們下面測試中,使用QSetting操作ini配置檔案,寫入QVariant類型鍵值,并讀取,來驗證與寫入内容是否一緻。
QSettings* setting = new QSettings(qApp->applicationDirPath() + "/setting.ini", QSettings::IniFormat);
- 儲存QStringList
// 測試寫入、讀取QStringList
void test_QStringList(QSettings *setting)
{
// 定義
QStringList list;
list << "zhangsan" << "lisi" << "wangxiaohua";
// 寫入
setting->setValue("AppAttribute/QStringList", list);
// 讀取
QStringList listResult = setting->value("AppAttribute/QStringList").toStringList();
qDebug() << listResult;
qDebug() << "-----------------------------------------------\n";
}
運作結果:

2. 儲存結構體
// 測試寫入、讀取結構體對象
void test_StructObject(QSettings *setting)
{
// 定義結構體
QMap<QString, QVariant> person;
person["name"] = "zhangsan";
person["age"] = 25;
person["sex"] = "man";
// 寫入
setting->setValue("AppAttribute/Person", person);
// 讀取
QMap<QString, QVariant> result = setting->value("AppAttribute/Person").toMap();
qDebug() << result;
qDebug() << "-----------------------------------------------\n";
}
運作結果:
3. 儲存結構體嵌套
// 測試寫入、讀取結構體下面嵌套結構體
void test_NestedStructObject(QSettings *setting)
{
// 定義嵌套結構體
QMap<QString, QVariant> car;
car["brand"] = "Audi";
car["price"] = 20;
QMap<QString, QVariant> person;
person["name"] = "zhangsan";
person["age"] = 25;
person["sex"] = "man";
person["car"] = car;
// 寫入
setting->setValue("AppAttribute/PersonCar", person);
// 讀取
QMap<QString, QVariant> result = setting->value("AppAttribute/PersonCar").toMap();
qDebug() << result;
qDebug() << "-----------------------------------------------\n";
}
運作結果:
4. 儲存對象清單
// 測試寫入、讀取結構體對象清單
void test_StructObjectList(QSettings *setting)
{
// 定義結構體清單
QMap<QString, QVariant> person1;
person1["name"] = "zhangsan";
person1["age"] = 25;
person1["sex"] = "man";
QMap<QString, QVariant> person2;
person2["name"] = "lisi";
person2["age"] = 30;
person2["sex"] = "woman";
QList<QVariant> list;
list << person1 << person2;
// 寫入
setting->setValue("AppAttribute/Persons", list);
// 讀取
QList<QVariant> result = setting->value("AppAttribute/Persons").toList();
qDebug() << result;
qDebug() << "-----------------------------------------------\n";
}
運作結果:
5. 儲存對象樹
// 測試寫入、讀取結構體對象樹
void test_StructObjectTree(QSettings *setting)
{
// 定義結構體對象樹
QMap<QString, QVariant> car1_0;
car1_0["brand"] = "Audi";
car1_0["price"] = 20;
QMap<QString, QVariant> car1_1;
car1_1["brand"] = "bmw";
car1_1["price"] = 30;
QMap<QString, QVariant> person1;
person1["name"] = "zhangsan";
person1["age"] = 25;
person1["sex"] = "man";
QList<QVariant> cars_1;
cars_1 << car1_0 << car1_1;
person1["cars"] = cars_1;
/
QMap<QString, QVariant> car2_0;
car2_0["brand"] = "VOLVO";
car2_0["price"] = 32;
QMap<QString, QVariant> car2_1;
car2_1["brand"] = "Benz";
car2_1["price"] = 40;
QMap<QString, QVariant> person2;
person2["name"] = "lisi";
person2["age"] = 31;
person2["sex"] = "woman";
QList<QVariant> cars_2;
cars_2 << car2_0 << car2_1;
person2["cars"] = cars_2;
QList<QVariant> persons;
persons << person1 << person2;
// 寫入
setting->setValue("AppAttribute/PersonTree", persons);
// 讀取
QList<QVariant> personsResult = setting->value("AppAttribute/PersonTree").toList();
qDebug() << personsResult;
qDebug() << "-----------------------------------------------\n";
}
運作結果:
結構越複雜,toString之後,可讀性越低。
三、總結
QVariant實際上是實作了,以一種通用的類型,來有效組織任意類型,層次的資料,并實作了針對任意類型,層次資料的序列化、反序列化。
即對任意類型、層次資料可以自動轉QString,對QString也可以自動轉成最初的結構資料。
QVariant類似于實作了XML這樣的可伸縮資料結構,而XML需要手寫各種标簽群組織層次。QVariant隻需要你把資料按你自己的層次結構放進去就可以了,至于如何序列化,反序列化,你都不用關心。
正如,上面的測試代碼,如果你覺得QVariant是一個值,那就錯了,它可以是Any things。QSettings的設定鍵值方法:
void setValue(const QString &key, const QVariant &value);