[Interest] "Pausing" a QML state transition?

Elvis Stansvik elvstone at gmail.com
Tue Jun 14 14:09:25 CEST 2016


Hi all,

I have a relatively complex QML item which is used to visualize and
control a rotating sample holder with 4 sample slots. I model this as
four visual states ("one", "two", "three" and "four"), and I've
defined a Transition with a RotationAnimation which is used for all
transition, in order to animate the rotation of the sample holder
(mimicking the rotation of the physical holder).

The problem is as follows: The hardware may report that the rotation
is blocked by something. At that point I want to "pause" the rotation
animation that was triggered by the transition, to mimick the hardware
state (caught in between two slot positions).

Since the QML for the actual item is quite complex, I'm instead
attaching a smaller example below which illustrates what I want to do.
The example shows a Rectangle (representing my sample holder) with 4
states "one", "two", "three" and "four", in which the rotation of the
rectangle is 0, 45, 90, 180 and 270 degrees, respectively. Clicking
the rectangle transitions from one state to the next. The transition
triggers a 2 second RotationAnimation.

Using a Timer, I try to pause the RotationAnimation halfway (1 second)
between state "two" and "three", as an example. The error I get is

    file:///home/estan/test.qml:51:17: QML RotationAnimation:
setPaused() cannot be used when animation isn't running.

even if you can clearly see that the animation is running at that point.

I'm guessing this is because an animation attached to a transition is
special in some way, and may not be paused.

Any good ideas on how I can solve this? In short, what I would
actually like is twofold:

 - Don't transition into the next state until the animation has finished.
 - Find some way of "freezing" or "pausing" the transition when it is
in mid-flight so to speak (because this is what happened in real life,
the sample holder got caught on something, blocking the rotation).

Cheers,
Elvis

test.qml:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    id: window
    width: 500
    height: 500

    Rectangle {
        id: rect
        width: 200
        height: 100
        color: "gray"
        anchors.centerIn: parent

        state: "one"

        states: [
            State {
                name: "one"
                PropertyChanges {
                    target: rect
                    rotation: 0
                }
            },
            State {
                name: "two"
                PropertyChanges {
                    target: rect
                    rotation: 90
                }
            },
            State {
                name: "three"
                PropertyChanges {
                    target: rect
                    rotation: 180
                }
            },
            State {
                name: "four"
                PropertyChanges {
                    target: rect
                    rotation: 270
                }
            }
        ]

        transitions: [
            Transition {
                RotationAnimation {
                    id: rotationAnimation
                    duration: 2000
                    direction: RotationAnimation.Shortest
                }
            }
        ]

        Text {
            text: "State: " + rect.state + " (click to transition)"
            anchors.centerIn: parent
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                if (rect.state === "one")
                    rect.state = "two";
                else if (rect.state === "two") {
                    rect.state = "three";

                    // How can I "pause" the transition animation that has
                    // just begun? Ideally I'd like to remain in state "two"
                    // but have the transition animation "freezed" where it
                    // was.
                    pauseTimer.start();
                } else if (rect.state === "three")
                    rect.state = "four";
                else if (rect.state === "four")
                    rect.state = "one";
            }
        }

        Timer {
            id: pauseTimer
            interval: 1000
            repeat: false
            onTriggered: rotationAnimation.pause()
        }
    }
}



More information about the Interest mailing list