在QML Book中,这部分内容在第五章 Fluid Elements(动态元素)。
1.了解State(状态)许多用户界面设计是状态驱动的 ; 接口的配置根据当前状态而有所不同。例如,交通信号灯根据状态点亮和熄灭,在禁止通行状态下,红色指示灯亮起,而黄色和绿色指示灯将熄灭。
在QML中,状态是在State类型中定义的一组属性配置。可以根据场景有不同的配置,如:
- 显示一些UI组件并隐藏其他
- 向用户呈现不同的可用操作
- 开始,停止或暂停动画
- 在新状态下执行一些脚本
- 更改特定Item的属性值
- 显示其他视图或屏幕
所有基于Item的对象都有一个state属性,并且可以通过将新State对象添加到Item的state属性来指定其他状态。组件内的每个状态通过唯一的name标识,默认为空字符串。可以通过给Item设置新的的state名称来更改状态,将state属性设置为空字符串将加载默认状态。另一种切换状态的方法是使用状态元素的when属性。该when属性可以被赋以一个表达式,当结果为true时状态被使用。 非Item对象可以通过StateGroup类型使用状态。
State类型不限于修改属性值,它还可以:
- 使用StateChangeScript运行一些脚本
- 使用PropertyChanges覆盖对象的现有信号处理程序
- 使用ParentChange修改父Item
- 使用AnchorChanges修改anchor值
下面通过代码来展示State的应用。代码实现了一个简单的红绿灯,当计时时间到了就切换状态。
Column{
id: light_column
spacing: 10
//绿灯
Rectangle{
id: green_light
width: 100; height: 100; radius:50
}
//红灯
Rectangle{
id: red_light
width: 100; height: 100; radius:50
}
Text {
id: number
color: "black"
font.pixelSize: 20
text: Number(count).toString()
readonly property int count_init: 5 //默认5s切换一次状态
property int count: count_init
Timer{
interval: 1000 //1 s跳一次
repeat: true
running: true
onTriggered: {
if(number.count>1){
number.count-=1;
}else{
number.count=number.count_init;
light_column.state=(light_column.state == "stop"? "go" : "stop");
}
}
}
}
state: "stop"
states: [
State {
name: "go"
PropertyChanges { target: red_light; color: "black" }
PropertyChanges { target: green_light; color: "green" }
},
State {
name: "stop"
PropertyChanges { target: red_light; color: "red" }
PropertyChanges { target: green_light; color: "black" }
}
]
}
3.Transition(过渡)
当可视Item从一种状态转换为另一种状态时,该项目的外观将发生变化。过渡是两种状态之间的 "edge"(原文: A transition is an "edge" between two states.)。Qt Quick提供的Transition类型具有属性,这些属性定义了当应用程序从一种状态更改为另一种状态时将发生的情况。要将过渡赋值给对象,需要将其绑定到Item的transitions属性。一系列过渡可以添加到每个Item,通过状态更改执行Transition。
下面修改下State的例子,给他加上带动画的Transition(过渡动画),让灯缓慢的亮和灭。(截图费事,我盗用QML Book里的图,就是加了个渐变的效果)
import QtQuick 2.12
Column{
id: light_column
spacing: 10
//绿灯
Rectangle{
id: green_light
width: 100; height: 100; radius:50
}
//红灯
Rectangle{
id: red_light
width: 100; height: 100; radius:50
}
Text {
id: number
color: "black"
font.pixelSize: 20
text: Number(count).toString()
readonly property int count_init: 5 //默认5s切换一次状态
property int count: count_init
Timer{
interval: 1000 //1 s跳一次
repeat: true
running: true
onTriggered: {
if(number.count>1){
number.count-=1;
}else{
number.count=number.count_init;
light_column.state=(light_column.state == "stop"? "go" : "stop");
}
}
}
}
state: "stop"
states: [
State {
name: "go"
PropertyChanges { target: red_light; color: "black" }
PropertyChanges { target: green_light; color: "green" }
},
State {
name: "stop"
PropertyChanges { target: red_light; color: "red" }
PropertyChanges { target: green_light; color: "black" }
}
]
transitions: [
Transition {
from: "stop"
to: "go"
ColorAnimation { targets: [green_light,red_light]; duration: 1000 }
},
Transition {
from: "go"
to: "stop"
ColorAnimation { targets: [green_light,red_light]; duration: 1000 }
}
]
}
状态和过渡在源码中也有应用,比如我们常用的ScrollBar,Control2里的滚动条就用到了状态和过渡(路径如\Qt\qt-everywhere-src-5.12.4\qtquickcontrols2\src\imports\controls\ScrollBar.qml)
总的来说,一个状态定义了该状态下一些属性的值,而过渡则定义了关联状态改变时的一些动作,如状态过渡动画。
4.参考QML Book:http://qmlbook.github.io/ch05-fluid/fluid.html
文档:https://doc.qt.io/qt-5/qtquick-statesanimations-topic.html
文档:https://doc.qt.io/qt-5/qtquick-statesanimations-states.html
文档:https://doc.qt.io/qt-5/qtquick-statesanimations-animations.html