Qt 4.6 Animation動畫實(shí)現(xiàn)之狀態(tài)機(jī) 實(shí)例講解
Qt 4.6 Animation動畫實(shí)現(xiàn)之狀態(tài)機(jī) 實(shí)例是本文要介紹的內(nèi)容,不多說,先來看內(nèi)容。狀態(tài)機(jī)顧名思義,應(yīng)該有不同的狀態(tài)在切換。上面狀態(tài)機(jī)圖中,我們提供了兩種狀態(tài)state1和state2。而狀態(tài)的區(qū)分是由狀態(tài)的屬性來描述的,與之相關(guān)的文章:剖析 Qt 實(shí)現(xiàn)動畫狀態(tài)機(jī)實(shí)例 ,應(yīng)該對你很有幫助。
比如 p1,p2…等等。從一個(gè)狀態(tài)到另一個(gè)狀態(tài)的轉(zhuǎn)化,必須由觸發(fā)條件來完成,上圖state1到state2的狀態(tài)轉(zhuǎn)換由transition1來表示,state2
到state1的狀態(tài)轉(zhuǎn)換由transition2來表示。如果希望在狀態(tài)轉(zhuǎn)換過程中有動畫來展示,那么可以在transition1和 transition2中加入動畫效
果animation1和animation2 。最后,狀態(tài)機(jī)進(jìn)入需要有一個(gè)初始狀態(tài),我們可以設(shè)定state1為我們這個(gè)狀態(tài)機(jī)的初始態(tài)。
有了狀態(tài)機(jī)的描述圖,我們就可以看看用Qt-4.6的代碼,如何實(shí)現(xiàn)以上功能。
- #include <QtGui/QApplication>
- #include <QApplication>
- #include <QWidget>
- #include <QPushButton>
- #include <QStateMachine>
- #include <QState>
- #include <QSignalTransition>
- #include <QPropertyAnimation>int main(int argc,char *argv[]){
- QApplication app(argc,argv);
- QPushButton *button = new QPushButton("Animated Button");
- button->show(); // 創(chuàng)建狀態(tài)機(jī)
- QStateMachine *machine = new QStateMachine; // 創(chuàng)建兩個(gè)狀態(tài),狀態(tài)的屬性由QPushButton的位置大小決定。
- //QState *state1 = new QState(machine->rootState());
- QState *state1 = new QState(machine);
- state1->assignProperty(button, "geometry", QRect(480, 480, 150, 30));
- //QState *state2 = new QState(machine->rootState());
- QState *state2 = new QState(machine);
- state2->assignProperty(button, "geometry", QRect(250, 250, 150, 30)); // 將狀態(tài)1設(shè)置為狀態(tài)機(jī)的初始狀態(tài)
- machine->setInitialState(state1); // 增加觸發(fā)狀態(tài)1到狀態(tài)2的觸發(fā)條件,QPushButton按鈕被按下,動畫效果由addAnimation()完成
- /*
- 細(xì)心的讀者可能發(fā)現(xiàn)QPropertyAnimation的setStartValue()和setEndValue()都沒有被調(diào)用到。
- 其實(shí)這里動畫變化的初始態(tài)和結(jié)束態(tài),
- 由state1和state2決定的。另外,如果沒有設(shè)置動畫的持續(xù)時(shí)長,則默認(rèn)是250毫秒。
- */
- QSignalTransition *transition1 = state1->addTransition(button, SIGNAL(clicked()), state2);
- transition1->addAnimation(new QPropertyAnimation(button, "geometry")); // 同理,增加狀態(tài)2到狀態(tài)1的觸發(fā)條件,也是按鈕被按下
- QSignalTransition *transition2 = state2->addTransition(button, SIGNAL(clicked()), state1);
- transition2->addAnimation(new QPropertyAnimation(button, "geometry")); // 將狀態(tài)機(jī)啟動
- machine->start();
- return app.exec();
- }
QT的State Machine Framework是在Qt4.6中引入的,其理論基礎(chǔ)是Harel的Statechart,通過定義一系列的可能狀態(tài),以及系統(tǒng)如何在這些狀態(tài)中進(jìn)行轉(zhuǎn)換(Transitions between states)來描述整個(gè)狀態(tài)機(jī)的運(yùn)行。
狀態(tài)機(jī)體系結(jié)構(gòu)
QT的狀態(tài)機(jī)體系主要包括三部分模塊:
以QAbstractState為基類的QState,以及QFinalState,QHistoryState等表示狀態(tài)的類
以QAbstractTransition為基類的用來表示各類狀態(tài)轉(zhuǎn)換行為(Transition)的類(包括:事件觸發(fā)/信號觸發(fā)/鼠標(biāo)鍵盤觸發(fā)的轉(zhuǎn)換等類別)
QStateMachine狀態(tài)機(jī)類
特性基本功能
光有狀態(tài)機(jī)本身,只是定義狀態(tài)轉(zhuǎn)換,什么事情也不做的話,這樣的狀態(tài)機(jī)也就沒有什么用
QState類可以和一個(gè)控件屬性綁定,在進(jìn)入這個(gè)狀態(tài)時(shí),設(shè)定該屬性值
也可以通過連接QState的entered和exited信號,執(zhí)行指定的槽函數(shù)。
狀態(tài)機(jī)的退出
你可以定義一個(gè)永不結(jié)束的狀態(tài)機(jī),也可以通過QFinalState給狀態(tài)機(jī)添加一個(gè)“結(jié)束狀態(tài)”,當(dāng)狀態(tài)機(jī)轉(zhuǎn)換到這個(gè)狀態(tài)以后,整個(gè)狀態(tài)機(jī)就會結(jié)束并退出運(yùn)行。
狀態(tài)嵌套
狀態(tài)本身可以嵌套,一個(gè)大的狀態(tài)內(nèi)部可以細(xì)分子狀態(tài),通過狀態(tài)嵌套機(jī)制和并行狀態(tài)機(jī)制,可以實(shí)現(xiàn)
狀態(tài)轉(zhuǎn)換的歸組(比如可以用一個(gè)Transtion將一組的狀態(tài)都轉(zhuǎn)向另一個(gè)狀態(tài),用來實(shí)現(xiàn),比如退出鍵),多個(gè)狀態(tài)轉(zhuǎn)換參數(shù)的并行監(jiān)控,以避免創(chuàng)建過多的獨(dú)立狀態(tài)(因?yàn)槿绻總€(gè)參數(shù)都是獨(dú)立互斥的,那么狀態(tài)的數(shù)目量級為O(N^2))
狀態(tài)的轉(zhuǎn)換,不受嵌套機(jī)制的影響,也就是說你可以定義從任意層級的狀態(tài)轉(zhuǎn)換到其它狀態(tài)。
動畫屬性值
狀態(tài)轉(zhuǎn)換可以配合Animation相關(guān)類,實(shí)現(xiàn)對象屬性值的動畫效果。針對一些邊際場合,State相關(guān)類還提供的函數(shù)用于判定屬性值是否已經(jīng)完成賦值(如果在動畫過程中,屬性值是在變化的,不算賦值完畢),以及動畫完成前,狀態(tài)提前退出時(shí)的屬性參數(shù)設(shè)置設(shè)定機(jī)制等。
歷史狀態(tài)
QHistoryState類,并不像我所想象的那樣,是用來跟蹤和記錄歷史狀態(tài)的記錄堆棧。到底是什么用途,看看如何使用它就知道了。
QHistoryState必須被添加為一個(gè)父狀態(tài)組的成員狀態(tài)。當(dāng)父狀態(tài)組退出(轉(zhuǎn)換到狀態(tài)組外部的其它狀態(tài))時(shí),會自動把當(dāng)前的狀態(tài)記錄到QHistoryState中,外部狀態(tài)轉(zhuǎn)換回來時(shí),不需要知道原先的狀態(tài)是該狀態(tài)組中具體的哪一個(gè),只需要轉(zhuǎn)向狀態(tài)組中的歷史狀態(tài)成因就可以了。
所以,歷史狀態(tài)的使用,應(yīng)該更多的是為了記錄一個(gè)被打斷的狀態(tài),比如跳到一個(gè)外部狀態(tài)處理一些事情,然后再返回到被打斷的狀態(tài)。
無目標(biāo)狀態(tài)轉(zhuǎn)換
所謂無目標(biāo)狀態(tài)轉(zhuǎn)換(Targetless Transitions),是指當(dāng)一個(gè)狀態(tài)轉(zhuǎn)換動作被觸發(fā)時(shí),并不轉(zhuǎn)向另一個(gè)狀態(tài),只是觸發(fā)一個(gè)QAbstractTramsotopm::triggered信號。你可以鏈接這個(gè)信號來做一些處理。
需要注意的是:Targetless Transitions是通過初始化一個(gè)Transition類時(shí),不指定目標(biāo)狀態(tài)來實(shí)現(xiàn)的,如果明確指定的目標(biāo)狀態(tài)為源狀態(tài)(比如S1->S1),那么該狀態(tài)會先退出,再進(jìn)入,從而依次觸發(fā)QAbstractState::entered和QAbstractState::exited 信號
小結(jié):關(guān)于詳解 Qt 4.6 Animation動畫實(shí)現(xiàn)之狀態(tài)機(jī) 實(shí)例的內(nèi)容介紹完了,希望本文對你有所幫助。