Qt Quick应用开发介绍 10-12(动态界面, 实践学习, 总结和扩展)
Chapter10 UI Dynamics and Dynamic UI 动态界面
前面章节学习了在开发时添加item, 让它们invisible; 该怎么做可以让程序根据不同的数据和用户输入来有不同的显示? 这些变化可能比visibility复杂; 我们怎样才能做到让程序UI的动态变化更appealing吸引人, 甚至成为用户体验的一部分?
10.1 Using States 使用state
网络连接对于现在的版本中天气相关的部件是必须的; 它让网络数据可视化; 如果你的电脑不在线, 启动clock-n-weather应用的话, 只会看到时钟和空的内容;
这是因为WeatherModelItem没能拿到天气数据; 所以没有model项可以显示; 如果你在笔记本或移动设备上使用这个程序, 这种情况会经常发生; 你的程序需要处理没有网络的情况; 我们可以使用State来处理;
QtQuick里的每个item都有一个state属性, 保存了当前state的名字; 也有一个states属性, 是一个States的list; 这个属性包含了那个item所有已知的states; 列表中每个States有个string名字, 定义了一组property值; 需要的话, 它甚至可以包含script代码, 当那个state变化的时候被执行; item可以被设成一个state, 只要把选中的state的名称分配给state属性; refer to QML States
对于我们的程序, 会添加三种state:
- Offline, 开始阶段的初始化状态; 也应用到没有网络连接或程序处于离线状态;
- Loading, 网络连接可用, 但是WeatherModelItem还在加载天气数据; 这个state在网络连接很慢的时候有用; (e.g. 非宽带的移动设备)
- Live Weather, 更新的天气数据可用而且能够显示;
在Offline和Loading状态, 程序只会显示clock, 以一个较大的尺寸显示在屏幕中间; 当Live Weather状态激活, 程序就会显示天气数据;
由于我们的新states和WeatherModelItem的状态紧密相关, 必须把它们直接绑定; WeatherModelItem没有定义任何真实的state; 我们根据current或forecast模型的status, hijack抓取它的states属性来存储Offline, Loading, Live Weather值;
components/WeatherModelItem.qml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
XmlListModel
{
id:
current
source:
root.source
query: "/xml_api_reply/weather/current_conditions"
XmlRole
{ name: "condition" ;
query: "condition/@data/string()" }
XmlRole
{ name: "temp_c" ;
query: "temp_c/@data/string()" }
onStatusChanged:
{
root.modelDataError
= false
if (status
== XmlListModel.Error) {
root.state
= "Offline"
root.statusMessage
= "Error
occurred: " +
errorString()
root.modelDataError
= true
//console.log("Weather
Clock: Error reading current: " + root.statusMessage)
} else if (status
== XmlListModel.Ready) {
//
check if the loaded model is not empty, and post a message
if (get(0)
=== undefined) {
root.state
= "Offline"
root.statusMessage
= "Invalid
location "" +
root.location + """
root.modelDataError
= true
} else {
root.state
= "Live
Weather"
root.statusMessage
= "Live
current weather is available"
}
//console.log("Weather
Clock: " + root.statusMessage)
} else if (status
== XmlListModel.Loading) {
root.state
= "Loading"
root.statusMessage
= "Current
weather is loading..."
//console.log("Weather
Clock: " + root.statusMessage)
} else if (status
== XmlListModel.Null) {
root.state
= "Loading"
root.statusMessage
= "Current
weather is empty..."
//console.log("Weather
Clock: " + root.statusMessage)
}
|