跳转到内容

第 7 课:状态、过渡和动画 ​

更新: 10/23/2026 字数: 0 字 时长: 0 分钟

这一课学三件事:

  1. 属性动画:让一个属性平滑变化
  2. Behavior:属性变化时自动带动画
  3. State + Transition:定义界面状态,并在状态间平滑切换

QML 动画基础 ​

1. 属性动画 ​

最简单的动画:让矩形宽度从 100 变到 300。

qml
import QtQuick
import QtQuick.Window

Window {
    width: 480
    height: 320
    visible: true
    title: "第七课"

    Rectangle {
        id: box
        width: 100
        height: 80
        color: "steelblue"
        anchors.centerIn: parent

        MouseArea {
            anchors.fill: parent
            onClicked: widthAnimation.start()
        }

        NumberAnimation {
            id: widthAnimation
            target: box
            property: "width"
            to: 300
            duration: 500
            easing.type: Easing.InOutQuad
        }
    }
}

点击矩形,宽度会在 500ms 内平滑变成 300。

关键属性:

  • target:动画作用在哪个对象上
  • property:动画改哪个属性
  • to:目标值
  • duration:持续时间,单位毫秒
  • easing.type:缓动曲线

2. Behavior:属性一变就自动动画 ​

每次点击都手动 start() 很麻烦。用 Behavior:

qml
Rectangle {
    id: box
    width: 100
    height: 80
    color: "steelblue"
    anchors.centerIn: parent

    Behavior on width {
        NumberAnimation { duration: 300 }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: box.width = box.width === 100 ? 300 : 100
    }
}

现在只要 width 发生变化,就自动用 300ms 动画过渡。

Behavior 的写法:

qml
Behavior on 属性名 {
    动画类型 { ... }
}

3. 颜色动画 ​

qml
ColorAnimation {
    target: box
    property: "color"
    to: "tomato"
    duration: 400
}

或者用 Behavior:

qml
Behavior on color {
    ColorAnimation { duration: 300 }
}

4. State + Transition ​

State 用来描述界面的一组属性值。
Transition 用来描述状态切换时怎么动画过渡。

示例:一个方块,点击后在“左边”和“右边”两个状态间切换。

qml
import QtQuick
import QtQuick.Window

Window {
    width: 480
    height: 320
    visible: true
    title: "状态与过渡"

    Rectangle {
        id: box
        width: 120
        height: 80
        color: "steelblue"
        y: 120
        x: 30

        states: [
            State {
                name: "left"
                PropertyChanges { target: box; x: 30; color: "steelblue" }
            },
            State {
                name: "right"
                PropertyChanges { target: box; x: 330; color: "tomato" }
            }
        ]

        transitions: [
            Transition {
                NumberAnimation { properties: "x"; duration: 400; easing.type: Easing.InOutQuad }
                ColorAnimation { duration: 400 }
            }
        ]

        MouseArea {
            anchors.fill: parent
            onClicked: box.state = box.state === "right" ? "left" : "right"
        }
    }
}

点击方块,它会在左右两边平滑移动,同时颜色渐变。

关键点:

  • states 定义若干状态,每个状态用 PropertyChanges 改属性
  • transitions 定义状态切换时的动画
  • Transition 里不写 target/property 时,会自动对所有变化的属性生效
  • 通过 box.state = "right" 切换状态

5. 常用动画类型 ​

  • NumberAnimation:数值属性
  • ColorAnimation:颜色
  • PropertyAnimation:通用属性动画
  • SequentialAnimation:顺序播放多个动画
  • ParallelAnimation:同时播放多个动画
  • RotationAnimation:旋转

例子:顺序动画

qml
SequentialAnimation {
    NumberAnimation { target: box; property: "width"; to: 200; duration: 300 }
    NumberAnimation { target: box; property: "height"; to: 120; duration: 300 }
}

你的动手练习 ​

练习 1 ​

用 Behavior on opacity 让一个矩形的透明度变化带动画:

qml
Rectangle {
    id: fadeBox
    width: 120; height: 120
    color: "orange"
    opacity: 1

    Behavior on opacity {
        NumberAnimation { duration: 400 }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: fadeBox.opacity = fadeBox.opacity === 1 ? 0.2 : 1
    }
}

练习 2 ​

用 RotationAnimation 让矩形每次点击旋转 90 度。

提示:给矩形加 rotation 属性,点击时 rotation += 90,并用 Behavior on rotation。

练习 3 ​

用 State 做一个“按钮悬停变色”的效果:

  • 默认状态:蓝色
  • 鼠标进入 MouseArea 时进入 hover 状态,变成橙色
  • 鼠标离开回到默认状态

提示:MouseArea 有 onEntered 和 onExited,状态里用 PropertyChanges 改 color。

练习 4(思考题) ​

如果给一个属性写了 Behavior,同时又用 PropertyChanges 在状态里改这个属性,动画会生效吗?为什么?