Qt QML 为什么这个 ListView 和 ListModel 不一致?

Qt QML Why isn't this ListView and ListModel consitent?

我在使用 ListView 和简单的 ListModel;

时遇到问题
import QtQuick 2.12
import QtQuick.Controls 2.12

ApplicationWindow
{
    id: app
    visible: true
    width: 640
    height: 480
    property int bheight: 48

    ListModel
    {
        id: jmodel
    }

    function dosomething1()
    {
        jmodel.clear();
        jmodel.append({"atext":"hello"})
    }

    function dosomething2()
    {
        jmodel.clear();
        jmodel.append({"atext":"hello","btext":"world"});
    }

    ListView
    {
        id: alist
        width: parent.width
        height: parent.height - bheight
        model: jmodel
        delegate: Item
        {
            width: app.width
            height: 48
            Row
            {
                spacing: 8
                Text
                {
                    text: model.atext || ""
                }

                Text
                {
                    text: model.btext || ""
                }
            }
        }
    }

    Row
    {
        height: bheight
        anchors.top: alist.bottom
        Button
        {
            // press "plan A" first and it will say "hello"
            // press "plan B" after and it will remain "hello"
            // pressing A & B will NOT toggle
            text: "Plan A"
            onClicked: dosomething1();
        }

        Button
        {
            // press "plan B" first and it will say "hello world"
            // press "plan A" after and it will say "hello"
            // pressing A & B will toggle
            text: "Plan B"
            onClicked: dosomething2();
        }
    }

}

我无法让它始终如一地工作。也许有一些简单的遗漏或者我不明白。

按 "Plan A" 会说 "hello" 而 之后按 "Plan B" 不会改变它。

但是,

先按 "Plan B" 会说 "hello world",然后按 "plan A" 和 "plan B" 会在 "hello world" 和 "hello" 之间切换。

应该和先按哪个按钮无关,我每次都是清除模型。

我已经在Qt5.12.3和5.9上试过了,没有任何变化。

更新

根据@eyllanesc 的回答,我更新了我的代码,改为为每次更新创建一个新模型。这有效,但我不知道我现在是否有内存泄漏。

这是我的代码:

import QtQuick 2.12
import QtQuick.Controls 2.12

ApplicationWindow
{
    id: app
    visible: true
    width: 640
    height: 480
    property int bheight: 48

    Component
    {
        id: jmodel
        ListModel {}
    }

    function dosomething1()
    {
        var m = jmodel.createObject()
        m.append({"atext":"hello"})
        alist.model = m;
    }

    function dosomething2()
    {
        var m = jmodel.createObject()
        m.append({"atext":"hello","btext":"world"});
        alist.model = m;
    }

    ListView
    {
        id: alist
        width: parent.width
        height: parent.height - bheight
        delegate: Item
        {
            width: app.width
            height: 48
            Row
            {
                spacing: 8
                Text
                {
                    text: model.atext || ""
                }

                Text
                {
                    text: model.btext || ""
                }
            }
        }
    }

    Row
    {
        height: bheight
        anchors.top: alist.bottom
        Button
        {
            text: "Plan A"
            onClicked: dosomething1();
        }

        Button
        {
            text: "Plan B"
            onClicked: dosomething2();
        }
    }



}

正如the docs指出的那样:

Modifying List Models

Modifying List Models The content of a ListModel may be created and modified using the clear(), append(), set(), insert() and setProperty() methods. For example:

Component {
    id: fruitDelegate
    Item {
        width: 200; height: 50
        Text { text: name }
        Text { text: '$' + cost; anchors.right: parent.right }

        // Double the price when clicked.
        MouseArea {
            anchors.fill: parent
            onClicked: fruitModel.setProperty(index, "cost", cost * 2)
        }
    }
} 

Note that when creating content dynamically the set of available properties cannot be changed once set. Whatever properties are first added to the model are the only permitted properties in the model.

(强调)

您不能在初始建立后添加或删除属性:

  • 情况 1 你的模型最初只有 atext 属性,然后你想添加 btext 属性 但 Qt 不允许它。

  • 在情况 2 中,您的模型具有属性 atext 和 btext,那么您只需重写 atext 属性,这样 btext 仍然存在并且值为 null。

这种情况下的解决方法是在情况1中给btext设置一个默认值:

function dosomething1()
{
    jmodel.clear();
    jmodel.append({"atext":"hello", "btext":""}) // <----
}