【问题标题】:Editing a QVariantMap from QML从 QML 编辑 QVariantMap
【发布时间】:2023-03-22 06:07:01
【问题描述】:

我有一个用 C++ 从 JSON 对象创建的 QVariantMap,我想从 QML 更新这个对象。我将其设置为上下文属性。

// main.cpp
engine.rootContext()->setContextProperty("myjson", myqvariantmap);

在 QML 中,我尝试更新其属性,但它似乎是只读的。 docs 支持这个,说

请注意,C++ 类型的 QVariantList 和 QVariantMap 属性存储为值,不能通过 QML 代码就地更改。您只能替换整个地图或列表,但不能操作其内容。

是否有替代 QVariatnMap 的解决方法或替代类型?

【问题讨论】:

    标签: c++ qt qml


    【解决方案1】:

    一个可能的选项是QQmlPropertyMap:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlPropertyMap>
    #include <QQmlContext>
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QQmlPropertyMap qpropertymap;
        qpropertymap.insert("name", "foo");
    
        QObject::connect(&qpropertymap, &QQmlPropertyMap::valueChanged, [](const QString &key, const QVariant &value){
            qDebug() << key << value;
        });
    
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("qpropertymap", &qpropertymap);
        const QUrl url(QStringLiteral("qrc:/main.qml"));
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
        engine.load(url);
    
        return app.exec();
    }
    
    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    Window {
        width: 640
        height: 480
        visible: true
        title: qsTr("Hello World")
        Component.onCompleted: {
            qpropertymap.name = "bar"
            // or
            // qpropertymap["name"] = "bar"
        }
    }
    

    【讨论】:

    • 这看起来和我要找的完全一样!有没有一种简单的方法可以从 QVariantMap 或 QJsonObject 转换为 QQmlPropertyMap?
    • @Mark 我看到的唯一解决方案是遍历 QVariantMap 并将元素复制到 QQmlPropertyMap
    【解决方案2】:

    这是一个与@eyllanesc 的解决方案一起使用的 sn-p,用于从 QVariantMap 转换为 QQmlPropertyMap。

    void toPropertyMap(const QVariantMap& source, QQmlPropertyMap* dest) {
        for (const auto& key : source.keys()) {
            (*dest)[key] = source[key];
        }
    }
    

    【讨论】:

    • 您绝对应该使用迭代器而不是keys() 方法。试想一下,有多少开发人员会在他们的生产代码中使用这样的 smth,只是因为它是由高级用户发布在 StackOverflow 上的。 1. keys() 创建一个新列表(字符串) 2. source[key] 在每次迭代中进行搜索,这本身就是 log(n),所以你的代码甚至不是线性的 3. 更糟。 QQmlPropertyMap [key] 是线性的,所以你的代码是 n^2。不要责怪 Qt 之后的速度慢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    相关资源
    最近更新 更多