Qt World Summit: Register Today!

Repaint Canvas during PropertyAnimation

  • Hello.
    I have this small problem trying to repaint a canvas that uses a property (angle) to draw a pie. I would like to animate the pie going around, like so...

    Below is my code. So what I did was to create a property called 'curAngle' (a real) that the Canvas uses to draw the above pie. I then created a PropertyAnimation to animate the light-blue part of the pie to grow. As you can see, it's not great. I animate the curAngle to increment by one, use the onStopped event to repaint the Canvas, then restart the animation again.
    I use another property 'filling' that is set to true/false in onPressed and onReleased mouse events respectively.
    I know this isn't best practice. Could anyone suggest a better and more elegant way to do this? A down-side in the way I've done it is that I can't really set how quickly I want the increment to happen.

    Thank you!

    Here's the code.

    import QtQuick 2.9
    import QtQuick.Window 2.2
    Window {
        id: mainWindow
        visible: true
        width: 640
        height: 480
        title: qsTr("Pie animation")
        Rectangle {
            id: panelRect
            property bool filling: false
            width: parent.width * 0.5
            height: width
            anchors.centerIn: parent
            function convert(a) {return a*(Math.PI/180);}
            MouseArea {
                anchors.fill: panelRect
                onPressed: {
                    panelRect.filling = true;
                    fillAnimation.running = true;
                onReleased: {
                    panelRect.filling = false;
            Canvas {
                id: theCanvas
                anchors.fill: panelRect
                rotation: -90
                property real curAngle: 0
                property color inactiveColor: '#25969E'
                property color activeColor: '#33EFFF'
                onPaint: {
                    var ctx = getContext('2d');
                    var centreX = panelRect.width / 2;
                    var centreY = panelRect.height / 2;
                    ctx.fillStyle = activeColor;
                    ctx.moveTo(centreX, centreY);
                    ctx.arc(centreX, centreY, panelRect.width / 2, 0, panelRect.convert(curAngle), false);
                    ctx.lineTo(centreX, centreY);
                    ctx.fillStyle = inactiveColor;
                    ctx.moveTo(centreX, centreY);
                    ctx.arc(centreX, centreY, panelRect.width / 2, panelRect.convert(curAngle), Math.PI * 2, false);
                    ctx.lineTo(centreX, centreY);
        PropertyAnimation {
            id: fillAnimation
            target: theCanvas
            properties: 'curAngle'
            to: theCanvas.curAngle + 1
            duration: 10
            onStopped: {
                if( panelRect.filling ) {
                    if( theCanvas.curAngle === 360 ) {
                        theCanvas.curAngle = 0;
                    fillAnimation.running = true;

  • I feel so silly...

    property real curAngle: 0
    // the part I was missing...
    onCurAngleChanged: theCanvas.requestPaint()
    PropertyAnimation {
        id: animatePie
        target: theCanvas.curAngle
        from: 0
        to: 180
        duration: 1000

    Wish someone could have pointed this out to me before.
    I guess there's lots of QtQuick I still need to learn.

Log in to reply