QVariant类
类似于最常见的Qt数据类型的联合。由于C++
禁止联合类型包括具有非默认构造函数
或析构函数
的类型,大多数有趣的Qt类
不能在联合中使用。如果没有QVariant
,则QObject::property()
和数据库操作等将会受到影响。
QVariant
对象同时持有一个单一类型(T)
的单一值(一些类型是多值的,例如字符串列表)。您可以通过convert()
将其转换为不同的类型T,使用其中一个toT()
函数(例如toSize()
)获取其值,并使用canConvert()
检查该类型是否可以转换为特定类型。
以toT()
(例如toInt()
,toString()
)命名的方法是const
的。如果您请求存储的类型,则它们返回存储对象的副本。如果要求使用存储的类型生成的类型,则toT()
会复制和转换并保留对象本身不变。如果要求一种无法从存储的类型生成的类型,则结果取决于该类型;有关详细信息,请参见函数文档。
以下是一些示例代码,演示了QVariant
的用法:
QDataStream out(...);
QVariant v(123); // variant现在包含一个int
int x = v.toInt(); // x=123
out << v; // 在out中写入类型标记和一个int
v = QVariant("hello");// variant现在包含一个QByteArray
v = QVariant(tr("hello")); // variant现在包含一个QString
int y = v.toInt(); // y=0,因为v不能转换为int
QString s = v.toString(); // s=tr("hello") (参见QObject::tr())
out << v; // 在out中写入类型标记和一个QString
...
QDataStream in(...); //(打开先前编写的流)
in >> v; //读取int变量
int z = v.toInt(); // z=123
qDebug("Type is %s",v.typeName()); // 打印“Type is int”
v = v.toInt()+100; // variant现在拥有值223
v = QVariant(QStringList());
您甚至可以将QList
和QMap
类型的值存储在variant
中,因此您可以轻松构建任意类型的任意复杂度的数据结构。这非常强大和灵活,但可能比在标准数据结构中存储特定类型的方式低效。
QVariant
还支持空值的概念,在该概念下,您可以拥有未设置值的定义类型。但是,请注意,只有在设置了值时,QVariant
类型才能进行强制转换。
QVariant x, y(QString()), z(QString(""));
x.convert(QVariant::Int);
// x.isNull() == true
// y.isNull() == true, z.isNull() == false
QVariant
可以扩展以支持Type
枚举中未提到的其他类型。
由于QVariant
是Qt Core
模块的一部分,因此它无法向Qt GUI
中定义的数据类型(如QColor
、QImage
和QPixmap
)提供转换函数。换句话说,没有toColor()
函数。相反,您可以使用QVariant::value()
或qvariant_cast()
模板函数。例如:
QVariant variant;
...
QColor color = variant.value<QColor>();
所有由QVariant
支持的数据类型,包括与GUI
相关的类型,都支持反向转换(例如,从QColor
到QVariant
),这是自动的。
QColor color = palette().background().color();
QVariant variant = color;
canConvert()
和convert()
当连续使用canConvert()
和convert()
时,canConvert()
可能会返回true
,但convert()
会返回false
。这通常是因为canConvert()仅
报告了QVariant
在给定适当数据的情况下转换类型的一般能力;仍然可能提供实际上无法转换的数据。
例如,当在包含字符串的variant
上调用canConvert(Int)
时,它将返回true
,因为原则上,QVariant
能够将数字字符串转换为整数。然而,如果字符串包含非数字字符,则无法将其转换为整数,任何尝试将其转换将失败。因此,两个函数都返回true
对于成功的转换来说是很重要的。
QVariant()
构造一个无效的变量。QVariant(Type type)
构造一个空的类型为type的变量。QVariant(const QRegularExpression &re)
构造一个新的变量,带有正则表达式值re。该函数在Qt 5.0中引入。QVariant(const QUrl &val)
构造一个新的变量,值为val的url。QVariant(const QEasingCurve &val)
构造一个新的带有easing curve值val的变量。该函数在Qt 4.7中引入。QVariant(const QUuid &val)
构造一个值为uuid值val的新变量。该函数在Qt 5.0中引入。QVariant(const QModelIndex &val)
构造一个新的带有QModelIndex值val的变量。该函数在Qt 5.0中引入。QVariant(const QPersistentModelIndex &val)
构造一个新的带有QPersistentModelIndex值val的变量。该函数在Qt 5.5中引入。QVariant(const QJsonValue &val)
构造一个新的带有json值val的变量。该函数在Qt 5.0中引入。QVariant(const QJsonObject &val)
构造一个新的带有json对象值val的变量。该函数在Qt 5.0中引入。QVariant(const QJsonArray &val)
构造一个新的带有json数组值val的变量。该函数在Qt 5.0中引入。QVariant(const QJsonDocument &val)
构造一个新的带有json文档值val的变量。该函数在Qt 5.0中引入。QVariant(QVariant &&other)
移动构造一个QVariant实例,使其指向other指向的同一对象。该函数在Qt 5.2中引入。QVariant(int typeId, const void *copy)
构造类型为typeId的变量,并且如果copy不为0则初始化为copy。注意,您必须传递要存储的变量的地址。通常情况下,您不需要使用此构造函数,而是使用. QVariant:: fromValue()
来从由QMetaType::VoidStar和QMetaType::QObjectStar表示的指针类型构造变量。另请参见. QVariant:: fromValue()
和QMetaType::Type。QVariant(const QVariant &p)
构造一个变量的副本,该变量作为此构造函数的参数传递。QVariant(QDataStream &s)
从数据流s中读取变量。QVariant(int val)
构造一个带有整数值val的新变量。QVariant(uint val)
构造一个带有无符号整数值val的新变量。QVariant(qlonglong val)
构造一个带有长整型值val的新变量。QVariant(qulonglong val)
构造一个带有无符号长整型值val的新变量。QVariant(bool val)
构造一个带有布尔值val的新变量。QVariant(double val)
构造一个带有浮点值val的新变量。QVariant(float val)
构造一个带有浮点值val的新变量。该函数在Qt 4.6中引入。QVariant(const char *val)
构造一个带有val字符串值的新变量。该变量会将val创建为一个QString的深拷贝,并假定输入val的编码为UTF-8。请注意,val被转换为QString以便存储在变量中,. QVariant:: userType()
将为该变量返回QMetaType::QString。可以通过在编译应用程序时定义QT_NO_CAST_FROM_ASCII来禁用该操作符。QVariant(const QByteArray &val)
构造具有bytearray值val的新变量。QVariant(const QBitArray &val)
构造具有bitarray值val的新变量。QVariant(const QString &val)
构造一个具有字符串值val的新变量。QVariant(QLatin1String val)
构造一个具有字符串值val的新变量。QVariant(const QStringList &val)
构造一个具有字符串列表值val的新变量。QVariant(QChar c)
构造一个具有char值c的新变量。QVariant(const QDate &val)
构造一个具有日期值val的新变量。QVariant(const QTime &val)
构造一个具有时间值val的新变量。QVariant(const QDateTime &val)
构造一个具有日期/时间值val的新变量。QVariant(const QList &val)
构造一个具有列表值val的新变量。QVariant(const QMap &val)
构造一个具有QVariant映射val的新变量。QVariant(const QHash &val)
构造一个具有QVariant哈希val的新变量。QVariant(const QSize &val)
构造一个具有值为val的大小值的新变量。QVariant(const QSizeF &val)
构造一个具有值为val的大小值的新变量。QVariant(const QPoint &val)
构造一个具有代表点值val的新变量。QVariant(const QPointF &val)
构造一个具有代表点值val的新变量。QVariant(const QLine &val)
构造一个具有表示线值val的新变量。QVariant(const QLineF &val)
构造一个具有表示线值val的新变量。QVariant(const QRect &val)
构造一个具有表示矩形值val的新变量。QVariant(const QRectF &val)
构造一个具有表示矩形值val的新变量。QVariant(const QLocale &l)
构造一个具有本地值l的新变量。QVariant(const QRegExp ®Exp)
构造一个新的正则表达式值regExp的变量。~QVariant()
销毁QVariant和所包含的对象。clear()
。这个析构函数调用clear()
,但因为它是析构函数,所以调用的是QVariant:: clear()
,而不是子类的clear()
。bool QVariant::canConvert(int targetTypeId) const
:如果变量的类型可以转换为请求的类型targetTypeId
,则返回true
。在调用toInt()
、toBool()
等方法时,会自动进行此类转换。 以下转换会自动完成:如果QVariant包含指向QObject派生类型的指针,则如果可以进行与targetTypeId所描述的类型相对应的qobject_cast,则此函数也将返回true。请注意,这仅适用于使用Q_OBJECT宏的QObject子类。
如果QVariant包含一个顺序容器,则如果targetTypeId为QVariantList,则该函数也将返回true。可以在不将其提取为(复制的)QVariantList的情况下迭代容器的内容。
QList<int> intList = {7, 11, 42};
QVariant variant = QVariant::fromValue(intList);
if (variant.canConvert<QVariantList>()) {
QSequentialIterable iterable = variant.value<QSequentialIterable>();
// Can use foreach:
foreach (const QVariant &v, iterable) {
qDebug() << v;
}
// Can use C++11 range-for:
for (const QVariant &v : iterable) {
qDebug() << v;
}
// Can use iterators:
QSequentialIterable::const_iterator it = iterable.begin();
const QSequentialIterable::const_iterator end = iterable.end();
for ( ; it != end; ++it) {
qDebug() << *it;
}
}
结果:
这需要容器的value_type本身是一个元类型。类似地,如果QVariant包含一个顺序容器,则如果targetTypeId为QVariantHash或QVariantMap,则该函数也将返回true。可以在不将其提取为(复制的)QVariantHash或QVariantMap的情况下迭代容器的内容:
QHash<int, QString> mapping;
mapping.insert(7, "Seven");
mapping.insert(11, "Eleven");
mapping.insert(42, "Forty-two");
QVariant variant = QVariant::fromValue(mapping);
if (variant.canConvert<QVariantHash>()) {
QAssociativeIterable iterable = variant.value<QAssociativeIterable>();
// Can use foreach over the values:
foreach (const QVariant &v, iterable) {
qDebug() << v;
}
// Can use C++11 range-for over the values:
for (const QVariant &v : iterable) {
qDebug() << v;
}
// Can use iterators:
QAssociativeIterable::const_iterator it = iterable.begin();
const QAssociativeIterable::const_iterator end = iterable.end();
for ( ; it != end; ++it) {
qDebug() << *it; // The current value
qDebug() << it.key();
qDebug() << it.value();
}
}