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 {
    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(); } }


    我定義了一個非常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 幫助。

    回想一下本系列文章:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM