首页 Qt 学习之路 2 Qt 学习之路 2(84):Repeater

Qt 学习之路 2(84):Repeater

16 6

前面的章节我们介绍过模型视图。这是一种数据和显示相分离的技术,在 Qt 中有着非常重要的地位。在 QtQuick 中,数据和显示的分离同样也是利用这种“模型-视图”技术实现的。对于每一个视图,数据元素的可视化显示交给代理完成。与 Qt/C++ 类似,QtQuick 提供了一系列预定义的模型和视图。本章开始,我们着重介绍这部分内容。这部分内容主要来自http://qmlbook.org/ch06/index.html,在此表示感谢。

由于 QtQuick 中的模型视图的基本概念同前面的章节没有本质的区别,所以这里不再赘述这部分内容。

将数据从表现层分离的最基本方法是使用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文本值为当前项的索引。代码运行结果如下:

Repeater 示例

虽然指定模型项的个数很简单,但实际用处不大。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
            }
        }
    }
}

代码运行结果如下:
Repeater 数组模型

由于能够使用 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
            }
        }
    }
}

运行结果如下图所示:

Repeater 使用 ListElement

ListElement的每个属性都被Repeater绑定到实例化的显示项。正如上面代码中显示的那样,这意味着每一个用于显示数据的Rectangle作用域内都可以访问到ListElementnamesurfaceColor属性。

像上面几段代码中,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
            }
        }
    }
}

实际上,这段代码与前面提到的是等价的。

16 评论

youcantknow 2014年6月28日 - 20:27

亲爱的的豆子老师你好,一直追踪你的课程,非常的感谢你。我要给我们公司开发一个进销存,界面我打算用QML来写,淘宝公司的淘宝助理 就是用QT写的,里面用了大量qml, 为了给我们公司写一个进销存,我一直在不断的学习qml,希望豆子老师多多的讲讲qml 谢谢老师 ,豆子老师什么时候出书呀

回复
豆子 2014年6月29日 - 08:37

这个系列之后的重点就在 QML 了。书的话估计要到年底左右的,感谢关注!;-P

回复
youcantknow 2014年6月29日 - 16:13

谢谢老师,求老师多多的详细的介绍qml, 谢谢 嘿嘿

回复
youcantknow 2014年6月28日 - 20:32

已捐款50. 钱少感情多,谢谢老师

回复
豆子 2014年6月29日 - 08:36

多谢支持,共同进步!

回复
vx 2014年8月3日 - 16:56

你好,我安装了 qt-opensource-windows-x86-msvc2013_64_opengl-5.3.1,
生成两个可执行文件,一个是qt creator,另一个是qt designer;
打开qt creator后,其界面上的qt designer,不可用,无法创建qt GUI程序。

另外单独打开qt designer,可以使用,但是没法编写程序,比如打开main.cpp等。
请问什么情况,x谢谢!

回复
豆子 2014年8月5日 - 21:17

你是自己编译的 Qt 吗?如果是直接安装官方的二进制文件,还没有出现你说的那种情况。会不会是文件关联的问题?

回复
vx 2014年8月5日 - 21:36

o 哦 安装错了,出问题了
64位兼容性不好啊,重装了一遍 好了。

谢谢啦

回复
muggle111 2014年9月26日 - 22:33

豆子兄,你提供的:
http://qmlbook.org/ch06/index.html

https://www.devbean.net/2013/01/qt-study-road-2-model-view/
两者的图矛盾。关键是后者的delegate的箭头是双向的,这应该不对。

另外,你辛苦写了这么多,有没有考虑一下出本书啊?我觉得你讲的实在是很好,深入浅出。你出书,我一定第一时间买。就是还应该再讲讲QSS,其威力绝对不可小觑,做出来的界面绝对漂亮,还不影响程序逻辑!!

回复
豆子 2014年9月28日 - 09:32

后面的图是 Qt 文档里面的,应该要比 qmlbook 的要准确一些。个人感觉文档中的图更准确一些,箭头应该从 Model 发出显得更合理。
现在有和别人合作写过一本书,目前正在出版社审核,多谢支持哦

回复
muggle111 2014年10月6日 - 23:08

另外请问豆子兄,你这一系列的教程,有没有相关的源码啊?现在不放在网上可以,但是将来还是要随书一起出版的吧?

回复
豆子 2014年10月7日 - 10:28

源代码都是在每一章节的最后,应该是可以下载的。

回复
nikoloss 2015年2月21日 - 15:30

豆子你好,能否教授一下各大平台上面qt打包方面的教程,我发现网上这方面的东西比较少,我最近在把程序打包在Linux碰到了不少问题。

回复
豆子 2015年3月9日 - 14:10

linux 平台一般是要求用户自行安装 Qt 库的,或者使用 rpm、deb 之类的平台相关包

回复
fan 2016年3月31日 - 17:46

看本章节的例3 又有点蒙圈了, 我理解的是Repeater即使是没有delegate属性,Rectangle就是其子元素,不管怎么样,子元素都得渲染啊。所以渲染数据项跟delegate属性有什么关系呢。

回复
fan 2016年3月31日 - 18:04

看到后面的章节 似乎有有点理解了,Rectangle作为Repeater的子元素只是为了给其默认属性delegate赋值,其实这里的Rectangle可以在其他地方,只要显示赋值给delegate属性就行。

回复

发表评论

关于我

devbean

devbean

豆子,生于山东,定居南京。毕业于山东大学软件工程专业。软件工程师,主要关注于 Qt、Angular 等界面技术。

主题 Salodad 由 PenciDesign 提供 | 静态文件存储由又拍云存储提供 | 苏ICP备13027999号-2