我有一个包含不同类的对象的QVariantList。我需要修改列表中一个对象的成员变量。我的代码运行了,但是对象没有改变(看起来对象的一个副本正在被改变)。下面是与我所做的类似的示例代码:
QVariantList l;
QVariant v = l.at(0);
MyClass c;
if (v.canConvert<MyClass >()) c = v.value<MyClass >();
c.myfield(10);
// l.at(0) has not changed
我也试过:
qvariant_cast<MyClass>(v).myfield(10)
,但无差异。我想改变对象的myfield,而不是对象的副本。我如何修改QVariant v中持有的对象的'myfield'字段
你的对象第一次被复制到这里:
QVariant v = l.at(0);
v
包含一个新对象。所有的操作都会改变这个副本,而不是列表中的对象。
改成这样:
QVariant& v = l.at(0);
现在您有了一个对列表中存储的正确QVariant的引用。
qvariant_cast
也创建了一个副本:
T qvariant_cast ( const QVariant & value )
和v.value<MyClass >()
too:
T QVariant::value () const
这就是为什么您需要将v
转换为MyClass
,更改它并将其分配回v
。下面是一个可能的解决方案:
QVariantList l;
QVariant v& = l.at(0);
if (v.canConvert<MyClass >())
{
MyClass c = v.value<MyClass>();
c.myfield(10);
v = QVariant::fromValue(c);
}
不使用引用,你也可以使用QVariant v = l.at(0);
,但在最后调用l[0] = QVariant::fromValue(c)
。
尝试使用
c.myfield(10);
v = c;
参见QVariant文档中指定的以下示例。
QDataStream in(...); // (opening the previously written stream)
in >> v; // Reads an Int variant
int z = v.toInt(); // z = 123
qDebug("Type is %s", // prints "Type is int"
v.typeName());
v = v.toInt() + 100; // The variant now hold the value 223
v = QVariant(QStringList());
你可以在这里参考QVariant文档
QVariant::data()
是你的朋友。它在Qt6之前没有正式文档,但是您也可以安全地在Qt5中使用它。
#include <QCoreApplication>
#include <QVariant>
#include <QDebug>
class MyClass
{
public:
int myfield {0};
};
Q_DECLARE_METATYPE(MyClass)
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qRegisterMetaType<MyClass>();
QVariantList l;
{
QVariant t;
MyClass mc;
t.setValue(mc);
l.append(t);
l.append(t);
l.append(t);
}
// ...
{
QVariant &v (l[0]); // obviously we don't use "at" since it's const and we need to modify the container
if(v.userType() != qMetaTypeId<MyClass>())
{
qWarning() << "Unexpected metatype " << QMetaType::typeName(v.userType());
return -1;
}
MyClass *const ptr {static_cast<MyClass*>(v.data())};
ptr->myfield = 10;
}
// ...
qDebug() << l.at(0).value<MyClass>().myfield; // returns 10
return 0;
}