Change state after transition animation finishes
I want to change the state after the transition animation has finished. I have the following code that achieves this, although it looks hackish:
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
Rectangle {
id: root
width: 400
height: 400
Rectangle {
id: rect
color: "blue"
width: 50
height: 50
anchors.centerIn: parent
MouseArea {
anchors.fill: parent
onClicked: rect.state = "animating"
}
states: [
State {
name: "animating"
PropertyChanges {
target: rect
rotation: 360
}
},
State {
name: "shrinking"
PropertyChanges {
target: rect
scale: 0
}
}
]
transitions: [
Transition {
from: ""
to: "animating"
SequentialAnimation {
RotationAnimation {
duration: 500
}
ScriptAction {
script: rect.state = "shrinking"
}
}
},
Transition {
from: "animating"
to: "shrinking"
NumberAnimation {
property: "scale"
duration: 500
}
}
]
}
}
Is there a better way to do this without using ScriptAction
? Note that I need the second state, and I don't want to just consolidate the scale animation into the SequentialAnimation
transition animating
.
source to share
The correct way is to change the state in the runningChanged
transition handler when it transitions to false, which completes the animation. for this you have two solutions:
Sol 1.use connections
(you will get a warning about some notifiable property, ignore it)
Connections{
target:rect.transitions[0]
onRunningChanged:{
if( rect.transitions[0].running === false)
{
rect.state = "shrinking"
}
}
}
the code will be:
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
Rectangle {
id: root
width: 400
height: 400
Rectangle {
id: rect
color: "blue"
width: 50
height: 50
anchors.centerIn: parent
MouseArea {
anchors.fill: parent
onClicked: rect.state = "animating"
}
states: [
State {
name: "animating"
PropertyChanges {
target: rect
rotation: 360
}
},
State {
name: "shrinking"
PropertyChanges {
target: rect
scale: 0
}
}
]
Connections{
target:rect.transitions[0]
onRunningChanged:{
if( rect.transitions[0].running === false)
{
rect.state = "shrinking"
}
}
}
transitions: [
Transition {
from: ""
to: "animating"
RotationAnimation {
duration: 500
}
},
Transition {
from: "animating"
to: "shrinking"
NumberAnimation {
property: "scale"
duration: 500
}
}
]
}
}
solution 2: change state in handler runningChanged
directly on transition:
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
Rectangle {
id: root
width: 400
height: 400
Rectangle {
id: rect
color: "blue"
width: 50
height: 50
anchors.centerIn: parent
MouseArea {
anchors.fill: parent
onClicked: rect.state = "animating"
}
states: [
State {
name: "animating"
PropertyChanges {
target: rect
rotation: 360
}
},
State {
name: "shrinking"
PropertyChanges {
target: rect
scale: 0
}
}
]
transitions: [
Transition {
from: ""
to: "animating"
RotationAnimation {
duration: 500
}
onRunningChanged:{
if( running === false)
{
rect.state = "shrinking"
}
}
},
Transition {
from: "animating"
to: "shrinking"
NumberAnimation {
property: "scale"
duration: 500
}
}
]
}
}
I prefer the first solution ( connections
) because it is more general
source to share
A slightly different approach is to set state shrinking
to state animating
and use it PropertyAction
to force a state change at the end of the transition:
State {
name: "animating"
PropertyChanges {
target: rect
rotation: 360
}
PropertyChanges {
target: rect
state: "shrinking"
}
and
Transition {
SequentialAnimation {
RotationAnimation {
duration: 500
}
PropertyAction {
target: rect
property: "state"
}
}
}
Note that I agree with jturcotte on his assessment of the use of these states here.
source to share