停止行为 - QML

时间:2013-05-27 15:52:57

标签: animation qml behavior

我编写了一个“游戏”,其中一个球被发送到墙上反弹。 在伤害墙壁之前,y上的行为是一个春天动画。当它伤到墙壁时,球应该反弹并且有一个线性运动。

我的问题是我无法阻止初始行为。 我试过几种方法: - 禁用行为,但正在进行的运动继续 - 停止SpringAnimation:我有错误:“QML SpringAnimation:setRunning()不能在非根动画节点上使用。”

这是代码

    Rectangle {
    id: ball
    property bool enableMoving: false

    function newMousePos(mX,mY){
        if(enableMoving){
            ball.x = mX - ball.width/2
            ball.y = mY - ball.height/2
        }
    }

    Behavior on x {enabled: true;id: behavX; SpringAnimation {id:spX;  spring: 0.8; damping: 0.9; mass: 10; } }
    Behavior on y {enabled: true;id: behavY; SpringAnimation {id:spY;  spring: 0.8; damping: 0.9; mass: 10 ; } }


    onXChanged: {
        if(ball.x>main.width-ball.size) {
            console.log("wall 2 ")
            spX.stop(); spY.stop()
        }
        if(ball.x<0)  {
         ...
        }
       }
    onYChanged: {
       ...
       }
  Timer{
        id:timerDisableMoving
        interval: 500; running:true
        onTriggered: enableMoving=false
    } }

我不明白为什么我无法阻止这种行为。是否有可能在状态上定义行为以解决问题?

感谢您的帮助

2 个答案:

答案 0 :(得分:0)

当球击中墙壁时,将此代码置于信号上:

behavX.enabled = false

这将禁用行为(我已在我的项目中测试过它)。

如果您只想禁用特定动画,请按以下方式执行:

spX.running = false  //ignore this, it is equivalent to spX.stop()

我只是认为你可能会推出这样的代码:

function disableBehavior()
{
  behavX.enabled = false
  //...
  behavX.enabled = true
}

如果是这种情况,那么它将无法正常工作因为在执行期间动画不会发生。 相反,你应该进行异步调用,例如:

function disableBehavior()
{
  behavX.enabled = false
  //...
  myTimer.start()
}

//...
Timer
{
  id: myTimer
  interval: 1
  running: false
  onTriggered:
  {
    behavX.enabled = true
    stop()
  }
}

但是,我认为你需要在“线性行为”完成后调用“行为启动器”(而不是创建新的计时器)。

答案 1 :(得分:0)

我认为,我也有类似的问题。我有一些行为,可以改变某些属性。而且我希望能够在中间尚未完成的情况下将其停止。

它没有用。顺便说一句,QML还在控制台中抱怨我试图在非root动画上使用某种方法。

简短答案: 行为似乎不支持将其停止在中间。

但是,可以通过为属性设置新值来中断它。这将重新启动动画以定位新值。当我意识到这一点时,就实现了这样的“停止”功能:

function stopAnimation() {
    // disable animation for the next value change
    moveBehavior.enabled = false 

    // Change value of the property of interest.
    // This stops currently running animation
    y += 1

    // Restore initial value of the property
    y -= 1

    // Enable animation for subsequent property changes
    moveBehavior.enabled = true
}

因此,我禁用了该行为以使属性更改立即生效。然后,将目标属性更改为非常接近当前值的值(我相信我不能使用相同的值,因为这样一来,将不会发出“ onChange”信号)。此时,应停止运行动画。然后,我将属性重置为其原始值。然后再次启用动画以处理进一步的属性更改。

看起来不太好,但是它对我的行为有帮助...

经过更多思考后,我得出结论,我可能不应该使用行为。然后,我刚刚创建了PropertyAnimation {},将它直接关联到需要移动的对象中我感兴趣的属性。然后,我只是动态分配目标值和持续时间,现在“ start()”和“ stop()”可以按预期工作。

完整的解决方案如下所示(它可以做什么,您可能会发现):

Item {
    id: root
    focus: true

    Rectangle {
        id: racket
        height: 40
        width: 10
        x: 20
        y: 20
        color: "blue"

        property int maxY: 460
        // ...

        PropertyAnimation {
            id: moveDownAnimation
            target: racket
            property: "y"
            to: racket.maxY
            // if you want constant velocity, you need
            // to calculate duration dynamically based
            // on desired velocity and distance
            duration: 1000 
        }

        function moveUp () { // just return racket to the initial position
            y = 50
        }

        function moveDown() {
            moveDownAnimation.start()
        }

        function stopAnimation() {
            moveDownAnimation.stop()
        }

    }

    Keys.onPressed: {
        if (event.isAutoRepeat) {
            return
        }
        if (event.key === Qt.Key_Q) {
            racket.moveUp() // return to initial position
        } else if (event.key === Qt.Key_A) {
            racket.moveDown()
        }
    }

    Keys.onReleased: {
        if (event.isAutoRepeat) {
            return
        }
        if (event.key === Qt.Key_A) {
            racket.stopAnimation()
        }
    }
}