詳解Qt中的狀態機機制(一)
狀態機,簡寫為FSM(Finite State Machine),狀態機由狀態暫存器和組合邏輯電路構成,能夠根據控制訊號按照預先設定的狀態進行狀態轉移,是協調相關訊號動作、完成特定操作的控制中心。
在GUI開發的時候,介面複雜的邏輯往往令人抓狂,邏輯都不清晰,程式碼寫起來更加費勁。使用者介面設計中採用狀態驅動,就可以使得GUI的邏輯更加清晰。根據當前狀態的不同,顯示不同的介面。程式介面可以被看作顯示對應不同場景,或者是通過改變外觀響應使用者的互動。通常情況下,介面中很多個元件的改變是併發進行的,這樣的介面可以看作從一個狀態改變到另外一個狀態。
今天我們來看看qt中的狀態機框架,qt把它作為QtCore中的一個模組,也足見其重要性:
在進入今天的主題之前,我們先來了解三個概念:
狀態
過渡(Transition):是一段時間或者空間的描述,狀態之間切換的整個過程,或者描述的是不同屬性值之間變化的一個過程。
動畫(Animation):是動態的一個東西,可以看作是過渡的執行者,通過在屬性值上應用動畫型別來建立。動畫型別會對屬性值進行插值,從而創建出平滑的過渡效果。要建立動畫,需要為某個屬性使用恰當的動畫型別;應用的動畫也依賴於需要實現的行為型別。
這三者之間的聯絡較為密切,只定義了狀態,它是一個死(靜態)的東西,所以就需要過渡,來讓它活起來。但是過渡這個過程是如何實現,就需要動畫來執行,從而讓過的的平滑,給使用者良好的視覺效果。
在Qt中,這三者之間的關係有沒有那麼明確,但是明確這三個概念,對於我們理解qt中的狀態機制會有很大的幫助。
一、狀態
對於初學者來說,我建議從qml中去學習瞭解狀態機的概念會更快。它描述性的語言,會讓人很快的去接受這些概念和使用。在你瞭解了qml中狀態機的使用後,再來了解qt中的狀態機就會發現很簡單。今天我們就先從qml中瞭解一些狀態機的魅力。
在qml中,繼承自Item的控制元件都會有一個states屬性,該屬性有使用者自定義的屬性組組成。可以通過PropertyChanges、ParentChange、StateChangeScript、 AnchorChanges這些控制元件對這個狀態中的屬性做定義和描述。下面是一個簡單的程式碼示例:
import QtQuick 2.0
Rectangle {
id: root
width: 100; height: 100
states: [
State {
name: "red_color"
PropertyChanges { target: root; color: "red" }
},
State {
name: "blue_color"
PropertyChanges { target: root; color: "blue" }
}
]
}
二、漸變
在狀態改變的過程中,我們可以指定一個過渡,可以採用Transition 、Behavior這兩個控制元件,可以在這個過渡中指定各種動畫,從而達到想要的互動效果。
import QtQuick 2.0
Rectangle {
id: rect
width: 100; height: 100
color: "red"
MouseArea {
id: mouseArea
anchors.fill: parent
}
states: State {
name: "moved"; when: mouseArea.pressed
PropertyChanges { target: rect; x: 50; y: 50 }
}
transitions: Transition {
NumberAnimation { properties: "x,y"; easing.type: Easing.InOutQuad }
}
}
這個小示例藉助Item的transitions屬性,qt幫助文件上的描述,This property holds the list of transitions for this item. These define the transitions to be applied to the item whenever it changes its state.,只有在狀態屬性發生改變,才會觸發這個漸變,再運用NumberAnimation,完成這個漸變。
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"
}
}
}
}
這串程式碼也實現了狀態的漸變,區別在於Behavior這個控制元件不僅可以用於狀態的改變,在沒有使用狀態,只要安裝Behavoir監控的屬性發生了改變,就會運用相應的動畫平滑的完成這個漸變,使用起來相當方便。
以上的兩部分講的就是狀態和漸變,藉助qml這種描述性語言,我們也可很方便的完成GUI的開發,很容易做出漂亮的效果。在上面的例項中,大家發現也有很多動畫,所以說,狀態、漸變、動畫三者關係是很密切的,下面,我們來看看動畫。
三、動畫
上面的圖是qtquick中的所有用到的動畫的一個關係圖,他們都繼承自Animation這個最基礎的控制元件,這個控制元件提供了動畫的控制,開始,暫停,重播,播放次數。此外它還提供了兩個訊號,started() 和 stopped(),以供其他控制元件去捕捉該訊號去響應其他的槽函式。在平時開發中運用較多的是 PropertyAnimation這個控制元件。Qt系統中強大的元物件系統,使得對屬性的操作很方便,所以這個PropertyAnimation就可以對這些屬性做動畫。而且它還帶Easing Curve緩和曲線,qt中提供了四十多種緩和曲線,讓開發者更方便的定義動畫的效果。此外還有ParallelAnimation 、 SequentialAnimation 這兩個控制元件,一個是平行動畫組,一個是序列動畫組,這兩個又可以相互的巢狀,使用非常的方便。在使用的時候,可能又會遇到想要在兩個動畫之間加一段空白暫停的時間,這時候 PauseAnimation 就可以達到你想要的效果。
總結:今天主要講解的是qt QML中的狀態機制,這個對於剛接觸qt的新手會比較好上手,瞭解了這些概念和控制元件的使用,我們基本上就可以完成一些基本的互動介面的開發。
後續 詳解Qt中的狀態機機制(二)中會講解qt C++中的狀態機制以及和QML中的狀態機制的比較。