ListElement
一、描述
列表元素,在
ListModel
中定义,并表示将使用
ListView
或
Repeater
项目显示的列表中的项目。
列表元素包含
角色定义
的集合而不是属性。角色既定义了数据的访问方式,又包含了数据本身。
用于角色的名称必须
以小写字母开头
,并且应该对给定模型中的所有元素通用。值必须是简单的常量、字符串、布尔值、数字或枚举值。
允许将函数声明分配给角色。
二、引用角色
代理使用角色名称从列表元素中获取数据。每个角色名称都可以在委托范围内访问,并引用当前元素中的相应角色。在角色名称使用不明确的情况下,可以通过模型属性访问它(例如,model.cost 而不是 cost)。
三、使用示例
以下模型定义了一系列列表元素,每个元素都包含“name”和“cost”角色及其关联值。
ListModel
{
id: fruitModel
ListElement
{
name: "Apple"
cost: 2.45
}
ListElement
{
name: "Orange"
cost: 3.25
}
ListElement
{
name: "Banana"
cost: 1.95
}
}
委托通过简单地引用名称和成本来获取每个元素的“name”和“cost”:
ListView
{
anchors.fill: parent
model: fruitModel
delegate: Row
{
Text { text: "Fruit: " + name }
Text { text: "Cost: $" + cost }
}
}
ListModel
一、描述
ListModel 是一个简单的
ListElement
定义容器,每个定义都包含数据角色。内容可以动态定义,也可以在 QML 中显式定义。
二、使用示例
import QtQuick 2.0
Rectangle
{
width: 200; height: 200
ListModel //模型-提供数据
{
id: fruitModel
ListElement
{
name: "Apple"
cost: 2.45
}
ListElement
{
name: "Orange"
cost: 3.25
}
ListElement
{
name: "Banana"
cost: 1.95
}
}
Component //委托-提供一个展示数据的示例(如何展示一个模型中的数据)
{
id: fruitDelegate
Row
{
spacing: 10
Text { text: name }
Text { text: '$' + cost }
}
}
ListView //视图-设置委托和模型,根据委托提供的展示方式展示模型提供的数据
{
anchors.fill: parent
model: fruitModel
delegate: fruitDelegate
}
}
角色可以包含列表数据:
import QtQuick 2.12
import QtQuick.Window 2.0
Window
{
id:root;
visible: true;
width: 1000;
height: 500;
title: "hello world"
Rectangle
{
width: 200; height: 200
ListModel {
id: fruitModel
ListElement
{
name: "苹果"
cost: 2.45
attributes:
[
ListElement { description: "Core" },
ListElement { description: "Deciduous" }
]
}
ListElement
{
name: "橘子"
cost: 3.25
attributes:
[
ListElement { description: "Citrus" }
]
}
ListElement
{
name: "香蕉"
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: "属性:" }
Repeater
{
model: attributes
Text { text: description }
}
}
}
}
ListView
{
anchors.fill: parent
model: fruitModel
delegate: fruitDelegate
}
}
}
三、修改列表模型
可以使用
clear
()、
append
()、
set
()、
insert
() 和
setProperty
() 方法创建和修改 ListModel 的内容。
例如:
Component
{
id: fruitDelegate
Item
{
width: 200; height: 50
Text { text: name }
Text { text: '$' + cost; anchors.right: parent.right }
MouseArea
{
anchors.fill: parent
onClicked: fruitModel.setProperty(index, "cost", cost * 2)
}
}
}
在动态创建内容时,属性集一旦设置就无法更改。
四、在
WorkerScript
中使用线程列表模型
ListModel 可以与
WorkerScript
一起使用,从多个线程访问列表模型。列表操作可以移动到不同的线程以避免阻塞主 GUI 线程。
这是一个使用 WorkerScript 定期将当前时间附加到列表模型的示例:
import QtQuick 2.12
import QtQuick.Window 2.0
Window
{
id:root;
visible: true;
width: 1000;
height: 500;
title: "hello world"
Rectangle
{
width: 200; height: 200
ListModel
{
id: listModel
}
Component
{
id: fruitDelegate
Item
{
width: 200; height: 25
Text { text: time }
}
}
ListView
{
anchors.fill: parent
model: listModel
delegate: fruitDelegate
}
WorkerScript
{
id: worker
source: "qrc:/dataloader.js"
}
Timer
{
id: timer
interval: 1000; repeat: true
running: true
triggeredOnStart: true
onTriggered:
{
var msg = {'action': 'appendCurrentTime', 'model': listModel};
worker.sendMessage(msg);
}
}
}
}
dataloader.js
WorkerScript.onMessage = function(msg)
{
if (msg.action === 'appendCurrentTime')
{
var data = {'time': new Date().toTimeString()};
msg.model.append(data);
msg.model.sync();
}
}
计时器通过调用
WorkerScript
::
sendMessage
() 向工作脚本发送消息。收到此消息后,会在 dataloader.js 中调用
WorkerScript
.
onMessage
(),将当前时间附加到列表模型中。
必须调用
sync
() 否则从该线程对列表所做的更改将不会反映在主线程的列表模型中。
五、属性成员
1、
count
: int
模型中数据条目的数量。
2、
dynamicRoles
: bool
是否启用动态角色。默认被禁用。
默认情况下,角色的类型在第一次使用时固定。例如,创建一个名为“data”的角色并为其分配一个数字,则不能再为“data”角色分配字符串。但是,当启用 dynamicRoles 属性时,给定角色的类型不是固定的,元素之间可以不同。
dynamicRoles 属性必须在任何数据添加到 ListModel 之前设置,并且必须从主线程设置。
具有静态定义的数据(通过
ListElement
定义)的 ListModel 不能启用 dynamicRoles 属性。使用启用了动态角色的 ListModel 会产生显着的性能成本。成本因平台而异,但通常比使用静态角色类型慢 4-6 倍。
六、成员函数
1、
append
(jsobject dict)
将一个新项目添加到列表模型的末尾,其值在 dict 中。
2、
clear
()
从模型中删除所有内容。
3、object
get
(int index)
返回列表模型中索引处的项目。这允许从 JavaScript 访问或修改项目数据。
Component.onCompleted:
{
fruitModel.append({"cost": 5.95, "name":"Jackfruit"});
console.log(fruitModel.get(0).cost);
fruitModel.get(0).cost = 10.95;
}
此方法用于访问元素:
fruitModel.append(..., "attributes":
[{"name":"spikes","value":"7mm"},
{"name":"color","value":"green"}]);
fruitModel.get(0).attributes.get(1).value; // == "green"
不保证返回的对象保持有效。不应该用于属性绑定。
4、
insert
(int index, jsobject dict)
在位置 index 处向列表模型添加一个新项目,其值在 dict 中。
index 必须指向列表中的现有项目,或者列表末尾之后的一项(相当于
append
())。
fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})
5、
move
(int from, int to, int n)
将 n 个项目从一个位置移动到另一个位置。from 和 to 范围必须存在。
例如,将前 3 个项目移动到列表的末尾:
fruitModel.move(0, fruitModel.count - 3, 3)
6、
remove
(int index, int count = 1)
从模型中删除 index 处的计数项。
7、
set
(int index, jsobject dict)
使用 dict 中的值更改列表模型中索引处的项目。
如果 index 等于
count
() ,则将新项目附加到列表中。否则,index 必须是列表中的元素。
fruitModel.set(3, {"cost": 5.95, "name":"Pizza"})
8、
setProperty
(int index, string property, variant value)
将列表模型中 index 处项目的属性更改为 value。index 必须是列表中的元素。
fruitModel.setProperty(3, "cost", 5.95)
9、
sync
()
在从工作脚本修改列表模型后,将任何未保存的更改写入列表模型。