QML类型——ListModel

正文

列表数据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()
    在工作脚本中调用,将所有修改项写入列表模型中。
  • 6
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值