#include <QtCore/QCoreApplication>
#include <QVariant>
#include <QtDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QVariantMap map;
map["foo"] = QVariant(QVariantMap());
map["baz"] = "asdf";
qvariant_cast<QVariantMap>(map["foo"])["bar"] = "a";
qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString();
qDebug() << map["baz"].toString();
return a.exec();
}
我正在尝试在嵌套的QVariantMap中分配QVariant。第一个qDebug()不输出任何内容,但第二个输出“asdf”如预期的那样。如何将嵌套变量映射中的“bar”键分配给值?
答案 0 :(得分:12)
问题是qvariant_cast不会返回对其正在运行的QVariant内部的引用;它返回一份副本。因此,如果使用新的子映射覆盖顶级映射中的“foo”元素,代码将正常工作:
#include <QtCore/QCoreApplication>
#include <QVariant>
#include <QtDebug>
int main(int argc, char** argv)
{
QCoreApplication a(argc, argv);
QVariantMap map;
map["foo"] = QVariant(QVariantMap());
map["baz"] = "asdf";
QVariantMap newMap;
newMap["bar"] = "a";
map["foo"] = QVariant(newMap);
qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString();
qDebug() << map["baz"].toString();
return a.exec();
}
据推测,您希望修改现有地图而不是覆盖它。您可以通过复制现有地图,添加新数据(这将导致深层复制),然后将地图写回:
来实现此目的。QVariantMap existingMap = qvariant_cast<QVariantMap>(map["foo"]);
existingMap["bar"] = "a";
map["foo"] = QVariant(existingMap);
如果您正在考虑存储大量数据,您可能希望重新考虑使用QVariant。
答案 1 :(得分:2)
或者你可以按照推车不喜欢的方式来做。
#include <QtCore/QCoreApplication>
#include <QVariant>
#include <QtDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QVariantMap map;
map["foo"] = QVariant(QVariantMap());
map["baz"] = "asdf";
static_cast<QVariantMap>(map["foo"].data_ptr())["bar"] = "a";
qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString();
qDebug() << map["baz"].toString();
return a.exec();
}
或者你可以安全而友好地使用QExplicitlySharedDataPointer而不是直接使用QVariantMap。像这样:
#include <QtCore>
#include <QtDebug>
class VarMap : public QVariantMap, public QSharedData {};
typedef QExplicitlySharedDataPointer<VarMap> SharedVarMap;
Q_DECLARE_METATYPE(SharedVarMap)
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QVariantMap map;
map["foo"] = SharedVarMap(new VarMap());
map["baz"] = "asdf";
map["foo"].value<SharedVarMap>()->["bar"] = "a";
qDebug() << map["foo"].value<SharedVarMap>()->["bar"].toString();
qDebug() << map["baz"].toString();
return a.exec();
}
答案 2 :(得分:2)
template <typename T>
inline T& getStoredValueRef(QVariant &v)
{
const auto type = qMetaTypeId<T>(static_cast<T*>(nullptr));
auto& d = v.data_ptr();
if (type == d.type)
{
auto data = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
return *data;
}
throw std::runtime_error("Bad type");
}
将其用作
(getStoredValueRef<QVariantMap>(map["foo"]))["bar"] = "a";
更深层次
(getStoredValueRef<QVariantMap>(
(getStoredValueRef<QVariantMap>(map["foo"]))["bar"]))["zoo"] = "a";
答案 3 :(得分:1)
执行qvariant_cast时,会复制对象。你应该使用对象的指针。您可以尝试以下代码而不是qvariant_cast代码。
QVariantMap* m = (QVariantMap*)(map["foo"].data());
(*m)["bar"] = "a";
答案 4 :(得分:1)
Starting from Qt 5.1,您可以使用C++11 uniform initialization syntax轻松构建嵌套QMap
或QVariantMap
:
QVariantMap fooMap{
{"bar", "a"}
};
QVariantMap map{
{"foo", fooMap}, // nested map
{"baz", "asdf"}
};
qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString(); // outputs "a"
qDebug() << map["baz"].toString(); // outputs "asdf"