Search code examples
qtqmlrepeatershapes

how to add PathLine to ShapePath with a Repeater?


UPDATE 1 - i can get it to work using Javascript - but that seems to be a little bit unoptimized (from 2-3% to 30% load with qmlscene.exe when activated) - complete recreation when the model changes (its not ever growing), is that the only way or is there a more "declarative" style available?

How can i add a PathLine to a ShapePath based on a Model?

  • i know how to use a Repeater from outside of Items but not how to implode them inside of Items
  • do i need some sort of Repeater-Delegate on pathElements?
  • and i don't want to use the LineSeries component

enter image description here

import QtQuick.Shapes 1.15
import QtQuick 2.15

Shape {
    ListModel {
        id: myPositions
        ListElement { x: 0; y:38 }
        ListElement { x: 10; y: 28 }
        ListElement { x: 20; y: 30 }
        ListElement { x: 30; y: 14 }
    }

    ShapePath {
        strokeColor: "black"
        strokeWidth: 1
        fillColor: "transparent"

        startX: 0
        startY: 0

        PathLine { x: 0; y: 38 }
        PathLine { x: 10; y: 28 }
        PathLine { x: 20; y: 30 }
        PathLine { x: 30; y: 14 }

//        Repeater {
//            model: myPositions
//            PathLine { x: model.x; y: model.y }
//        }
    }
}

UPDATE 1

enter image description here

import QtQuick.Shapes 1.15
import QtQuick 2.15

Shape {
    ListModel {
        id: myPositions
    }

    function getRandomInt(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    Timer
    {
        interval: 100
        running: true
        repeat: true

        property real myX: 0

        onTriggered: {
            myPositions.append({"x":myX, "y":getRandomInt(0,30)})
            myX = myX + 10
        }
    }

    function createPathLineElements(positionsModel, shapePath)
    {
        var pathElements = []

        for (var i = 0; i < positionsModel.count; i++)
        {
            var pos = myPositions.get(i)
            var pathLine = Qt.createQmlObject('import QtQuick 2.15; PathLine {}',
                                              shapePath);
            pathLine.x = pos.x
            pathLine.y = pos.y
            pathElements.push(pathLine)
        }

        return pathElements
    }

    ShapePath {
        id: myPath

        strokeColor: "black"
        strokeWidth: 1
        fillColor: "transparent"

        startX: 0
        startY: 0

        pathElements: createPathLineElements(myPositions, myPath)
    }
}

Solution

  • You can't use repeater in that element.
    The most performant way is to use QQuickItem in order to create a custom Item which draws incremental path.
    Yet another simpler ways are:

    1- Use PathSvg element and set its path runtime like below:

    ShapePath {
        fillColor: "transparent"
        strokeColor: "red"
        capStyle: ShapePath.RoundCap
        joinStyle: ShapePath.RoundJoin
        strokeWidth: 3
        strokeStyle: ShapePath.SolidLine
        
        PathSvg { id: ps; path: parent.p }    //<== fill path property using js
        property string p: ""
        
        Component.onCompleted: {
            for ( var i = 0; i < myModel.count; i++) {
                p += "L %1 %2".arg(myModel.get(i).x).arg(myModel.get(i).y);
            }
            ps.path = p;
        }
    }
    

    2- If you know steps, so you can pre-declare all PathLines and then set their values runtime. Just like a heart rate line on a health care monitor.