使用Qt Quick行为和状态

使用状态和行为

在某些情况下,您可能想使用一个行为来动画化由状态更改引起的属性更改。虽然这在某些情况下效果很好,但在其他情况下可能会导致意外的行为。

以下是一个显示问题的例子

import QtQuick 2.0

Rectangle {
    width: 400
    height: 400

    Rectangle {
        id: coloredRect
        width: 100
        height: 100
        anchors.centerIn: parent

        color: "red"
        Behavior on color {
            ColorAnimation {}
        }

        MouseArea {
            id: mouser
            anchors.fill: parent
            hoverEnabled: true
        }

        states: State {
            name: "GreenState"
            when: mouser.containsMouse

            PropertyChanges {
                target: coloredRect
                color: "green"
            }
        }
    }
}

通过快速多次将鼠标移入和移出彩色矩形来测试此示例,会发现彩色矩形会逐渐变为绿色,永远不会完全回到红色。这不是我们想要的!问题发生因为我们使用了行为来动画化颜色更改,而我们的状态更改是由鼠标进入或退出MouseArea触发的,这很容易被中断。

更正式地说,当以下情况发生时,使用状态和行为一起可能会导致意外行为:

  • 当使用行为来动画化属性更改时,特别是从显式定义的状态回到隐式的基础状态时;
  • 此行为可以被中断以(重新)进入显式定义的状态。

问题发生的原因是QML为基本状态定义的方式:作为进入显式定义的状态之前的应用程序的“快照”状态。在这种情况下,如果我们正在将绿色动画回到红色,并中断动画返回“GreenState”,则基础状态将包括在其中间、中动画形式的颜色。

虽然QML的未来版本应该能够更优雅地处理这种情况,但目前有几种方法可以重新设计您的应用程序以避免此问题。

1. 使用过渡来动画化更改,而不是行为。

import QtQuick 2.0

Rectangle {
    width: 400
    height: 400

    Rectangle {
        id: coloredRect
        width: 100
        height: 100
        anchors.centerIn: parent

        color: "red"

        MouseArea {
            id: mouser
            anchors.fill: parent
            hoverEnabled: true
        }

        states: State {
            name: "GreenState"
            when: mouser.containsMouse

            PropertyChanges {
                target: coloredRect
                color: "green"
            }
        }

        transitions: Transition {
            ColorAnimation {}
        }
    }
}

2. 使用条件绑定来更改属性值,而不是状态

import QtQuick 2.0

Rectangle {
    width: 400
    height: 400

    Rectangle {
        id: coloredRect
        width: 100
        height: 100
        anchors.centerIn: parent

        color: mouser.containsMouse ? "green" : "red"
        Behavior on color {
            ColorAnimation {}
        }

        MouseArea {
            id: mouser
            anchors.fill: parent
            hoverEnabled: true
        }
    }
}

3. 只使用显式定义的状态,而不是隐式基础状态

import QtQuick 2.0

Rectangle {
    width: 400
    height: 400

    Rectangle {
        id: coloredRect
        width: 100
        height: 100
        anchors.centerIn: parent

        Behavior on color {
            ColorAnimation {}
        }

        MouseArea {
            id: mouser
            anchors.fill: parent
            hoverEnabled: true
        }

        states: [
        State {
            name: "GreenState"
            when: mouser.containsMouse

            PropertyChanges {
                target: coloredRect
                color: "green"
            }
        },
        State {
            name: "RedState"
            when: !mouser.containsMouse

            PropertyChanges {
                target: coloredRect
                color: "red"
            }
        }]
    }
}

© 2024 Qt公司有限。在此处包含的文档贡献是各自所有者的版权。此处提供的文档是根据自由软件基金会发布的、适用于版本1.3的GNU自由文档许可证条款许可的。Qt和相应徽标是在芬兰和/或其他国家的世界各地的Qt公司的商标。所有其他商标均为其各自所有者的财产。