C

Qt Quick Ultralite中的模型和视图

应用程序通常需要提供和显示数据。Qt Quick有着数据、视图和委派的概念以显示数据。它们模块化地展示了数据,从而让开发人员或设计师可以控制数据的各个方面。开发人员可以简单地通过列表视图和栅格视图进行切换,而对数据仅作少许修改。同样,将数据实例封装到委派中可以让开发人员指定数据的表现方式或处理方式。

  • 模型 - 包含数据和它的结构。有多种方式可以创建模型。
  • 视图 - 显示数据的容器。视图可能以列表或栅格的形式显示数据。
  • 委派 - 决定数据在视图中的显示方式。委派封装了模型中的每个数据,并通过委派访问这些数据。委派还可以将数据写回可编辑的模型。

要可视化数据,将视图的model属性绑定到一个模型,将delegate属性绑定到一个组件或其他兼容的类型。

使用视图显示数据

视图是项目集合的容器。它们功能丰富,可以自定义以满足样式和行为要求。

基本Qt Quick图形类型中提供了一套标准的视图

  • 重复器 - 不依赖于预定的布局为每个数据条目创建项目
  • 列表视图 - 以水平或垂直列表的形式排列项目

这些类型具有专属的属性和行为。请参阅它们的相应文档以了解更多信息。

视图委派

视图需要一个来在列表中视觉表示一个项目。视图会根据委派中定义的模板来可视化每个列表项目。模型中的项目可以通过index属性以及项目的属性访问。

Component {
    id: petdelegate
    Text {
        id: label
        width: view.width / petlist.count
        height: view.height / petlist.count
        font.pixelSize: 24
        text: if (index == 0)
            label.text = model.type + " (default)"
        else
            text: model.type
    }
}

数据通过命名数据角色提供给委派,这些角色可以被委派绑定。下面是一个ListModel,它有两个角色,即typeage,以及一个ListView,它的委派将绑定到这些角色以显示它们的值。

import QtQuick 2.15

Rectangle {
    color: "white"

    ListModel {
        id: myModel
        ListElement {
            type: "Dog"
            age: 8
        }
        ListElement {
            type: "Cat"
            age: 5
        }
    }

    Component {
        id: myDelegate
        Text {
            width: listView.width / myModel.count
            height: listView.height / myModel.count
            text: model.type + ", " + model.age
        }
    }

    ListView {
        id: listView
        anchors.fill: parent
        model: myModel
        delegate: myDelegate
    }
}

要控制哪些角色可访问,以及使委托更独立和能够在视图之外使用,可以使用必需的属性。如果一个委托包含必需的属性,则不会提供命名角色。相反,Qt Quick Ultralite 引擎会检查必需属性的名称是否与模型角色的名称匹配。如果匹配,则将该属性绑定到来自模型的对应值。

import QtQuick 2.15

Rectangle {
    color: "white"

    ListModel {
        id: myModel
        ListElement {
            type: "Dog"
            age: 8
            noise: "meow"
        }
        ListElement {
            type: "Cat"
            age: 5
            noise: "woof"
        }
    }

    Component {
        id: delegate
        Text {
            width: listView.width / myModel.count
            height: listView.height / myModel.count
            required property string type
            required property int age
            text: type + ", " + age
            // WRONG: text: type + ", " + noise
            // The above line would cause a compiler error
            // as there is no required property noise
        }
    }

    ListView {
        id: listView
        anchors.fill: parent
        model: myModel
        delegate: delegate
    }
}

如果模型属性和委托属性之间存在命名冲突,可以使用合格的 model 名称来访问角色。例如,如果一个 Text 类型有 typeage 属性,那么上面示例中的文本将显示那些属性值,而不是模型中的 typeage 值。在这种情况下,属性可以这样引用 model.typemodel.age,以确保委托显示模型中的属性值。

一个特殊的 index 角色也可用于委托,该角色包含模型中项的索引。请注意,如果项被从模型中删除,则此索引设为 -1。如果您绑定到索引角色,请确保逻辑考虑了索引可能为 -1 的情况,即项不再有效。通常项将很快被销毁,但在某些视图中可以延迟委托的销毁。

没有命名角色的模型将通过 modelData 角色提供数据。对于只有一个角色的模型,也会提供 modelData 角色在此情况下,modelData 角色包含与命名角色相同的数据。

注意:indexmodelData 角色在委托包含必需属性时不可以访问,除非它也有具有匹配名称的必需属性。

列表模型

ListModel 是在 QML 中指定的简单类型层次结构。可用的角色通过 ListElement 属性指定。

ListModel {
    id: fruitModel

    ListElement {
        name: "Apple"
        cost: 245
    }
    ListElement {
        name: "Orange"
        cost: 325
    }
    ListElement {
        name: "Banana"
        cost: 195
    }
}

上述模型有两个角色:namecost。这些可以由 ListView 委托绑定,例如

ListView {
    anchors.fill: parent
    model: fruitModel
    delegate: Row {
        width: parent.width / fruitModel.count
        height: parent.height / fruitModel.count
        Text { text: "Fruit: " + model.name }
        Text { text: " Cost: $" + model.cost }
    }
}

注意:与 Qt Quick 不同,ListModelListElement 是只读的。这意味着您无法更改存储在此类模型中的值。如果您需要可编辑的模型,请参阅 Qul::ListModel将 C++ 代码与 QML 集成

对象列表

可以使用包含对象字面量的数组字面量作为模型。数组的当前元素作为 modelData 角色可用,可以直接访问或作为 model.modelData 访问。

ListView {
    anchors.fill: parent
    model: [
        { name: "Apple", color: "green" },
        { name: "Pear", color: "pink" }
    ]
    delegate: Row {
        width: parent.width / 2
        height: parent.height / 2
        Text { text: "Fruit: " + modelData.name }
        Text { text: " Color: " + model.modelData.color }
    }
}

ListModel<T> 类型的属性

可以使用类型为 ListModel<T> 的属性作为模型,其中 T 的属性描述模型结构。

这允许外部设置模型数据,或由 PropertyChangesState 中设置。

// MyView.qml
Item {
    width: 120
    height: 40

    property ListModel<NameAgeType> myModel

    ListView {
        anchors.fill: parents
        model: myModel
        delegate: Text {
            width: parent.width / myModel.count
            height: parent.height / myModel.count
            text: model.name
        }
    }
}
// NameAgeType.qml
QtObject {
    property string name
    property int age
}
// User.qml
Rectangle {
    Row {
        MyView {
            myModel: [{ name: "John Smith", age: 42 }]
        }
        MyView {
            myModel: ListModel { ListElement { name: "Smith"; age: 42 } }
        }
    }
}

注意:ListModel<T> 类型是 Qt Quick Ultralite 特有的,在 Qt Quick 中不存在。使用它意味着 QML 代码将不与 Qt Quick 兼容。不使用它,无法在另一文件中声明模型。

整数作为模型

可以使用整数作为包含一定数量类型的模型。在这种情况下,模型没有任何数据角色。

以下示例创建了一个包含五个元素的 ListView

Rectangle {

    Component {
        id: itemDelegate
        Text {
            width: listView.width / 5
            height: listView.height / 5
            text: "I am item number: " + index
        }
    }

    ListView {
        id: listView
        anchors.fill: parent
        model: 5
        delegate: itemDelegate
    }

}

注意: 整数模型中项目的数量限制为1亿。

C++数据模型

C++中可以定义模型,然后将其对QML可用。此机制适用于将现有的C++数据模型、可变模型或其他复杂的数据集暴露给QML。

有关信息,请访问 Qul::ListModel将C++代码与QML集成

在特定的Qt许可证下可用。
了解更多信息。