如何使 QML 动画仅在属性值增加而不是减少时才起作用?

Posted

技术标签:

【中文标题】如何使 QML 动画仅在属性值增加而不是减少时才起作用?【英文标题】:How to make a QML animation work only when a property value is increasing not decreasing? 【发布时间】:2021-06-08 17:52:01 【问题描述】:

从Qt官方文档here我了解到我可以为QML项目的x坐标的变化设置动画。

以下工作,但问题是我希望在 x 的值递减时不激活动画:

Rectangle 
    id: some_item
    x: somePropertyValueThatKeepsChanging

    Behavior on x 
        NumberAnimation 
            duration: 50
        
    

问题: 如何使动画Behavior on x 仅在x 增加时执行,而不是在减少时执行?

我使用的是Qt商业版5.15.1

【问题讨论】:

可能启用的属性:Behavior on x enabled: x > 0 NumberAnimation duration: 50 【参考方案1】:

这可以通过使用行为的targetValue(5.12 中添加)和targetProperty(5.15 中添加)来实现:

Behavior on x 
    enabled: targetValue > targetProperty.object[targetProperty.name]
    NumberAnimation  duration: 200 

(请注意,您可以只使用targetValue > some_item.x 而不是使用targetProperty,但targetProperty 允许您定义通用的可重用行为)

小例子:

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
        
    

【讨论】:

【参考方案2】:

这是可能的,但我不认为这是 QML 行为/动画的内置功能,因此需要一些自定义实现。

而不是将x直接绑定到变化的值,使用中间监听器来确定新值是大于还是小于当前x值,并在Behavior之前设置enabled标志设置x。这是一个完整的工作示例:

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
            
        
    

如果 x 将被设置为比以前更大的值,它将启用动画,否则将其禁用。

关于替代实现的其他说明:如果您不想为此中间侦听器使用新的property real,则可以将Connections 对象直接绑定到somePropertyThatChanges。我没有包括这个,因为我相信他们在我的 Qt 版本(5.12)和你的之间改变了这些语法,但对我来说它看起来像:

        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
            
        

【讨论】:

以上是关于如何使 QML 动画仅在属性值增加而不是减少时才起作用?的主要内容,如果未能解决你的问题,请参考以下文章

阻止在输入类型号中输入负值的角度方式(在复制粘贴和增加、减少时)

jQuery悬停仅在悬停一定时间时才起作用

如何在属性更改 QML 上实现行为动画

JFreeChart:当时间轴减少时如何缩放 Y 轴?

InputBindings只在聚焦时才起作用

如何在 3D 中对 QML 旋转变换进行动画处理和属性插值