Repeater适用于少量的静态数据集。但是在实际应用中,数据模型往往是非常复杂的,并且数量巨大。这种情况下,Repeater并不十分适合。于是,QtQuick 提供了两个专门的视图元素:ListView和GridView。这两个元素都继承自Flickable,因此允许用户在一个很大的数据集中进行移动。同时,ListView和GridView能够复用创建的代理,这意味着,ListView和GridView不需要为每一个数据创建一个单独的代理。这种技术减少了大量代理的创建造成的内存问题。

由于ListView和GridView在使用上非常相似,因此我们以ListView为例进行介绍。

ListView类似前面章节提到的Repeater元素。ListView使用模型提供数据,创建代理渲染数据。下面是ListView的简单使用:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import QtQuick 2.2
 
Rectangle {
    width: 80
    height: 300
    color: "white"
    ListView {
        anchors.fill: parent
        anchors.margins: 20
        clip: true
        model: 100
        delegate: numberDelegate
        spacing: 5
    }
 
    Component {
        id: numberDelegate
        Rectangle {
            width: 40
            height: 40
            color: "lightGreen"
            Text {
                anchors.centerIn: parent
                font.pixelSize: 10
                text: index
            }
        }
    }
}

代码运行结果如下图所示:

如果数据模型包含的数据不能在一屏显示完全,ListView只会显示整个列表的一部分。但是,作为 QtQuick 的一种默认行为,ListView并不能限制显示范围就在代理显示的区域内。这意味着,代理可能会在ListView的外部显示出来。为避免这一点,我们需要设置clip属性为true,使得超出ListView边界的代理能够被裁减掉。注意下图所示的行为(左面是设置了clip的ListView而右图则没有):

对于用户而言,ListView是一个可滚动的区域。ListView支持平滑滚动,这意味着它能够快速流畅地进行滚动。默认情况下,这种滚动具有在向下到达底部时会有一个反弹的特效。这一行为由boundsBehavior属性控制。boundsBehavior属性有三个可选值:Flickable.StopAtBounds完全消除反弹效果;Flickable.DragOverBounds在自由滑动时没有反弹效果,但是允许用户拖动越界;Flickable.DragAndOvershootBounds则是默认值,意味着不仅用户可以拖动越界,还可以通过自由滑动越界。

当列表滑动结束时,列表可能停在任意位置:一个代理可能只显示一部分,另外部分被裁减掉。这一行为是由snapMode属性控制的。snapMode属性的默认值是ListView.NoSnap,也就是可以停在任意位置;ListView.SnapToItem会在某一代理的顶部停止滑动;ListView.SnapOneItem则规定每次滑动时不得超过一个代理,也就是每次只滑动一个代理,这种行为在分页滚动时尤其有效。

默认情况下,列表视图是纵向的。通过orientation属性可以将其改为横向。属性可接受值为ListView.Vertical或ListView.Horizontal。例如下面的代码:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import QtQuick 2.2
 
Rectangle {
    width: 480
    height: 80
    color: "white"
 
    ListView {
        anchors.fill: parent
        anchors.margins: 20
        clip: true
        model: 100
        orientation: ListView.Horizontal
        delegate: numberDelegate
        spacing: 5
    }
    
    Component {
        id: numberDelegate
    
        Rectangle {
            width: 40
            height: 40
            color: "lightGreen"
            Text {
                anchors.centerIn: parent
                font.pixelSize: 10
                text: index
            }
        }
    }
}

当列表视图横向排列时,其中的元素按照从左向右的顺序布局。使用layoutDirection属性可以修改这一设置。该属性的可选值为Qt.LeftToRight或Qt.RightToLeft。

在触摸屏环境下使用ListView,默认的设置已经足够。但是,如果在带有键盘的环境下,使用方向键一般应该突出显示当前项。这一特性在 QML 中称为“高亮”。与普通的代理类似,视图也支持使用一个专门用于高亮的代理。这可以认为是一个额外的代理,只会被实例化一次,并且只会移动到当前项目的位置。

下面的例子设置了两个属性。第一,focus属性应当被设置为true,这允许ListView接收键盘焦点。第二,highlight属性被设置为一个被使用的高亮代理。这个高亮代理可以使用当前项目的x、y和height属性;另外,如果没有指定width属性,也可以使用当前项目的width属性。在这个例子中,宽度是由ListView.view.width附加属性提供的。我们会在后面的内容详细介绍这个附加属性。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import QtQuick 2.2
 
Rectangle {
    width: 240
    height: 300
    color: "white"
 
    ListView {
        anchors.fill: parent
        anchors.margins: 20
        clip: true
        model: 100
        delegate: numberDelegate
        spacing: 5
        highlight: highlightComponent
        focus: true
    }
    
    Component {
        id: highlightComponent
        Rectangle {
            width: ListView.view.width
            color: "lightGreen"
        }
    }
    
    Component {
        id: numberDelegate
        Item {
            width: 40
            height: 40
            Text {
                anchors.centerIn: parent
                font.pixelSize: 10
                text: index
            }
        }
    }
}

运行结果如下图所示:

在使用高亮时,QML 提供了很多属性,用于控制高亮的行为。例如,highlightRangeMode设置高亮如何在视图进行显示。默认值ListView.NoHighlightRange意味着高亮区域和项目的可视范围没有关联;ListView.StrictlyEnforceRange则使高亮始终可见,如果用户试图将高亮区域从视图的可视区域移开,当前项目也会随之改变,以便保证高亮区域始终可见;介于二者之间的是ListView.ApplyRange,它会保持高亮区域可视,但是并不强制,也就是说,如果必要的话,高亮区域也会被移出视图的可视区。

默认情况下,高亮的移动是由视图负责的。这个移动速度和大小的改变都是可控的,相关属性有highlightMoveSpeed,highlightMoveDuration,highlightResizeSpeed以及highlightResizeDuration。其中,速度默认为每秒 400 像素;持续时间被设置为 -1,意味着持续时间由速度和距离控制。同时设置速度和持续时间则由系统选择二者中较快的那个值。有关高亮更详细的设置则可以通过将highlightFollowCurrentItem属性设置为false达到。这表示视图将不再负责高亮的移动,完全交给开发者处理。下面的例子中,高亮代理的y属性被绑定到ListView.view.currentItem.y附加属性。这保证了高亮能够跟随当前项目。但是,我们不希望视图移动高亮,而是由自己完全控制,因此在y属性上面应用了一个Behavior。下面的代码将这个移动的过程分成三步:淡出、移动、淡入。注意,SequentialAnimation和PropertyAnimation可以结合NumberAnimation实现更复杂的移动。有关动画部分,将在后面的章节详细介绍,这里只是先演示这一效果。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Component {
    id: highlightComponent
    Item {
        width: ListView.view.width
        height: ListView.view.currentItem.height
        y: ListView.view.currentItem.y
            
        Behavior on y {
            SequentialAnimation {
                PropertyAnimation { target: highlightRectangle; property: "opacity"; to: 0; duration: 200 }
                NumberAnimation { duration: 1 }
                PropertyAnimation { target: highlightRectangle; property: "opacity"; to: 1; duration: 200 }
            }
        }
            
        Rectangle {
            id: highlightRectangle
            anchors.fill: parent
            color: "lightGreen"
        }
    }
}

最后需要介绍的是ListView的 header 和 footer。header 和 footer 可以认为是两个特殊的代理。虽然取名为 header 和 footer,但是这两个部分实际会添加在第一个元素之前和最后一个元素之后。也就是说,对于一个从左到右的横向列表,header 会出现在最左侧而不是上方。下面的例子演示了 header 和 footer 的位置。header 和 footer 通常用于显示额外的元素,例如在最底部显示“加载更多”的按钮。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import QtQuick 2.2
 
Rectangle {
    width: 80
    height: 300
    color: "white"
 
    ListView {
        anchors.fill: parent
        anchors.margins: 20
        clip: true
        model: 4
        delegate: numberDelegate
        spacing: 5
        header: headerComponent
        footer: footerComponent
    }
    
    Component {
        id: headerComponent
        Rectangle {
            width: 40
            height: 20
            color: "yellow"
        }
    }
 
    Component {
        id: footerComponent
        Rectangle {
            width: 40
            height: 20
            color: "red"
        }
    }
    
    Component {
        id: numberDelegate
        Rectangle {
            width: 40
            height: 40
            color: "lightGreen"
            Text {
                anchors.centerIn: parent
                font.pixelSize: 10
                text: index
            }
        }
    }
}

需要注意的是,header 和 footer 与ListView之间没有预留间距。这意味着,header 和 footer 将紧贴着列表的第一个和最后一个元素。如果需要在二者之间留有一定的间距,则这个间距应该成为 header 和 footer 的一部分。

GridView与ListView非常相似,唯一的区别在于,ListView用于显示一维列表,GridView则用于显示二维表格。相比列表,表格的元素并不依赖于代理的大小和代理之间的间隔,而是由cellWidth和cellHeight属性控制一个单元格。每一个代理都会被放置在这个单元格的左上角。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import QtQuick 2.2
 
Rectangle {
    width: 240
    height: 300
    color: "white"
 
    GridView {
        anchors.fill: parent
        anchors.margins: 20
        clip: true
        model: 100
        cellWidth: 45
        cellHeight: 45
        delegate: numberDelegate
    }
    
    Component {
        id: numberDelegate
        Rectangle {
            width: 40
            height: 40
            color: "lightGreen"
            Text {
                anchors.centerIn: parent
                font.pixelSize: 10
                text: index
            }
        }
    }
}

与ListView类似,GridView也可以设置 header 和 footer,也能够使用高亮代理和类似列表的边界行为。GridView支持不同的显示方向,这需要使用flow属性控制,可选值为GridView.LeftToRight和GridView.TopToBottom。前者按照先从左向右、再从上到下的顺序填充,滚动条出现在竖直方向;后者按照先从上到下、在从左到右的顺序填充,滚动条出现在水平方向。

 

Qt 学习之路 :动态视图的更多相关文章

  1. Qt 学习之路:视图选择 (QItemSelectionModel)

    选择是视图中常用的一个操作.在列表.树或者表格中,通过鼠标点击可以选中某一项,被选中项会变成高亮或者反色.在 Qt 中,选择也是使用了一种模型.在 model/view 架构中,这种选择模型提供了一种 ...

  2. Qt 学习之路 :视图代理

    与 Qt model/view 架构类似,在自定义用户界面中,代理扮演着重要的角色.模型中的每一个数据项都要通过一个代理向用户展示,事实上,用户看到的可视部分就是代理. 每一个代理都可以访问一系列属性 ...

  3. Qt 学习之路 2(47):视图选择

    Qt 学习之路 2(47):视图选择 豆子 2013年3月28日 Qt 学习之路 2 34条评论 选择是视图中常用的一个操作.在列表.树或者表格中,通过鼠标点击可以选中某一项,被选中项会变成高亮或者反 ...

  4. Qt 学习之路 2(46):视图和委托

    Home / Qt 学习之路 2 / Qt 学习之路 2(46):视图和委托 Qt 学习之路 2(46):视图和委托  豆子  2013年3月11日  Qt 学习之路 2  63条评论 前面我们介绍了 ...

  5. 《Qt 学习之路 2》目录

    <Qt 学习之路 2>目录 <Qt 学习之路 2>目录  豆子  2012年8月23日  Qt 学习之路 2  177条评论 <Qt 学习之路 2>目录 序 Qt ...

  6. Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON

    Home / Qt 学习之路 2 / Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON  豆子 ...

  7. Qt 学习之路 2(57):可视化显示数据库数据

    Qt 学习之路 2(57):可视化显示数据库数据(skip) 豆子 2013年6月26日 Qt 学习之路 2 26条评论 前面我们用了两个章节介绍了 Qt 提供的两种操作数据库的方法.显然,使用QSq ...

  8. Qt 学习之路 2(51):布尔表达式树模型

    Qt 学习之路 2(51):布尔表达式树模型 豆子 2013年5月15日 Qt 学习之路 2 17条评论 本章将会是自定义模型的最后一部分.原本打算结束这部分内容,不过实在不忍心放弃这个示例.来自于 ...

  9. Qt 学习之路 2(50):自定义可编辑模型

    Home / Qt 学习之路 2 / Qt 学习之路 2(50):自定义可编辑模型 Qt 学习之路 2(50):自定义可编辑模型 豆子 2013年5月13日 Qt 学习之路 2 13条评论 上一章我们 ...

  10. Qt 学习之路 2(49):自定义只读模型

    Qt 学习之路 2(49):自定义只读模型 豆子 2013年5月5日 Qt 学习之路 2 18条评论 model/view 模型将数据与视图分割开来,也就是说,我们可以为不同的视图,QListView ...

随机推荐

  1. LPC1114

    时钟配置: 3个时钟源:系统振荡源(system),IRC振荡源,(IRC,内部RC振荡器)看门狗振荡源(WatchDog) MAINCLKSEL:主时钟源选择寄存器(复位值:0) 只用了前两位: 0 ...

  2. boost之algorithm/string

    头文件: #include<iostream>#include <boost/algorithm/string.hpp>using namespace std;using na ...

  3. C++11老关键字的新含义(auto, using,extern)

    http://blog.csdn.net/cnsword/article/details/8034947 公司可以使用c++11.看大牛的代码模仿使用,所以现在已经不知道什么使用的是c++的语法还是c ...

  4. css3:user-select属性

    一.user-select简介 这是在css3 UI规范中新增的一个功能,用来控制内容的可选择性 二.user-select:值 auto——默认值,用户可以选中元素中的内容 none——用户不能选择 ...

  5. Nginx配置免费SSL证书StartSSL,解决Firefox不信任问题

    先在StartSSL上申请免费一年的SSL证书,具体过程网上很多教程.然后把申请到的key和crt文件上传到服务器,比如/usr/local/nginx/certs/. Nginx配置SSL证书 直接 ...

  6. asp.net学习

    http://www.cnblogs.com/fish-li/archive/2011/12/27/2304063.html

  7. django中的事务管理

    在讲解之前首先来了解一下数据库中的事务. 什么是数据库中的事务? 热心网友回答: ():事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不 ...

  8. ShareSDK(iOS版)开发实践:自定义授权视图和分享视图导航栏

    最近很多人问ShareSDK的授权视图和分享视图的导航栏样式与应用风格不一致,能否修改导航栏的样式?那么这里我就2.6.1版本进行说明(还在使用1.x版本的朋友建议升级到2.x版本,在新版本中可定制的 ...

  9. mac 目录详解

    打开Macintosh HD你会发现内中有四个文件夹 分别有——应用程序(Applications).系统(System).用户(User).资料库(Library).四个文件夹中又分别各有若干数量的 ...

  10. mysql排序,可以对统计的数据进行排序

    sql SELECT a.*,b.name as address_name,b.tel as address_tel,b.province as address_province,b.city as ...