ListModel QML Type
定义了一个自由格式列表数据源。更多...
| Import Statement: | import QtQml.Models |
属性
- count : int
- dynamicRoles : bool
方法
- void append(jsobject dict)
- void clear()
- var get(int index)
- void insert(int index, jsobject dict)
- void move(int from, int to, int n)
- void remove(int index, int count)
- void set(int index, jsobject dict)
- void setProperty(int index, string property, var value)
- void sync()
详细说明
ListModel 是一个简单的容器,用于存放ListElement 定义,每个定义都包含数据角色。其内容可以动态定义,也可以在 QML 中显式定义。
模型中的元素数量可通过其 `count ` 属性获取。此外还提供了一系列常用方法来操作模型内容,包括 `append()`、`insert()`、`move()`、`remove()` 和 `set()`。这些方法接受字典作为参数;这些字典将由模型转换为 `ListElement ` 对象。
可以通过模型使用setProperty() 方法对元素进行操作,该方法允许设置和更改指定元素的角色。
ListModel 继承自QAbstractListModel ,并提供了Q_INVOKABLE 方法。例如,您可以使用QAbstractItemModel::index 来获取行和列对应的QModelIndex 。
使用示例
以下示例展示了一个包含三个元素的 ListModel,这些元素具有“name”和“cost”这两个角色。

import QtQuick
ListModel {
id: fruitModel
ListElement {
name: "Apple"
cost: 2.45
}
ListElement {
name: "Orange"
cost: 3.25
}
ListElement {
name: "Banana"
cost: 1.95
}
}每个元素中的角色(属性)必须以小写字母开头,并且应在模型中的所有元素中保持一致。《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 }
}
}
}
}修改列表模型
ListModel 的内容可通过clear()、append()、set()、insert() 和setProperty() 等方法进行创建和修改。例如:
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(),否则该线程对列表所做的更改将不会反映在主线程的列表模型中。
属性文档
count : int [read-only]
模型中的数据条目数量。
dynamicRoles : bool
默认情况下,角色的类型在首次使用该角色时即被固定。 例如,如果您创建了一个名为“data”的角色并为其分配了一个数字,则无法再为“data”角色分配字符串。但是,当启用 dynamicRoles 属性时,给定角色的类型并非固定,且不同元素之间的角色类型可以不同。
必须在向ListModel 添加任何数据之前设置 dynamicRoles 属性,并且必须在主线程上进行设置。
数据通过 QML 语法(ListElement )静态定义的ListModel 不能启用 dynamicRoles 属性。
使用启用了动态角色的ListModel 会带来显著的性能开销。该开销因平台而异,但通常比使用静态角色类型慢 4 到 6 倍。
鉴于使用动态角色的性能开销,默认情况下它们处于禁用状态。
方法文档
void append(jsobject dict)
在列表模型末尾添加一个新项,其值取自dict 。
fruitModel.append({"cost": 5.95, "name":"Pizza"})void clear()
从模型中删除所有内容。特别是,这会使您可能通过get() 获取的所有对象失效。
另请参阅 append()、remove() 和get()。
var 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"void insert(int index, jsobject dict)
在列表模型的index 位置添加一个新项,其值为dict 中的值。
fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})index 必须指向列表中的现有项,或者指向列表末尾之后的项(相当于 append)。
void move(int from, int to, int n)
将n 中的项目from 移动一个位置,to 移动另一个位置。
源范围和目标范围必须存在;例如,要将前 3 个元素移至列表末尾:
fruitModel.move(0, fruitModel.count - 3, 3)另请参阅 append()。
void remove(int index, int count = 1)
从模型中删除位于index 的count 个项目。
另请参阅 clear()。
void set(int index, jsobject dict)
使用dict 中的值修改列表模型中位于index 的项。未出现在dict 中的属性将保持不变。
fruitModel.set(3, {"cost": 5.95, "name":"Pizza"})如果index 等于 count(),则会在列表末尾追加一个新项。否则,index 必须是列表中的一个元素。
另请参阅 append()。
void setProperty(int index, string property, var value)
将列表模型中位于index 的项的property 更改为value 。
fruitModel.setProperty(3, "cost", 5.95)index 必须是列表中的一个元素。
另请参阅 append()。
void sync()
在列表模型被工作脚本修改后,将任何未保存的更改写入该模型。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.