【问题标题】:How to switch to another state at the end of a transition in QML?如何在 QML 转换结束时切换到另一个状态?
【发布时间】:2014-04-07 02:43:22
【问题描述】:

我正在尝试实现一个健身应用程序,该应用程序显示当前锻炼名称,然后在休息期间显示一个进度条。当进度条填满时,显示下一个练习的名称,完成后显示进度条,以此类推。

请注意,我在此示例中使用了进度条,但在实际应用程序中我将拥有自己的小部件。

我的系统有两种状态:

  • exercise进度条的值为0并保持为0
  • rest在休息期间,进度条的值从 0 变为 maximumValue

原来是这样的:

  1. 应用程序处于“练习”状态并显示当前练习的名称
  2. 用户执行练习并在完成后单击进度条
  3. 应用程序切换到“休息”状态
  4. 用户在进度条完成时休息
  5. 进度条完成后,应用程序切换回“练习”状态并显示下一个练习的名称

我的问题在于第 5 步:我不知道如何在转换结束时切换回另一个状态。我尝试在 PropertyChanges 期间更改“状态”属性,并在使用 SequentialAnimation 的转换结束时对其进行计时,但我收到以下错误消息:

QML StateGroup:无法将状态更改应用为状态定义的一部分。

这里是一些示例代码:

import QtQuick 2.0
import QtQuick.Controls 1.1

ProgressBar {
    id: root

    width: 200
    height: 48

    minimumValue: 0
    maximumValue: 100
    value: 76

    function switchState() {
        if (state == "exercise")
        {
            state = "rest"
            return
        }

        if (state == "rest")
        {
            state = "exercise"
            return
        }
    }

    state: "exercise"

    states: [
        State {
            name: "exercise"
            PropertyChanges {
                target: root
                value: 0
            }
        },
        State {
            name: "rest"
            PropertyChanges {
                target: root
                value: maximumValue

                // error: QML StateGroup: Can't apply a state change as part of a state definition.
                // state: "exercise"
            }
        }
    ]

    transitions: [
        Transition {
            to: "rest"
            PropertyAnimation {
                target: root
                properties: "value"
                duration: 1000
            }
        }
    ]

    MouseArea {
        anchors.fill: parent
        onClicked: parent.switchState()
    }
}

如何在状态转换结束时切换到另一个状态?

【问题讨论】:

  • 一种选择是在最后触发一个计时器并从计时器滴答声中改变状态。

标签: qt qml


【解决方案1】:

我相信您可以通过使用转换中的 RunningChanged 信号来做到这一点:

transitions: [
    Transition {
        to: "rest"
        PropertyAnimation {
            target: root
            properties: "value"
            duration: 1000
        }

        onRunningChanged: {
            if ((state == "rest") && (!running))
                switchState();
        }
    }
]

QML 对象具有属性更改的关联信号 (on<Property>Changed)。关联的处理程序通常不会记录在对象的引用中,但由于属性的存在而隐式可用。见this

【讨论】:

    【解决方案2】:

    更新
    我提出了一个错误的解决方案,因为一个错误,请见谅。
    解决其问题的结果与@GabrielF 相同。所以我删除了它以避免重复。

    但是下面的解决方案效果很好,可以让您在过渡/动画中进行精细控制。

    还有另一种方式!

    transitions: [
        Transition {
            to: "rest"
            SequentialAnimation {
                PropertyAnimation {
                    target: root
                    properties: "value"
                    duration: 1000
                }
                ScriptAction { script: switchState() }    //<----
            }
        }
    ]    
    

    请注意,在过渡动画中使用SequentialAnimation,您无需定义中间状态,只要确保完成特定动画即可。

    祝你好运 - S.M.Mousavi

    【讨论】:

    • 根据docs on the stopped signal,“它只会为顶级的独立动画触发。它不会为行为或过渡中的动画或动画组中的动画触发。”所以我认为你的第一个和第二个例子行不通。
    • 我真的很喜欢你上一个例子中的方法,我现在在我的应用程序中使用它并且效果很好。
    • 我更喜欢使用 SequentialAnimation{... ScriptAction{ script: ...} } 的这个解决方案,但第二个 PropertyAnimation 具有误导性,并且与 OP 的问题无关,所以我不能投票(目前)。注意:switchState() 周围的花括号不是必需的。
    • 在转换过程中状态发生变化会发生什么?顺序动画会运行到结束并执行脚本动作吗?在文档中找不到它
    • @JohannesSchaub-litb 过渡行为是这样的:如果您在过渡期间更改状态,它将停止(暂停)该过渡并从当前值开始合适的过渡。
    猜你喜欢
    • 2019-12-28
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多