正文
列表数据Model,可以自定义格式。
详细说明
ListModel是定义ListElement的容器。内容可以动态定义,也可以在QML中明确定义。
可以通过count属性获得模型中数据的数量。可以使用模型的setProperty()方法来操作元素,该方法允许设置和更改指定元素属性。
用法示例
下面的示例显示一个ListModel,其中包含三个元素以及对应的角色(name和cost)。
import QtQuick 2.0
ListModel {
id: fruitModel
ListElement {
name: "Apple"
cost: 2.45
}
ListElement {
name: "Orange"
cost: 3.25
}
ListElement {
name: "Banana"
cost: 1.95
}
}
每个元素中的角色(属性)必须以小写字母开头,并且模型中的所有元素共有这些角色。
由于示例模型包含一个id属性,因此可以由视图(如下示例中的ListView)引用它:
import QtQuick 2.0
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定期将当前时间附加到列表模型中:
WorkerScript {
id:worker
source: "dataloader.mjs"
}
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()收到消息后,将当前时间append到列表模型中。
注意:外部线程通过调用sync()来更新列表显示。
属性
- count: int(只读)
此属性获取模型中的数据条数。
- dynamicRoles: bool
默认情况下,角色的类型在第一次使用时是固定的。例如,如果创建一个名为“data”的角色并为其分配一个数字,则不能再为该“data”角色分配一个字符串。但是,启用dynamicRoles属性后,给定角色的类型将不固定,并在各个元素之间可以不同。
必须在将任何数据添加到ListModel之前设置dynamicRoles属性,并且必须从主线程进行设置。
具有静态定义的数据(通过ListElement设置的数据)的ListModel不能启用dynamicRoles属性。
使用启用了动态角色的ListModel会产生巨大的性能成本。成本因平台而异,但通常比使用静态角色类型慢4-6倍。
由于使用动态角色会降低性能,因此默认情况下将其禁用。
方法
- append(dict)
将一个新角色添加到列表模型的末尾:
fruitModel.append({"cost": 5.95, "name":"Pizza"})
- clear()
从模型中删除所有内容。 - object get(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"
警告:不能保证返回的对象仍然有效。不应使用属性绑定。
- insert(index, jsobject dict)
在index位置处插入新元素到列表模型中。
fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})
index必须指向列表中的现有项,或者指向列表末尾的索引(等效于append())。
- move(from, int to, int n)
将n个元素从一个位置移动到另一个位置。
from和to必须存在。
如下示例,将前三个元素移动到列表末尾:
fruitModel.move(0, fruitModel.count - 3, 3)
- remove(index, int count = 1)
从列表模型中删除index索引项开始的count个元素。 - set(index, jsobject dict)
设置dict对象到列表模型的index索引项中,dict对象中未出现的属性保持不变。
fruitModel.set(3, {"cost": 5.95, "name":"Pizza"})
如果index等于count(),则将新项追加到列表中。否则,index必须是列表中的元素。
- setProperty(index, string property, variant value)
将列表模型中index索引的元素属性更改为valu。
fruitModel.setProperty(3, "cost", 5.95)
- sync()
在工作脚本中调用,将所有修改项写入列表模型中。