Qt QML 杂记

QML Book 第六章 模型、视图及代理 1

2017-07-08  本文已影响31人  赵者也

6.Model-View-Delegate

** 注意: **
最新的构建时间:2016/03/21
这章的源代码能够在assetts folder找到。

在 Qt Quick 中,数据被通过模型(model 下同)-视图(view 下同)分离的方式分离出来。对于每个视图,每个数据元素的可视化都被分离成一个代理(delegate 下同)。Qt Quick 附带一组预定义的模型和视图类。要利用这个系统,我们必须了解这些类,并知道如何创建合适的代理以获得正确的呈现效果。

6.1 概念

在开发用户界面时,最重要的一个模式是保持数据部分与可视化部分的分离。例如,电话本可以被安排为一个垂直的文本条目列表或联系人的图片网格。在这两种情况下,数据部分都是相同的:电话簿,只是可视化部分的呈现方式不同而已。这种划分通常被称为 模型-视图 模式。在这个模式中,数据部分被称为模型(model),而可视化部分是由视图(view)处理的。

在 QML 中,模型(model)和视图(view)是由代理(delegate)连接起来的。责任分为以下几点。该模型提供了数据。对于每个数据项,可能有多个值。在上面提到的电话本的例子中,最简单的电话本条目基本上是由一个名称、一个头像和一串电话数字数字组成。数据被排列在视图(view)中,在视图(view)中,每个项目都使用代理(delegate)进行可视化的处理。视图(view)的任务是对代理进行排列,而每个代理(delegate)将每个模型(model)项的值显示给用户。

Model-View-Delegate

6.2 基本模型

将数据从视图显示中分离出来的最基本的方法是使用 Repeater 元素。它用于实例化一个 QML 可视元素的数组,并且很容易与定位器相结合来填充用户界面的一部分。Repeater 有一个模型(model)属性,它可以是使用任意 QML 可视元素的数量来作为值进行实例化,也可以是从网络上获取数据的完整的数据模型。

在最简单的形式中,Repeater 可以用来实例化指定数量的 QML 可视元素。每个条目都可以访问一个附加的属性,变量索引(index),它可以用来区分不同的条目。在下面的例子中,一个 Repeater 被用来创建一个有10个项目实例的视图。项目的数量由 model 属性控制。对于 Repeater 中的已经实例化的每一项都是一个 Rectangle 元素中包含着一个 Text 元素。正如你看到的,Text 元素的 text 属性被设置为 index 的值,因此项目是从 0 到 9 显示的。

下面是示例 Example 01:

import QtQuick 2.5
import "../common"

Column {
    spacing: 2

    Repeater {
        model: 10
        BlueBox {
            width: 120
            height: 32
            text: index
        }
    }
}
repeater-number

有编号的条目列表看起来似乎很不错,但是显示一个更复杂的数据集可能更有趣也更符合我们的实际需要。我们可以通过使用 JS 数组替换掉原有的数字值作为 model 的值来实现我们的想法。数组的内容可以是任何类型的,无论是字符串、整数还是对象。在下面的例子中,使用了一个字符串列表。这时,我们在仍然可以访问和使用索引变量(index)的同时,我们也可以使用包含数组中每个元素的数据的 modelData 属性。

import QtQuick 2.5
import "../common"

Column {
    spacing: 2

    Repeater {
        model: ["Enterprise", "Columbia", "Challenger", "Discovery", "Endeavour", "Atlantis"]

        BlueBox {
            width: 100
            height: 32
            radius: 3

            text: modelData + ' (' + index + ')'
        }
    }
}
repeater-array

由于能够公开一个数组的数据,我们很快就会发现自己需要数组中的每一项可以包含多个数据项。ListModel 是最简单,也是最常用的模型之一。ListModel 是 ListElement 元素的集合。 在每个列表元素内,可以将多个属性和其对应的值绑定。 例如,在下面的示例中,为每个元素提供了一个名称和颜色。

每个元素内的属性被 Repeater 附加到每个实例化的项。这意味着变量 name 和 surfaceColor 可以在由 Repeater 创建的每个 Rectangle 和 Text 项目的范围内使用。这不仅使访问数据变得容易,还可以轻松地读取源代码。surfaceColor 是名称左侧的圆圈的颜色,这是很形象的,而不是像第 j 行的 i 列的数据那样模糊的概念。

import QtQuick 2.5
import "../common"

Column {
    spacing: 2

    Repeater {
        model: ListModel {
            ListElement { name: "Mercury"; surfaceColor: "gray" }
            ListElement { name: "Venus"; surfaceColor: "yellow" }
            ListElement { name: "Earth"; surfaceColor: "blue" }
            ListElement { name: "Mars"; surfaceColor: "orange" }
            ListElement { name: "Jupiter"; surfaceColor: "orange" }
            ListElement { name: "Saturn"; surfaceColor: "yellow" }
            ListElement { name: "Uranus"; surfaceColor: "lightBlue" }
            ListElement { name: "Neptune"; surfaceColor: "lightBlue" }
        }

        BlueBox {
            width: 120
            height: 32

            radius: 3
            text: name

            Box {
                anchors.left: parent.left
                anchors.verticalCenter: parent.verticalCenter
                anchors.leftMargin: 4

                width: 16
                height: 16

                radius: 8

                color: surfaceColor
            }
        }
    }
}
repeater-model

正在为每个项目实例化的 Repeater 的内容实际上是绑定到默认属性,delegate 的内容。这意味着 Example 01 的代码与下面显示的代码同义。请注意,唯一的区别是 delegate 属性名称在后者中被明确列出。

import QtQuick 2.5
import "../common"

Column {
    spacing: 2

    Repeater {
        model: 10

        delegate: BlueBox {
            width: 100
            height: 32
            text: index
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读