首页 > Qt 学习之路:模型-视图高级技术

Qt 学习之路:模型-视图高级技术

PathView

PathView是 QtQuick 中最强大的视图,同时也是最复杂的。PathView允许创建一种更灵活的视图。在这种视图中,数据项并不是方方正正,而是可以沿着任意路径布局。沿着同一布局路径,数据项的属性可以被更详细的设置,例如缩放、透明度等。

 

使用PathView首先需要定义一个代理和一个路径。除此之外,PathView还可以设置很多其它属性,其中最普遍的是pathItemCount,用于设置可视数据项的数目;preferredHighlightBeginpreferredHighlightEndhighlightRangeMode可以设置高亮的范围,也就是沿着路径上面的当前可以被显示的数据项。

在深入了解高亮范围之前,我们必须首先了解path属性。path接受一个Path元素,用于定义PathView中的代理所需要的路径。该路径使用startXstartY属性,结合PathLinePathQuadPathCubic等路径元素进行定义。这些元素可以结合起来形成一个二维路径。

一旦路径定义完成,我们可以使用PathPercentPathAttribute元素进行调整。这些元素用于两个路径元素之间,更好的控制路径和路径上面的代理。PathPercent控制两个元素之间的路径部分有多大。它控制了路径上面代理的分布,这些代理按照其定义的百分比进行分布。

PathAttribute元素同PathPercent同样放置在元素之间。该元素允许沿路径插入一些属性值。这些属性值附加到代理上面,可用于任何能够使用的属性。

下面的例子演示了如何利用PathView实现卡片的弹入。这里使用了一些技巧来达到这一目的。它的路径包含三个PathLine元素。通过PathPercent元素,中间的元素可以正好位于中央位置,并且能够留有充足的空间,以避免被别的元素遮挡。元素的旋转、大小缩放和 Z 轴都是由PathAttribute进行控制。除了定义路径,我们还设置了PathViewpathItemCount属性。该属性用于指定路径所期望的元素个数。最后,代理中的PathView.onPath使用preferredHighlightBeginpreferredHighlightEnd属性控制代理的可见性。

 

 

代理直接使用了通过PathAttribute元素附加的itemZitemAngleitemScale属性。需要注意的是,被附加到代理的属性只能在wrapper中使用。因此,我们又定义了一个rotX属性,以便在内部的Rotation元素中使用。另一点需要注意的是附件属性PathView.onPath的使用。通常我们会将这个属性绑定到可视化属性,这样允许PathView保留非可见元素,以便进行缓存。如果不这样设置,不可见元素可能会由于界面裁剪等原因被销毁,因为PathViewListViewGridView要灵活得多,所以为提高性能,一般会使用这种绑定实现缓存。

 

 

示例运行结果如下:

PathView

完成PathView中图片和一些复杂元素的变换之后,通常会进行一定的性能优化,比如,将Image元素的smooth属性绑定到PathView.view.moving附加属性。这意味着在移动时,图片质量会稍有下降,静止时恢复正常。在视图移动时,很少有用户会在意图片的清晰度,因此,这样的妥协一般是可以接受的。

从 XML 加载模型

XML 是一种非常常见的数据格式,QML 提供了XmlListModel元素支持将 XML 数据转换为模型。XmlListModel可以加载本地或远程的 XML 文档,使用 XPath 表达式处理数据。

下面的例子给出了如何从 RSS 获取图片。source属性指向了一个远程地址,其数据会被自动下载下来。

 

 

当数据被下载下来,这个 XML 就被处理成模型的数据项和角色。query属性是 XPath 表达式语言,用于创建模型数据项。在这个例子中,该属性值为/rss/channel/item,因此,rss 标签下的每一个 channel 标签中的每一个 item 标签,都会被生成一个数据项。每一个数据项都可以定义一系列角色,这些角色使用XmlRole表示。每一个角色都有一个名字,代理可以使用附件属性访问到其值。角色的值是使用 XPath 表达式获取的。例如,title属性的值由title/string()表达式决定,返回的是</code>和<code>标签之间的文本。imageSource属性值则更有趣。它并不是直接由 XML 获取的字符串,而是一系列函数的运算结果。在返回的 XML 中,有些 item 中包含图片,使用标签表示。使用substring-aftersubstring-beforeXPath 函数,可以找到每张图片的地址并返回。因此,imageSource属性可以直接作为Image元素的source属性值。

分组列表

有时,列表中的数据可以分成几个部分,例如,按照列表数据的首字母分组。利用ListView可以将一个扁平的列表分为几个组,如下图所示:

ListView 分组

为了使用分组,需要设置section.propertysection.criteria两个属性。section.property定义了使用哪个属性进行分组。这里,需要确保模型已经排好序了,以便每一部分能够包含连续的元素,否则,同一属性的名字可能出现在多个位置。section.criteria的可选值为ViewSection.FullStringViewSection.FirstCharacter。前者为默认值,适用于具有明显分组的模型,例如,音乐集等;后者按照属性首字母分组,并且意味着所有属性都适用于此,常见例子是电话本的通讯录名单。

一旦分组定义完毕,在每一个数据项就可以使用附加属性ListView.sectionListView.previousSectionListView.nextSection访问到这个分组。使用这个属性,我们就可以找到一个分组的第一个和最后一个元素,从而实现某些特殊功能。

我们也可以给ListViewsection.delegate属性赋值,以便自定义分组显示的代理。这会在一个组的数据项之前插入一个用于显示分组的代理。这个代理可以使用附加属性访问当前分组的名字。

下面的例子按照国别对一组人进行分组。国别被设置为section.property属性的值。section.delegate组件,也就是sectionDelegate,用于显示每组的名字,也就是国家名。每组中的人名则使用spaceManDelegate显示。

 

 

关于性能

模型视图的性能很大程度上取决于创建新的代理所造成的消耗。例如,如果clip属性设置为false,当向下滚动ListView时,系统会在列表末尾创建新的代理,并且将列表上部已经不可显示的代理移除。显然,当初始化代理需要消耗大量时间时,用户在快速拖动滚动条时,这种现象就会造成一定程度的影响。

为了避免这种情况,你可以调整被滚动视图的外边框的值。通过修改cacheBuffer属性即可达到这一目的。在上面所述的有关竖直滚动的例子中,这个属性会影响到列表上方和下方会有多少像素。这些像素则影响到是否能够容纳这些代理。例如,将异步加载图片与此结合,就可以实现在图片真正加载完毕之后才显示出来。

更多的代理意味着更多的内存消耗,从而影响到用户的操作流畅度,同时也有关代理初始化的时间。对于复杂的代理,上面的方法并不能从根本上解决问题。代理初始化一次,其内容就会被重新计算。这会消耗时间,如果这个时间很长,很显然,这会降低用户体验。代理中子元素的个数同样也有影响。原因很简单,移动更多的元素当然要更多的时间。为了解决前面所说的两个问题,我们推荐使用Loader元素。Loader元素允许延时加载额外的元素。例如,一个可展开的代理,只有当用户点击时,才会显示这一项的详细信息,包含一个很大的图片。那么,利用Loader元素,我们可以做到,只有其被显示时才进行加载,否则不加载。基于同样的原因,应该使每个代理中包含的 JavaScript 代码尽可能少。最好能做到在代理之外调用复杂的 JavaScript 代码。这将减少代理创建时编译 JavaScript 所消耗的时间。

转载于:https://www.cnblogs.com/lvdongjie/p/4811582.html

更多相关:

  • 文档树Document Object Model (DOM) 为文档对象模型, 它使用对象的表示方式来表示对应的文档结构及其中的内容。下面为一个样例 p 元素在文档中的对象所包含的所有属性。控制台:p#domaccessKey: ""align: ""assignedSlot: nullattributeStyleMap: Style...

  • 1、封装 什么是封装?   1.对外部隐藏内部的属性,以及实现细节,给外部提供使用的接口     注意:封装有隐藏的意思,但不是单纯的隐藏     学习封装的目的:就是为了能够限制外界对内部数据的访问   python中属性的权限分为两种:   1.公开的     没有任何限制,谁都可以访问   2.私有的     只有当前类本身能狗...

  • jquery:js框架; 主要区别在dom的操作 jq需要引入文件并且引入顺序在最上面; 找元素 操作元素 js:doucument.getElementById..classname,tagname,name jq:$(选择器) dom是js对象 jqDom是jquery对象 操作内容 js:dom.innerHTML(非表单元素)...

  • Mock.js 的语法规范包括两部分: 数据模板定义规范(Data Template Definition,DTD)数据占位符定义规范(Data Placeholder Definition,DPD)1.数据模板定义规范 DTD 数据模板中的每个属性由 3 部分构成:属性名、生成规则、属性值: // 属性名 name // 生...

  • vue   vue.js 是用于构建交互式的 Web 界面的库。它提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API。从技术上讲, Vue.js 集中在 MVVM 模式上的视图模型层,并通过双向数据绑定连接视图和模型。实际的 DOM 操作和输出格式被抽象出来成指令和过滤器。相比其它的 MVVM 框架,Vue.j...

  • 栈stack:stack 后入先出(LIFO) q.top()获取栈顶元素(并不删除)q.pop()删除栈顶元素q.push(x)向栈中加入元素q.empty()判断栈是否为空 队列queue:先入先出(FIFO)   q.front()获取队首元素(并不删除)q.pop()删除队首元素q.push(x)向队列中加入元素q....

  • resize(),设置大小(size); reserve(),设置容量(capacity); size()是分配容器的内存大小,而capacity()只是设置容器容量大小,但并没有真正分配内存。 打个比方:正在建造的一辆公交车,车里面可以设置40个座椅(reserve(40);),这是它的容量,但并不是说它里面就有了40个座椅,只能说...

  • v-for="(index,$i) in total" :key="$i":style="{left:`${itemWidth*((index-1)%rowItemCount)}px`,top:`${itemHeight*(Math.ceil(index/rowItemCount)-1)}px`}" //total是显示总数量 //l...

  •   技巧一(推荐指数★★★★★) 采用top、right、bottom、left,可以不在乎父元素的宽度和高度,对GPU损耗低于技巧三,但是对浏览器内存的消耗高于技巧三 .子元素 {/*父元素需要position: relative|absolute;*/position: absolute;margin: auto;to...

  • 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。 push(x) – 将元素 x 推入栈中。pop() – 删除栈顶的元素。top() – 获取栈顶元素。getMin() – 检索栈中的最小元素。 示例: MinStack minStack = new MinStack(); minStack...

  • 文章目录1. 解决问题2. 应用场景1. 业务系统的非功能性开发2. 代理模式在RPC、缓存中的应用3. 实现C++实现C语言实现 1. 解决问题 客户端和目标对象之间需要进行交互,此时客户端类和目标对象类相关操作之间的逻辑如果交合在一起,会导致客户端和目标对象模块耦合度升高,后期扩展客户端的功能时,则需要修改两者的源代码。...

  • 微信公众号:compassblog 欢迎关注、转发,互相学习,共同进步! 有任何问题,请后台留言联系! 1、AOP概述 (1)、什么是 AOP AOP 为 Aspect Oriented Programming 的缩写,意为“面向切面编程”。AOP 是 OOP (面向对象)的延续,可以对业务的各个部分进行隔离,从而使得业务逻辑各...