qtqmlbehaviorqt-quick

how to combine Behavior with sequential animation in qml


if you have 4 properties and each one has a Behavior block (that lets you animate if the corresponding property is changed ) if you change 4 properties then the animation will be parallel by default, but is it possible to make the Behavior blocks execute in sequence?

import QtQuick 
import QtQuick.Controls 


ApplicationWindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Rectangle {
        id: root
        width:196
        height:196
        color:"lightgray"

        Rectangle {
            id: box
            width:48
            height:48
            x:10
            y:10
            color: "red"
            rotation:0
            MouseArea {
                id:d
                anchors.fill: parent
                onClicked: {
                    parent.x= parent.x==10 ? root.width - parent.width -10 : 10
                    parent.y= parent.y==10 ? root.height - parent.height -10 : 10
                    parent.rotation= parent.rotation==360 ? 0 : 360
                    parent.color=parent.color=="#ff0000" ? "teal": "red"

                }
            }

            Behavior on rotation {
                id:d1
                RotationAnimation {
                    duration: 500
                }
            }

            Behavior on x {
                id:d2
                NumberAnimation {
                    duration: 500
                }
            }
            Behavior on y {
                id:d3
                NumberAnimation {
                    duration: 500
                }
            }
            Behavior on color {
                id:d4
                ColorAnimation{
                    duration:500
                        }

            }
        
    }

}
}

I tried to `onClicked:{ ... d1.start() d2.start() ...

` but it doesn't make sense for Qml


Solution

  • Following this guide (Using Qt Quick Behaviors with States) I've used State and Transition instead of Behavior. You can simply replace the SequentialAnimation with ParallelAnimation to get your old behavior back.

    This paragraph from the guide advises to use Transition and State to avoid unwanted behavior.

    Testing the example by quickly and repeatedly moving the mouse in to and out of the colored rectangle shows that the colored rectangle will settle into a green color over time, never returning to full red. This is not what we wanted! The problem occurs because we have used a Behavior to animate the change in color, and our state change is trigged by the mouse entering or exiting the MouseArea, which is easily interrupted.

    Rectangle {
        id: root
        width: 196
        height: 196
        color: "lightgray"
    
        Rectangle {
            id: box
            width: 48
            height: 48
            x: 10
            y: 10
            color: "red"
            rotation: 0
    
            property bool toggle: false
    
            MouseArea {
                id:d
                anchors.fill: parent
                onClicked: box.toggle = !box.toggle
            }
    
            states: [
                State {
                    name: "topLeft"
                    when: !box.toggle
    
                    PropertyChanges {
                        target: box
                        color: "red"
                        x: 10
                        y: 10
                        rotation: 0
                    }
                },
                State {
                    name: "bottomRight"
                    when: box.toggle
    
                    PropertyChanges {
                        target: box
                        color: "teal"
                        x: root.width - box.width - 10
                        y: root.height - box.height - 10
                        rotation: 360
                    }
                }
            ]
    
            transitions: Transition {
                SequentialAnimation {
                    ColorAnimation { duration: 500 }
                    RotationAnimation { duration: 500 }
                    NumberAnimation { properties: "x"; duration: 500 }
                    NumberAnimation { properties: "y"; duration: 500 }
                    NumberAnimation { properties: "rotation"; duration: 500 }
                }
            }
        }
    }
    

    NumberAnimation could also be combined to move the Rectangle in x and y at the same time.

    NumberAnimation { properties: "x"; duration: 500 }
    NumberAnimation { properties: "y"; duration: 500 }
    

    to

    NumberAnimation { properties: "x,y"; duration: 500 }