2012-06-18 35 views
10
#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(); 
} 

Tôi đang cố gán cho một QVariant trong một QVariantMap lồng nhau. QDebug() đầu tiên đầu ra không có gì, nhưng đầu ra thứ hai "asdf" như mong đợi. Làm cách nào để gán khóa "thanh" trong bản đồ biến lồng nhau vào một giá trị?Chỉ định cho lồng nhau QVariantMap

Trả lời

11

Vấn đề là qvariant_cast không trả lại tham chiếu đến nội bộ của QVariant mà nó đang hoạt động; nó trả về một bản sao. Như vậy, nếu bạn ghi đè lên các yếu tố "foo" trong bản đồ cấp cao nhất của bạn với một bản đồ mới trẻ, mã sẽ hoạt động đúng:

#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(); 
} 

Có lẽ, bạn muốn thay đổi bản đồ hiện có thay vì overwritting nó. Bạn có thể thực hiện điều này bằng cách sao chép các bản đồ hiện có, bổ sung các dữ liệu mới (mà sẽ dẫn đến một bản sao sâu), và sau đó viết bản đồ lại:

QVariantMap existingMap = qvariant_cast<QVariantMap>(map["foo"]); 
existingMap["bar"] = "a"; 
map["foo"] = QVariant(existingMap); 

Nếu bạn đang cân nhắc việc lưu trữ một lượng lớn dữ liệu , bạn có thể cân nhắc việc sử dụng QVariant của mình.

+0

Dành cho người đọc đến đây vào năm 2016: với Qt 5.1+ và trình biên dịch C++ 11, mã này có thể được thực hiện đơn giản hơn nhiều, như được chỉ ra trong [câu trả lời của tôi dưới đây] (http://stackoverflow.com/ câu hỏi/11090846/chỉ định-tới-lồng nhau-qvariantmap/37119292 # 37119292). –

2

Hoặc bạn có thể làm điều đó theo cách mà trollies không thích.

#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(); 
} 

Hoặc bạn có thể làm tất cả an toàn và tốt đẹp và sử dụng QExplicitlySharedDataPointer thay vì trực tiếp QVariantMap. Như thế này:

#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(); 
} 
1

Khi qvariant_cast được thi hành, đối tượng được sao chép. bạn nên sử dụng một con trỏ của đối tượng. Bạn có thể thử đoạn mã sau thay vì mã qvariant_cast.

QVariantMap* m = (QVariantMap*)(map["foo"].data()); 
(*m)["bar"] = "a"; 
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"); 
} 

sử dụng nó như

(getStoredValueRef<QVariantMap>(map["foo"]))["bar"] = "a"; 

và sâu hơn

(getStoredValueRef<QVariantMap>(
    (getStoredValueRef<QVariantMap>(map["foo"]))["bar"]))["zoo"] = "a"; 
1

Starting from Qt 5.1, bạn có thể sử dụng để xây dựng một C++11 uniform initialization syntax lồng nhau QMap hoặc QVariantMap dễ dàng:

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" 
+0

Tôi nên lưu ý rõ ràng với phương pháp tiếp cận này: nó chỉ hoạt động nếu bản đồ có một bộ khóa đã biết. –