Reputation: 8229
From Qt official documentation here I understand that I can animate the the change x
coordinate of a QML item.
Following works but the issue is that I want the animation to be not activate when value of x
is decrementing:
Rectangle {
id: some_item
x: somePropertyValueThatKeepsChanging
Behavior on x {
NumberAnimation {
duration: 50
}
}
}
Question:
How do I make the animation Behavior on x
execute only when x
is increasing, not when it is decreasing?
I am using Qt commercial version 5.15.1.
Upvotes: 0
Views: 1054
Reputation: 7150
This is possible by using the targetValue
(added in 5.12) and the targetProperty
(added in 5.15) of Behavior:
Behavior on x {
enabled: targetValue > targetProperty.object[targetProperty.name]
NumberAnimation { duration: 200 }
}
(Note than you can just do targetValue > some_item.x
instead of using targetProperty
, but targetProperty
lets you define generic reusable Behaviors)
Small example:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
id: some_item
x: 0
y: 100
height: 100
width: 100
color: "salmon"
Behavior on x {
enabled: targetValue > targetProperty.object[targetProperty.name]
NumberAnimation { duration: 200 }
}
}
Row {
Button {
text: "increase"
onClicked: some_item.x += 10
}
Button {
text: "decrease"
onClicked: some_item.x -= 10
}
}
}
Upvotes: 2
Reputation: 1728
This is possible, but I don't think this is a built-in feature of QML behaviors/animations, so it needs a little bit of custom implementation.
Rather than bind x
directly to the changing value, use an intermediate listener to determine if the new value is greater or less than the current x
value, and set the enabled
flag on the Behavior
prior to setting x
. Here is a complete working example:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
id: root
width: 640
height: 480
visible: true
property real somePropertyThatChanges // simulated externally changing value using timer below
Timer {
interval: 500
running: true
repeat: true
onTriggered: {
somePropertyThatChanges = Math.round(Math.random()* rect.parent.height) // simulate value changes every 500ms
}
}
Rectangle {
id: rect
color: "lightgrey"
width: 50
height: 50
property real intermediateValueChecker: root.somePropertyThatChanges
onIntermediateValueCheckerChanged: {
if (root.somePropertyThatChanges > rect.x) { // check if new value is greater or less than current x, set behavior.enabled accordingly
xBehavior.enabled = true
} else {
xBehavior.enabled = false
}
rect.x = somePropertyThatChanges // set x after the animation is enabled or disabled
}
Behavior on x {
id: xBehavior
NumberAnimation {
duration: 500
}
}
}
}
If x is going to be set to a greater value than previously, it will enable the animation, otherwise disable it.
Other note on alternative implementation: If you don't want to use a new property real
for this intermediate listener, you could bind a Connections
object directly to somePropertyThatChanges
instead. I didn't include this because I believe they changed the syntax of these between my Qt version (5.12) and yours, but for me it would look like:
Connections {
target: root
onSomePropertyThatChangesChanged: { // in QT 5.15 this may need to instead be: function onSomePropertyThatChangesChanged() {
if (root.somePropertyThatChanges > rect.x) { // same logic
xBehavior.enabled = true
} else {
xBehavior.enabled = false
}
rect.x = somePropertyThatChanges
}
}
Upvotes: 1