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 年。由法国project师皮埃尔·贝塞尔( 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 {
     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 {
     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 {
         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 {
     480;
    height: 300;
    color: "black";
    id: root;
   
    Component {
        id: rectDelegate;
        Item {
            id: wrapper;
            z: PathView.zOrder;
            opacity: PathView.itemAlpha;
            scale: PathView.itemScale;
            Rectangle {
                 100;
                height: 60;
                color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
                border. 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(); } }


    我定义了一个非常easy的 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 帮助。

    回想一下本系列文章:
原文地址:https://www.cnblogs.com/gccbuaa/p/6946291.html