#(84):Repeater
[前面的章节](http://www.devbean.net/2013/01/qt-study-road-2-model-view/)我们介绍过模型视图。这是一种数据和显示相分离的技术,在 Qt 中有着非常重要的地位。在 QtQuick 中,数据和显示的分离同样也是利用这种“模型-视图”技术实现的。对于每一个视图,数据元素的可视化显示交给代理完成。与 Qt/C++ 类似,QtQuick 提供了一系列预定义的模型和视图。本章开始,我们着重介绍这部分内容。这部分内容主要来自[http://qmlbook.org/ch06/index.html](http://qmlbook.org/ch06/index.html),在此表示感谢。
由于 QtQuick 中的模型视图的基本概念同[前面的章节](http://www.devbean.net/2013/01/qt-study-road-2-model-view/)没有本质的区别,所以这里不再赘述这部分内容。
将数据从表现层分离的最基本方法是使用`Repeater`元素。`Repeater`元素可以用于显示一个数组的数据,并且可以很方便地在用户界面进行定位。`Repeater`的模型范围很广:从一个整型到网络数据,均可作为其数据模型。
`Repeater`最简单的用法是将一个整数作为其`model`属性的值。这个整型代表`Repeater`所使用的模型中的数据个数。例如下面的代码中,`model: 10`代表`Repeater`的模型有 10 个数据项。
~~~
import QtQuick 2.2
Column {
spacing: 2
Repeater {
model: 10
Rectangle {
width: 100
height: 20
radius: 3
color: "lightBlue"
Text {
anchors.centerIn: parent
text: index
}
}
}
}
~~~
现在我们设置了 10 个数据项,然后定义一个`Rectangle`进行显示。每一个`Rectangle`的宽度和高度分别为 100px 和 20px,并且有圆角和浅蓝色背景。`Rectangle`中有一个`Text`元素为其子元素,`Text`文本值为当前项的索引。代码运行结果如下:
[![](https://box.kancloud.cn/2015-12-29_56823286b6ca2.png)](http://files.devbean.net/images/2014/06/repeater-demo.png)
虽然指定模型项的个数很简单,但实际用处不大。`Repeater`还支持更复杂的方式,例如,把一个 JavaScript 数组作为模型。JavaScript 数组元素可以是任意类型:字符串、数字或对象。在下面的例子中,我们将一个字符串数组作为`Repeater`的模型。我们当然可以使用`index`获得当前索引,同时,我们也可以使用`modelData`访问到数组中的每一个元素的值:
~~~
import QtQuick 2.2
Column {
spacing: 2
Repeater {
model: ["Enterprise", "Colombia", "Challenger", "Discovery", "Endeavour", "Atlantis"]
Rectangle {
width: 100
height: 20
radius: 3
color: "lightBlue"
Text {
anchors.centerIn: parent
text: index +": "+modelData
}
}
}
}
~~~
代码运行结果如下:
![](https://box.kancloud.cn/2015-12-29_56823286c3af0.png)
由于能够使用 JavaScript 数组作为`Repeater`的模型,而 JavaScript 数组能够以对象作为其元素类型,因而`Repeater`就可以处理复杂的数据项,比如带有属性的对象。这种情况其实更为常见。相比普通的 JavaScript 对象,更常用的是`ListElement`类型。类似普通 JavaScript 对象,每一个`ListElement`可以有任意属性。例如下面的代码示例中,每一个数据项都有一个名字和外观颜色。
~~~
import QtQuick 2.2
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" }
}
Rectangle {
width: 100
height: 20
radius: 3
color: "lightBlue"
Text {
anchors.centerIn: parent
text: name
}
Rectangle {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 2
width: 16
height: 16
radius: 8
border.color: "black"
border.width: 1
color: surfaceColor
}
}
}
}
~~~
运行结果如下图所示:
[![](https://box.kancloud.cn/2015-12-29_56823286d2d22.png)](http://files.devbean.net/images/2014/06/repeater-listelement.png)
`ListElement`的每个属性都被`Repeater`绑定到实例化的显示项。正如上面代码中显示的那样,这意味着每一个用于显示数据的`Rectangle`作用域内都可以访问到`ListElement`的`name`和`surfaceColor`属性。
像上面几段代码中,`Repeater`的每一个数据项都使用一个`Rectangle`渲染。事实上,这是由于`Repeater`具有一个`delegate`的默认属性,由于`Rectangle`没有显式赋值给任何一个属性,因此它直接成为默认属性`delegate`的值,所以才会使用`Rectangle`渲染。理解了这一点,我们就可以写出具有显式赋值的代码:
~~~
import QtQuick 2.2
Column {
spacing: 2
Repeater {
model: 10
delegate: Rectangle {
width: 100
height: 20
radius: 3
color: "lightBlue"
Text {
anchors.centerIn: parent
text: index
}
}
}
}
~~~
实际上,这段代码与前面提到的是等价的。
- (1)序
- (2)Qt 简介
- (3)Hello, world!
- (4)信号槽
- (5)自定义信号槽
- (6)Qt 模块简介
- (7)MainWindow 简介
- (8)添加动作
- (9)资源文件
- (10)对象模型
- (11)布局管理器
- (12)菜单栏、工具栏和状态栏
- (13)对话框简介
- (14)对话框数据传递
- (15)标准对话框 QMessageBox
- (16)深入 Qt5 信号槽新语法
- (17)文件对话框
- (18)事件
- (19)事件的接受与忽略
- (21)事件过滤器
- (22)事件总结
- (23)自定义事件
- (24)Qt 绘制系统简介
- (25)画刷和画笔
- (26)反走样
- (27)渐变
- (28)坐标系统
- (29)绘制设备
- (30)Graphics View Framework
- (31)贪吃蛇游戏(1)
- (32)贪吃蛇游戏(2)
- (33)贪吃蛇游戏(3)
- (34)贪吃蛇游戏(4)
- (35)文件
- (36)二进制文件读写
- (37)文本文件读写
- (38)存储容器
- (39)遍历容器
- (40)隐式数据共享
- (41)model/view 架构
- (42)QListWidget、QTreeWidget 和 QTableWidget
- (43)QStringListModel
- (44)QFileSystemModel
- (45)模型
- (46)视图和委托
- (47)视图选择
- (48)QSortFilterProxyModel
- (49)自定义只读模型
- (50)自定义可编辑模型
- (51)布尔表达式树模型
- (52)使用拖放
- (53)自定义拖放数据
- (54)剪贴板
- (55)数据库操作
- (56)使用模型操作数据库
- (57)可视化显示数据库数据
- (58)编辑数据库外键
- (59)使用流处理 XML
- (60)使用 DOM 处理 XML
- (61)使用 SAX 处理 XML
- (62)保存 XML
- (63)使用 QJson 处理 JSON
- (64)使用 QJsonDocument 处理 JSON
- (65)访问网络(1)
- (66)访问网络(2)
- (67)访问网络(3)
- (68)访问网络(4)
- (69)进程
- (70)进程间通信
- (71)线程简介
- (72)线程和事件循环
- (73)Qt 线程相关类
- (74)线程和 QObject
- (75)线程总结
- (76)QML 和 QtQuick 2
- (77)QML 语法
- (78)QML 基本元素
- (79)QML 组件
- (80)定位器
- (81)元素布局
- (82)输入元素
- (83)Qt Quick Controls
- (84)Repeater
- (85)动态视图
- (86)视图代理
- (87)模型-视图高级技术
- (88)Canvas
- (89)Canvas(续)