QML更新Json模型

时间:2016-06-20 11:58:26

标签: json qt qml

我有一个用QML创建gui的QT。我使用的是使用模型显示数据的自定义组件。在运行时,此模型将更改。但是没有反映出这些变化。

MyCustomComponent
{
    property var myModel: [
        {
            icon: "qrc:/resources/my_icon1.png",
            data: "Initial text",
        },
        {
            icon: "qrc:/resources/my_icon2.png",
            data: "Initial text",
        }
    ]
    model: myModel

    property int myProp: 0

    onMyPropChanged:
    {
        refreshModel()
    }

    function refreshModel()
    {
        console.error("refreshModel: before: myModel:" + myModel[0].data +  ", model:" + model[0].data);
        myModel[0].data = "alternate text"
        console.error("refreshModel: after: myModel:" + myModel[0].data +  ", model:" + model[0].data);
    }
}

结果:

refreshModel: before: myModel:Initial text, model:Initial text
refreshModel: after: myModel:alternate text, model:Initial text

因此,在运行时myProp发生变化时,将调用refreshModel。但是model本身保持不变,myModel确实发生了变化。

直接更改模型而不是也不起作用。 (所以删除myModel中间属性)。

我需要做些什么不同的事情?

旁注: 最初我使用的是ListModel + ListElement,但这还有其他问题,我正在寻找替代(ListElement: cannot use script for property value)

3 个答案:

答案 0 :(得分:2)

查看Qt文档中有关var type的内容。

  

值得注意的是,分配给var属性的JavaScript对象的常规属性的更改不会触发访问它们的绑定的更新。

因此,为了触发更新,您必须在修改模型后手动发出myModelChanged信号。

function refreshModel()
{
    console.error("refreshModel: before: myModel:" + myModel[0].data +  ", model:" + model[0].data);
    myModel[0].data = "alternate text"
    myModelChanged()
    console.error("refreshModel: after: myModel:" + myModel[0].data +  ", model:" + model[0].data);
}

答案 1 :(得分:0)

实际上,修改myModel结构不会触发信号。我习惯了这种模式,它具有使用不可变结构的优点:

MyCustomComponent
{
    function computeModel(initial)
    {
        return [
            {
                icon: "qrc:/resources/my_icon1.png",
                data: initial ? "Initial text" : "alternate text",
            },
            {
                icon: "qrc:/resources/my_icon2.png",
                data: "Initial text",
            }
        ];
    }
    model: computeModel(true)

    property int myProp: 0

    onMyPropChanged:
    {
        model = computeModel(false);
    }
}

答案 2 :(得分:0)

正如其他答案已经指出的那样,JSON结构是一种变体类型。因此, modelChanged 信号仅在您将新值(新JSON)重新分配给属性的情况下才会触发。对结构的各个部分进行细微改动不会触发信号。

也请注意:在将此类变体模型用于您的ListView,也会遭受性能和可用性方面的缺点。即使您修改模型并手动触发信号,该视图也需要完整重绘。它只知道“ 模型中的某些东西发生了改变”。

为避免这种情况,您可以使用 JsonListModel 将JSON转换为实际的 ListModel 类型( QAbstractListModel 实现):

MyCustomComponent
{
    property var myJson: [
        {
            id: 1,
            icon: "qrc:/resources/my_icon1.png",
            data: "Initial text",
        },
        {
            id: 2,
            icon: "qrc:/resources/my_icon2.png",
            data: "Initial text",
        }
    ]

    model: JsonListModel {
      source: myJson
      keyField: "id"
    }

    property int myProp: 0

    onMyPropChanged:
    {
        refreshModel()
    }

    function refreshModel()
    {
        myJson[0].data = "alternate text"
        myJsonChanged() // emit changed signal, JsonListModel thus also updates
    }
}

您可以找到有关JsonListModel及其用法here的更多详细信息。