`
king_tt
  • 浏览: 2108588 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Qt Quick 之 PathView 详解

 
阅读更多

PathView ,顾名思义,沿着特定的路径显示 Model 内的数据。 Model 可以是 QML 内建的 ListModel 、 XmlListModel ,也可以是在 C++ 中实现的 QAbstractListModel 的派生类。

PathView 恐怕是 Qt Quick 提供的 Model-View 类库中最复杂也最灵活的一个了。

要使用一个 PathView ,至少需要设置 model 、 delegate 、 path 三个属性。

model 、 delegate 如果你学习过 ListView 肯定已经接触过,这里不再细说。 path 是 PathView 的专有特性,它指定 PathView 用来放置 item 的路径。要使用 PathView ,先要了解 Path 。

版权所有 foruok ,如需转载请注明出处:作者 foruok ,博客 http://blog.csdn.net/foruok

Path

西安是十三朝古都,虽然尿骚味很重,还是值得一游。于是你从杭州的武陵广场出发,准备去看兵马俑。先打的去萧山机场,步行进入航站楼,过安检,坐飞机到咸阳机场,出站,乘机场大巴到火车站,然后坐游 5 公交到兵马俑……在这个过程中,换乘的中间点很多,相邻两个中间点之间的,就是路径段;多个路径段最终形成了从杭州武陵广场到西安临潼兵马俑之间的路径;武陵广场是起点,兵马俑是终点。

在 Qt 中 Path 就是直译为路径,一个路径是由多个路径元素组成的,从起点开始,首尾衔接,抵达终点。

Path 的属性 startX 、 startY 描述路径起点。 pathElements 属性是个列表,是默认属性,它保存组成路径的多个路径元素,常见的路径元素有 PathLine 、 PathQuad 、 PathCubic 、 PathArc 、 PathCurve 、 PathSvg 。路径上最后一个路径元素的终点就是整个路径的终点,如果终点与起点重合,那么 Path 的 closed 属性就为 true 。

路径元素除 PathSvg 外,都有 x 、 y 属性,以绝对坐标的形式指定本段路径的终点;而起点呢,就是前一个路径段的终点;第一个路径段的起点,就是 Path 的 startX 、 startY 所描述的整个路径的起点。另外还有 relativeX 、 relativeY 两个属性,以相对于起点的相对坐标的形式来指定终点。你还可以混合使用绝对坐标与相对坐标,比如使用 x 和 relativeY 来决定路径段的终点。

PathLine

PathLine 是最简单的路径元素,在 Path 的起点或者上一段路径的终点,与本元素定义的终点之间绘制一条直线。
一个最简的路径示例:
    Path {
        startX: 0;
        startY: 0;
        PathLine {
            x: root.width - 1;
            y: root.height - 1;
        }
    }

上面的路径,是一条从界面左上角到右下角的直线。

PathQuad

贝塞尔曲线( Bézier curve ),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。
贝塞尔曲线于 1962 年,由法国工程师皮埃尔·贝塞尔( Pierre Bézier )所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由 Paul de Casteljau 于 1959 年运用 de Casteljau 算法开发,以稳定数值的方法求出贝塞尔曲线。
常见的贝塞尔曲线有线性贝塞尔曲线、二次方贝塞尔曲线、三次方贝塞尔曲线,当然也有四阶、五阶甚至更高阶的贝塞尔曲线。线性贝塞尔曲线其实只是两点之间的直线。二次方贝塞尔曲线,由两个端点和一个控制点以及一个函数来生成。三次方贝塞尔曲线,由两个端点和两个控制点以及一个函数来生成。
在 Qt Quick 的 Path 主题中,提供了基于二次方贝塞尔曲线和三次方贝塞尔曲线的路径元素。
在我们使用 Canvas 进行 2D 绘图时, Context2D 对象的 quadraticCurveTo(real cpx, real cpy, real x, real y) 方法可以在路径中添加一条二次方贝塞尔曲线, bezierCurveTo(real cp1x, real cp1y, real cp2x, real cp2y, real x, real y) 方法用来在路径中添加一条三次方贝塞尔曲线。
PathQuad 元素定义一条二次贝塞尔曲线作为路径段。它的起点为上一个路径元素的终点(或者路径的起点),终点由 x 、 y 或 relativeX 、 relativeY 定义,控制点由 controlX 、 controlY 或 relativeControlX 、 relativeControlY 来定义。
一个简单的二次方贝塞尔路径定义:
    Path {
        startX: 0;
        startY: 0;
        PathQuad {
            x: root.width - 1;
            y: root.height - 1;
            controlX: 0;
            controlY: root.height - 1;
        }
    }

在 Qt Quick 中, Path 虽然描述了一条路径,但它是不可见的,不够形象化。这里我们通过使用 Canvas 来绘制同样的曲线,以求大家看了可以有个直观的印象。上面的路径定义,对应 qml 代码:
import QtQuick 2.0
import QtQuick.Controls 1.1

Canvas {
    width: 320;
    height: 240;

    onPaint: {
        var ctx = getContext("2d");
        ctx.lineWidth = 2;
        ctx.strokeStyle = "red";
        ctx.beginPath();
        ctx.moveTo(0, 0);
        ctx.quadraticCurveTo(0, height - 1, width - 1, height - 1);
        ctx.stroke();
    }
    
    Text {
        anchors.centerIn: parent;
        font.pixelSize: 20;
        text: "quadratic Bezier curve";
    }
}

执行 "qmlscene pathQuad_canvas.qml" 命令,可以看到下图的效果:


PathCubic

PathCubic 定义一个三次方贝塞尔曲线,它有两个控制点。下面是一个简单的示例程序, pathCubic_canvas.qml :
import QtQuick 2.0
import QtQuick.Controls 1.1

Canvas {
    width: 320;
    height: 240;
    id: root;

    onPaint: {
        var ctx = getContext("2d");
        ctx.lineWidth = 2;
        ctx.strokeStyle = "red";
        ctx.beginPath();
        ctx.moveTo(16, 16);
        ctx.bezierCurveTo(0, height - 1, width -1, height / 2, width - 16, height - 16);
        ctx.stroke();
    }
    
    Text {
        anchors.centerIn: parent;
        font.pixelSize: 20;
        text: "cubic Bezier curve";
    }
    
    Rectangle {
        width: 32;
        height: 32;
        radius: 16;
        color: "blue";
        id: ball;
       
        MouseArea {
            anchors.fill: parent;
            id: mouseArea;
            onClicked: pathAnim.start();
        }
   
        PathAnimation {
            id: pathAnim;
            target: ball;
            duration: 3000;
            anchorPoint: "16,16";
            easing.type: Easing.InCubic;
            path: Path {
                startX: 16;
                startY: 16;
                PathCubic {
                    x: root.width - 16;
                    y: root.height - 16;
                    control1X: 0;
                    control1Y: root.height - 1;
                    control2X: root.width - 1;
                    control2Y: root.height / 2;
                }
            }
        } 
    }
}

如你所见,这次我使用 PathAnimation 来演示 PathCubic 的用法,请查看改动画元素的 API 文档。
我在 Canvas 的 onPaint() 方法中使用 bezierCurveTo() 绘制了一个三次方贝塞尔曲线,为的是能让你看见这个曲线到底什么模样。
我定义了一个 Rectangle 对象,长宽各为 32 ,设置其 radius 为 16 ,实际上就是个圆形。然后定义了 PathAnimation 对象,设置其 Path 为三次方贝塞尔曲线,与 onPaint() 方法绘制曲线所用参数完全一致;另外设置了 anchorPoint 为 ball 的中心点。 MouseArea 对象在鼠标左键点击时启动动画。
执行 "qmlscene pathCubic_canvas.qml" ,鼠标点击蓝色的圆圈,动画就开始咧。下图是运行中的截图:

PathArc

PathArc 路径元素定义一条弧线,它的起点为上一个路径元素的终点(或者路径的起点),终点由 x 、 y 或 relativeX 、 relativeY 定义。弧线的半径由 radiusX 、 radiusY 定义。
direction 属性定义绘制弧线的方向,默认取值 PathArc.Clockwise ,顺时针绘制弧线;要想逆时针绘制弧线,设置 direction 的值为 PathArc.Counterclockwise 。
当你制定了弧线的起点、终点、半径、绘制方向后,还是可能存在两条弧线都能满足给定的参数,此时 useLargeArc 属性就可以派上用场了,其默认值为 false ,取较小的弧线,设置为 true 后,取较大的弧线。下图是存在两条弧线的一种情形示例:


其它的路径元素我们就不一个一个来说了,用到时请自行研读 Qt 帮助,讲得很详细了。

PathAttribute

PathAttribute 定义一些属性,它的声明语法类似下面:
PathAttribute { name: "zOrder"; value: 0.2; }
name 属性指定待定义属性的名字, real 类型的 value 属性的值为待定义的属性的值。
PathAttribute 放在某个路径段的前面,指明这段路径起始时的属性值;路径段后面的 PathAttribute 指明路径段终止时的属性值;而在路径段上的属性值, Path 会根据起、止值自动插值计算。
我们可以通过使用 PathAttribute 来定义一些属性,用于控制分布在路径上的 item 的外观。比如定义名为 "zOrder" 的属性,控制沿路径分布的 item 的 Z 序。
下面是个简单的示例:
    Path {
            startX: 10;
            startY: 100;
            PathAttribute { name: "zOrder"; value: 0 }
            PathAttribute { name: "itemAlpha"; value: 0.1 }
            PathAttribute { name: "itemScale"; value: 0.6 }
            PathLine {
                x: root.width/2 - 40;
                y: 100;
            }
            PathAttribute { name: "zOrder"; value: 10 }
            PathAttribute { name: "itemAlpha"; value: 0.8 }
            PathAttribute { name: "itemScale"; value: 1.2 }
            PathLine {
                relativeX: root.width/2 - 60;
                relativeY: 0;
            }
            PathAttribute { name: "zOrder"; value: 0 }
            PathAttribute { name: "itemAlpha"; value: 0.1 }
            PathAttribute { name: "itemScale"; value: 0.6 }
        }

我把路径分成了两段,起点是 (10, 100) 。为路径定义了三个属性, zOrder 、 itemAlpha 、 itemScale ,在 PathView 的 delegate 中会用到这些属性。以 zOrder 属性为例,起点处值为 0 ,中间值为 1 ,终点值为 0 ,其它的, Path 会自动根据两端的值来生成。
PathAttribute 定义的属性,会导出为 delegate 的顶层 item 的附加属性,通过 PathView.${name} 的形式来访问。比如 zOrder 属性,在 delegate 中使用 PathView.zOrder 访问。

PathPercent

PathPercent 放在组成路径的元素后面,比如放在 PathLine 后面,指明它前面的那部分路径(通常由一个或多个 Path 元素组成)所放置的 item 数量占整个路径上所有 item 数量的比率。
PathPercent 的 value 属性为 real 值,范围 0.0 至 1.0 。需要注意的是,在一个 Path 中使用 PathPercent ,PathPercent 元素的 value 值是递增的,某一段路径如果在两个 PathPercent 之间,那么这段路径上面放置的 item 数量占路径上总 item 数量的比率,是后面的 PathPercent 与 前面的 PathPercent 的 value 之差。
下面是个简单的示例:
     Path {
            startX: 10;
            startY: 100;
            PathLine {
                x: root.width/2 - 40;
                y: 100;
            }
            PathPercent { value: 0.28; }
            PathLine {
                relativeX: root.width/2 - 60;
                relativeY: 0;
            }
        }

第一个路径段上放置的 item 数量占路径上总 item 数的 28% ,结合实例会看到左边矩形稀疏、右边紧凑这样的效果。

PathView

了解了 Path 、PathAttribute 及 PathPercent 等对象,咱们再来看 PathView 。
像 ListView 一样, PathView 有一个 count 属性,保存 PathView 要显示的 item 总数。另外 PathView 还有一个 pathItemCount 属性,指定在路径上可见的 item 数量,它可以与 count 不同。
preferredHighlightBegin 和 preferredHighlightEnd 属性的值是 real 类型的,范围 0.0 至 1.0 。preferredHighlightBegin 指定当前 item 在 view 中的首选起始位置, preferredHighlightEnd 指定当前 item 在 view 中的首选结束位置。与它们相关的,还有一个 highlightRangeMode 属性,可以取值 PathView.NoHighlightRange 、 PathView.ApplyRange 或 PathView.StrictlyEnforceRange 。比如我们想严格地将当前 item 限制在路径的中央,可以设置 highlightRangeMode 为 PathView.StrictlyEnforceRange ,设置 preferredHighlightBegin 和 preferredHighlightEnd 都为 0.5 。
highlight 属性指定为当前 item 绘制高亮效果的组件。
PathView 像 Flickable 一样,当用户拖动 view 时,具有弹簧效果。 interactive 属性设置为 true ,用户就可以拖动 PathView ,如果产生了弹动, flicking 会变为 true 。 flickDeceleration 属性设置弹簧效果的衰减速率,默认值为 100 。
decrementCurrentIndex() 、 incrementCurrentIndex() 两个方法可以递减、递增 PathView 维护的当前 item 的索引。这两个函数有循环效果,如果你不需要,可以自己修改 currentIndex 属性来实现你的逻辑。
PathView 还向 delegate 导出了 isCurrentItem(布尔值) 、onPath(布尔值) 、 view 三个附加属性。在 delegate 的顶层 item 内使用 PathView.isCurrentItem 可以获知本 item 是否为 PathView 的当前 item ;使用 PathView.onPath 则可以知道本 item 是否在路径上; PathView.view 则指向 item 所属的 PathView 实例,你可以通过它来访问 PathView 的方法、属性、信号等。
有关 PathView 的更多细节,请研读 Qt 帮助中有关 PathView 的文档,现在该来看一个 PathView 的实例了,下面是pathview_simple.qml :
import QtQuick 2.0
import QtQuick.Controls 1.1

Rectangle {
    width: 480;
    height: 300;
    color: "black";
    id: root;
   
    Component {
        id: rectDelegate;
        Item {
            id: wrapper;
            z: PathView.zOrder;
            opacity: PathView.itemAlpha;
            scale: PathView.itemScale;
            Rectangle {
                width: 100;
                height: 60;
                color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
                border.width: 2;
                border.color: wrapper.PathView.isCurrentItem ? "red" : "lightgray";
                Text {
                    anchors.centerIn: parent;
                    font.pixelSize: 28;
                    text: index;
                    color: Qt.lighter(parent.color, 2);
                }
            }           
        }
    }
   
    PathView {
        id: pathView;
        anchors.fill: parent;
        interactive: true;
        pathItemCount: 7;
        preferredHighlightBegin: 0.5;
        preferredHighlightEnd: 0.5;
        highlightRangeMode: PathView.StrictlyEnforceRange;

        delegate: rectDelegate;
        model: 15;

        path:Path {
            startX: 10;
            startY: 100;
            PathAttribute { name: "zOrder"; value: 0 }
            PathAttribute { name: "itemAlpha"; value: 0.1 }
            PathAttribute { name: "itemScale"; value: 0.6 }
            PathLine {
                x: root.width/2 - 40;
                y: 100;
            }
            PathAttribute { name: "zOrder"; value: 10 }
            PathAttribute { name: "itemAlpha"; value: 0.8 }
            PathAttribute { name: "itemScale"; value: 1.2 }
            PathLine {
                relativeX: root.width/2 - 60;
                relativeY: 0;
            }
            PathAttribute { name: "zOrder"; value: 0 }
            PathAttribute { name: "itemAlpha"; value: 0.1 }
            PathAttribute { name: "itemScale"; value: 0.6 }
        }

        focus: true;
        Keys.onLeftPressed: decrementCurrentIndex();
        Keys.onRightPressed: incrementCurrentIndex();
    }
}

我定义了一个很简单的 delegate :在带边框的矩形内显示 item 索引。 delegate 的顶层 item 使用了路径内通过 PathAttribute 定义的 zOrder 、itemAlpha 、 itemScale 等附加属性来控制 item 的大小、透明度。 Rectangle 对象的颜色随机生成。边框则通过 isCurrentItem 附加属性来分别设置,注意附加属性只在顶层 item ,即 wrapper 内可以直接访问,所以 Rectangle 内使用 wrapper.PathView.isCurrentItem 来访问。
model 更简单,只给了个数字。
path 对象在 PathAttribute 一节介绍过了。
focus 设置为 true ,是为了处理按键事件。左右方向键可以循环浏览 PathView 内的 item 。
我设置路径上可见的 item 数量为 7 ,当前 item 保持在路径中央。
执行 "qmlscene pathview_simple.qml" 命令,效果下图所示:


请注意观察 item 之间的遮挡效果:当前 item 在最上面,路径两端的 item 在最下面,中间的 item 递推。这是把路径分为两个路径元素并且将 PathAttribute 定义 的zOrder 属性应用在 delegate 上的效果,你可以去掉 zOrder 属性声明及相关的语句看看效果。当然你也可以修改 itemAlpha 、 itemScale 两个属性来试试。
如果你想让试试 PathPercent 的效果,可以在第一个 PathLine 后面加入代码 "PathPercent { value: 0.28; }" ,然后就可以看到下图的效果:


看上去有点儿怪怪的,大家来找茬吧。
没错,当前选中的 item 以及它的高亮框被挡住了嗳。调整下 preferredHighlightBegin 属性,设置其值为 0.3 ,再来看下图:

嗷卖糕的,好啦!
版权所有 foruok ,如需转载请注明出处:作者 foruok ,博客 http://blog.csdn.net/foruok

PathView 还有很多其它属性,使用到时请自行研究 Qt 帮助。
回顾一下本系列文章:
分享到:
评论

相关推荐

    QML之pathview

    QML之PathView示例,

    基于QML2.0的View之PathView

    继QML2.0TabView之后,打算简单说下PathView这个QML视图,最近找到先前研究的项目,但是对于PathView这个在qml2.0里面继续出现的旧东西,感觉好熟悉,看看qml2.0是否新增了一些特性或者修复了哪些bug,遂研究了下

    基于PathView,Qt/QML做的一个可以无限滚动的日历控件

    基于PathView,Qt/QML做的一个可以无限滚动的日历控件 基于PathView,Qt/QML做的一个可以无限滚动的日历控件 基于PathView,Qt/QML做的一个可以无限滚动的日历控件 基于PathView,Qt/QML做的一个可以无限滚动的...

    QML用PathView实现轮播图

    轮播图是一个常见的功能,在QML中,可以使用PathView来实现一个循环播放的轮播图组件。 默认情况,如果限制了加载个数,...import QtQuick 2.12 import QtQuick.Controls 2.12 //轮播图 Item { id: control propert

    android PathView

    android PathView,效果很好看,也很实用

    Android-android-pathview.zip

    Android-android-pathview.zip,android视图,既有来自构造路径的路径,也有来自svg的路径。,安卓系统是谷歌在2008年设计和制造的。操作系统主要写在爪哇,C和C 的核心组件。它是在linux内核之上构建的,具有安全性...

    已经交叉编译好的arm64版本的qt5.12.1以及qtmqtt的完整产物

    Building on: linux-g++ (x86_64, CPU features: mmx sse sse2) Building for: linux-aarch64-gnu-g++ (arm64, CPU features: neon) Target compiler: gcc 6.3.1 ...Qt Quick: Direct3D 12 .....................

    QML实现酷炫的 Cover Flow 图片轮播效果(PathView)

    通过 QML 的PathView来实现酷炫的 Cover Flow 图片轮播效果,http://blog.csdn.net/luoyayun361/article/details/77659386

    PathView.zip

    PathView.zip,前段时间打开新版BiliBili发现有个弹幕聊天室的功能,里面会定时播放一段线条动画,科技感十足,于是就有了这个库。。。

    CoverFlowDemo.zip

    如果大家了解过QML和Qt Quick,那么一定会想到这个需要使用PathView来实现。没错,这个效果是使用PathView实现的,而且如果学习过《Qt 5编程入门》,那么实现这个功能应该不难,但是难点在于动画的处理以及那个倒影...

    qmlpathview:基于QML PathView实现的一些效果

    qmlpathview基于QML PathView实现的一些效果====================================== 这是QML实现的一个pathview示例,它是完全跨平台的,运行在Linux、OS X和Windows上。 它还可以在 iOS、Android、Wphone、Ubutun ...

    QtProjects:Qt控件,项目合集

    :sun: Qt控件,项目合集 Qt写的控件,项目合集,包含: Qt仿手机通讯录:Qt-Qml-联系方式 Qt结合画图绘图:Qt-Qml-Echarts Qt无限滚动日历控件:Qt-...基于PathView,Qt / QML做的一个可以无限滚动的日历控件,效果:

    qml时间滚筒控件-使用PathView来实现

    qml时间滚筒控件,使用PathView来实现

    PathView.git_java_might9fv_android_

    Android手写源码效果PathView.git

    SVGPathView

    * PathView is an View that animate paths. */ public class PathView extends View { /** * Logging tag. */ public static final String LOG_TAG = "PathView"; /** * The paint for the path. */ ...

    QML path view 示例

    QML pathview 简单示例 自己学习成果 与大家分享

    Android快速SDK(11)圆弧菜单库PathView【傻瓜模式】

    Android快速SDK(11)圆弧菜单库PathView【傻瓜模式】

    安卓动画效果相关-android-pathview路径动画库.rar

    android-pathview路径动画库.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。

Global site tag (gtag.js) - Google Analytics