ListModel QML 类型

定义一个自由形式的列表数据源。 更多...

导入语句import QtQml.Models

属性

方法

详细描述

ListModel 是一个简单的容器,包含 ListElement 定义,每个定义中包含数据角色。内容可以动态定义,或在 QML 中显式定义。

可以通过模型中的 count 属性获取模型中元素的数量。提供了一系列熟悉的方法来操作模型的内容,包括 append()、insert()、move()、remove() 和 set()。这些方法接受字典作为参数,由模型将它们转换为 ListElement 对象。

可以使用 setProperty() 方法通过模型操作元素,该方法允许设置和更改指定元素的角色。

ListModel 继承自 QAbstractListModel 并提供它的 Q_INVOKABLE 方法。例如,您可以使用 QAbstractItemModel::index 检索行和列的 QModelIndex

示例用法

以下示例展示了一个包含三个元素且具有“name”和“cost”角色的 ListModel。

import QtQuick

ListModel {
    id: fruitModel

    ListElement {
        name: "Apple"
        cost: 2.45
    }
    ListElement {
        name: "Orange"
        cost: 3.25
    }
    ListElement {
        name: "Banana"
        cost: 1.95
    }
}

每个元素中的角色(属性)必须以小写字母开始,并且在模型的所有元素中应该是通用的。《a href="qml-qtqml-models-listelement.html" translate="no">ListElement 文档提供了有关如何定义元素更详细的指南。

由于示例模型包含一个 id 属性,它可以被视图引用,例如本例中的 ListView

import QtQuick

Rectangle {
    width: 200; height: 200

    ListModel {
        id: fruitModel
        ...
    }

    Component {
        id: fruitDelegate
        Row {
            spacing: 10
            Text { text: name }
            Text { text: '$' + cost }
        }
    }

    ListView {
        anchors.fill: parent
        model: fruitModel
        delegate: fruitDelegate
    }
}

角色可以包含列表数据。以下示例中我们创建了一个水果属性的列表

ListModel {
    id: fruitModel

    ListElement {
        name: "Apple"
        cost: 2.45
        attributes: [
            ListElement { description: "Core" },
            ListElement { description: "Deciduous" }
        ]
    }
    ListElement {
        name: "Orange"
        cost: 3.25
        attributes: [
            ListElement { description: "Citrus" }
        ]
    }
    ListElement {
        name: "Banana"
        cost: 1.95
        attributes: [
            ListElement { description: "Tropical" },
            ListElement { description: "Seedless" }
        ]
    }
}

委托显示所有水果属性

Component {
    id: fruitDelegate
    Item {
        width: 200; height: 50
        Text { id: nameField; text: name }
        Text { text: '$' + cost; anchors.left: nameField.right }
        Row {
            anchors.top: nameField.bottom
            spacing: 5
            Text { text: "Attributes:" }
            Repeater {
                model: attributes
                Text { text: description }
            }
        }
    }
}

修改列表模型

可以使用以下方法创建和修改 clear()、append()、set()、insert() 和 setProperty() 的 ListModel 内容。例如

    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)
            }
        }
    }

请注意,在动态创建内容时,一旦设置,可用的属性集不能更改。最初添加到模型中的所有属性都是模型中唯一允许的属性。

使用 WorkerScript 与线程化的列表模型

ListModel 可以与 WorkerScript 一起使用,从多个线程访问列表模型。如果列表修改是同步的且需要一些时间,这是很有用的:可以将列表操作移动到不同的线程,以避免阻塞主 GUI 线程。

以下是一个使用 WorkerScript 定期将当前时间追加到列表模型的示例

        Timer {
            id: timer
            interval: 2000; repeat: true
            running: true
            triggeredOnStart: true

            onTriggered: {
                var msg = {'action': 'appendCurrentTime', 'model': listModel};
                worker.sendMessage(msg);
            }
        }

包含的文件 dataloader.mjs 看起来是这样的

WorkerScript.onMessage = function(msg) {
    if (msg.action == 'appendCurrentTime') {
        var data = {'time': new Date().toTimeString()};
        msg.model.append(data);
        msg.model.sync();   // updates the changes to the list
    }
}

主示例中的计时器通过调用 WorkerScript::sendMessage() 向工作脚本发送消息。当接收到这条消息时,在 dataloader.mjs 中将调用 WorkerScript.onMessage(),它将当前时间追加到列表模型。

请注意从外部线程调用 sync()。您必须调用 sync(),否则该线程所做的列表更改将不会反映在主线程的列表模型中。

另请参阅数据模型Qt Qml

属性文档

count : int [只读]

模型中的数据条目数量。


dynamicRoles : bool

默认情况下,角色类型在第一次使用时是固定的。例如,如果你创建了一个名为 "data" 的角色并将其分配给一个数字,你不能再将字符串分配给 "data" 角色。但是,当启用 dynamicRoles 属性时,给定角色的类型不是固定的,并且可以不同。

必须在向 ListModel 添加任何数据之前设置 dynamicRoles 属性,并且必须从主线程设置。

具有通过 ListElement QML 语法静态定义(定义)数据的 ListModel 不能启用 dynamicRoles 属性。

使用启用动态角色的 ListModel 的性能成本很高。成本因平台而异,但通常比使用静态角色类型慢 4-6 倍。

由于使用动态角色的性能成本很高,因此默认禁用。


方法文档

append(jsobject dict)

向列表模型的末尾添加一个新条目,其中的值在 dict 中。

fruitModel.append({"cost": 5.95, "name":"Pizza"})

另请参阅set() 和 remove()。


clear()

从模型中删除所有内容。

另请参阅 append() 和 remove()。


对象 get(int index)

返回列表模型中的 index 位置的项。这允许从 JavaScript 访问或修改项目数据

Component.onCompleted: {
    fruitModel.append({"cost": 5.95, "name":"Jackfruit"});
    console.log(fruitModel.get(0).cost);
    fruitModel.get(0).cost = 10.95;
}

index 必须是列表中的元素。

注意,返回对象的属性如果是自身也是对象,也将会是模型,此 get() 方法用于访问元素

fruitModel.append(..., "attributes":
    [{"name":"spikes","value":"7mm"},
     {"name":"color","value":"green"}]);
fruitModel.get(0).attributes.get(1).value; // == "green"

警告: 返回的对象不保证保持有效。不应在 属性绑定 中使用。

另请参阅 append


insert(int index, jsobject dict)

在列表模型中位置 index 处添加一个新项目,其值为 dict

fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})

index 必须是列表中的现有项,或位于列表末尾之后(等同于 append)。

另请参阅 set() 和 append


move(int from, int to, int n)

n 个项从位置 from 移动到 to

from 和 to 范围必须存在;例如,将前 3 个项移动到列表末尾

fruitModel.move(0, fruitModel.count - 3, 3)

另请参阅 append


remove(int index, int count = 1)

从模型中删除 index 位置的 count 个项。

另请参阅 clear


set(int index, jsobject dict)

使用 dict 中的值更改列表模型中的 index 位置的项。未出现在 dict 中的属性保持不变。

fruitModel.set(3, {"cost": 5.95, "name":"Pizza"})

如果 index 等于 count(),则向列表中添加一项新项。否则,index 必须是列表中的元素。

另请参阅 append


setProperty(int index, string property, variant value)

将列表模型中 index 位置的项的 property 更改为 value

fruitModel.setProperty(3, "cost", 5.95)

index 必须是列表中的元素。

另请参阅 append


sync()

将修改后的列表模型中的任何未保存更改写入。


© 2024 Qt 公司有限公司。此处包含的文档贡献的版权为各自所有者所有。此处提供的文档是根据 Free Software Foundation 发布的 GNU 自由文档许可证版本 1.3 的条款许可的。Qt 和相应的标志是芬兰和/或其他国家的 Qt 公司的 商标。所有其他商标均为其各自所有者的财产。