Qt狀態機器學習3

來源:互聯網
上載者:User

                      在使用狀態機器表述的系統中中存在一個屬性,這個屬性取值都是是互斥的,比如電源有開啟和關閉,燈有亮和滅,但是不一定只有兩個取值。我們的理想狀態機器不可能只有一個單一的屬性。

                      下面我們舉一個例子,在一個狀態機器中存在下面這幾種屬性,每個屬性都有幾個取值。

                      

                       所以就會有四種狀態,2*2 = 4;如果每個狀態都是可以互相轉換的餓,那麼就是4*2 = 8中過渡。

                       如果又添加了一種屬性

                        

                       那麼就是2*2*3=12中狀態,12*2 = 24中過渡,是指數級的增長,而且在添加和移除屬性是,會影響狀態。

                       在此Qt的QState類中有一個枚舉類型

                      

                        第二個平行的狀態集就是為瞭解決這個問題。

                        

#include <QApplication>#include <QState>#include <QStateMachine>#include <QPushButton>#include <QVariant>#include <QFinalState>#include <QLayout>#include <QHistoryState>#include <QLabel>#include <QMessageBox>#include <QtDebug>#include <QAbstractTransition>//Qt的狀態機器是層次的,是事件驅動的,使用到了事件迴圈,那麼就是非同步int main(int argc, char* argv[]){    QApplication app(argc,argv);    QStateMachine sMachine;//一個狀態機器對象    QState s;//和fState在同一個層次    QState s0;//開始狀態,空白狀態    QState s1;//3個狀態物件    s1.setChildMode(QState::ParallelStates);    s1.setParent(&s);    QState s2;    s2.setParent(&s);    QState s3;    s3.setParent(&s);    s.setInitialState(&s1);//一組狀態中要指定一組狀態中的初始狀態    QState s11;    s11.setChildMode(QState::ExclusiveStates);    s11.setParent(&s1);    QState s111;//a1    s111.setParent(&s11);    QState s112;//a2    s112.setParent(&s11);    s11.setInitialState(&s111);    QState s12;    s12.setChildMode(QState::ExclusiveStates);    s12.setParent(&s1);    QState s121;//b1    s121.setParent(&s12);    QState s122;//b2    s122.setParent(&s12);    s12.setInitialState(&s121);    QHistoryState sh;//記錄s組狀態被打斷的狀態    sh.setParent(&s);    QFinalState fState;    QState is;//中斷狀態    QWidget w;    QHBoxLayout layout;    QPushButton button(QObject::tr("狀態改變"));    QPushButton qButton;    QPushButton startButton("start");    QPushButton stopButton("stop");    qButton.setText(QObject::tr("退出"));    QPushButton iButton;    iButton.setText(QObject::tr("打斷"));    QPushButton button1("a1,b1");    QPushButton button2("a1,b2");    QPushButton button3("a2,b1");    QPushButton button4("a2,b2");    QLabel showLabel;    QLabel showLabel2;    QLabel showLabel3;    layout.addWidget(&button);    layout.addWidget(&qButton);    layout.addWidget(&iButton);    layout.addWidget(&showLabel);    layout.addWidget(&showLabel2);    layout.addWidget(&showLabel3);    layout.addWidget(&startButton);    layout.addWidget(&stopButton);    layout.addWidget(&button1);    layout.addWidget(&button2);    layout.addWidget(&button3);    layout.addWidget(&button4);    w.setLayout(&layout);    QMessageBox box(&w);    box.addButton(QMessageBox::Ok);    box.setText(QObject::tr("打斷了,現在是is"));    box.setIcon(QMessageBox::Information);    s0.addTransition(&button,SIGNAL(clicked()),&s);    s1.addTransition(&button,SIGNAL(clicked()),&s2);//s1為這個過渡的始狀態,s2為末狀態        //八個過渡,可是應為選擇的是2個屬性,所以是2+2和2*2一樣,但是這樣是線性    //比如按鈕3被點擊,s111和s122都是activity的同時響應,平行的    s111.addTransition(&button3,SIGNAL(clicked()),&s112);//a1->a2    s111.addTransition(&button4,SIGNAL(clicked()),&s112);    s112.addTransition(&button1,SIGNAL(clicked()),&s111);//a2->a1    s112.addTransition(&button2,SIGNAL(clicked()),&s111);    s121.addTransition(&button2,SIGNAL(clicked()),&s122);//b1->b2    s121.addTransition(&button4,SIGNAL(clicked()),&s122);    s122.addTransition(&button1,SIGNAL(clicked()),&s121);//b2->b1    s122.addTransition(&button3,SIGNAL(clicked()),&s121);    s2.addTransition(&button,SIGNAL(clicked()),&s3);    s3.addTransition(&button,SIGNAL(clicked()),&s1);    //每個狀態進入時,設定指定對象指定項指定的值    s1.assignProperty(&showLabel,"text","當前:s1");    s2.assignProperty(&showLabel,"text","當前:s2");    s3.assignProperty(&showLabel,"text","當前:s3");    //同時進入,而且這個是原子操作,不會被事件打斷,但是是隊列的,因為狀態機器是單線程的    s11.assignProperty(&showLabel,"text","s11");    s12.assignProperty(&showLabel2,"text","s12");    s111.assignProperty(&showLabel,"text","a1");    s112.assignProperty(&showLabel,"text","a2");    s121.assignProperty(&showLabel2,"text","b1");    s122.assignProperty(&showLabel2,"text","b2");    //給每個狀態添加過渡    s.addTransition(&qButton,SIGNAL(clicked()),&fState);//s -- > finalState,但是在這組內的狀態對於這個過渡可以覆蓋    //s2.addTransition(&qButton,SIGNAL(clicked()),&s3);//如果添加這一個句,那麼在s2點擊qButton按鈕    //就不會退出,只是轉向了s3    s.addTransition(&iButton,SIGNAL(clicked()),&is);    is.addTransition(&sh);    QObject::connect(&is,SIGNAL(entered()),&box,SLOT(exec()));    //也可能重寫 QAbstractState::onEntry()和QAbstractState::onExit()函數    //在UML的狀態圖中,每個狀態在進入狀態和離開狀態的時候都會進行相關的操作    //這個可以通過這兩個訊號來解決,也可通過繼承來重寫上述的兩個函數    QObject::connect(&s3,SIGNAL(entered()),&w,SLOT(showMinimized()));    QObject::connect(&s3,SIGNAL(exited()),&w,SLOT(showMaximized()));    QObject::connect(&sMachine,SIGNAL(finished()),&app,SLOT(quit()));    QObject::connect(&startButton,SIGNAL(clicked()),&sMachine,SLOT(start()));    QObject::connect(&stopButton,SIGNAL(clicked()),&sMachine,SLOT(stop()));    sMachine.addState(&s0);    sMachine.addState(&s);//對於狀態機器只是添加頂層的狀態    // sMachine.addState(&s1);    // sMachine.addState(&s2);    // sMachine.addState(&s3);    sMachine.addState(&fState);    sMachine.addState(&is);    //設定狀態機器的初始狀態    //sMachine.setInitialState(&s1);    sMachine.setInitialState(&s0);//對於狀態機器的初始化,只是使用頂層的狀態初始化,所以每個頂層如果是    //一組狀態,那麼就要指定這組狀態的初始化狀態    w.show();    //狀態機器開啟    //   sMachine.start();    //可以通過給狀態分組來實現狀態過渡的共用,比如我們希望在任何狀態下我們都能夠退出,    //那麼這個退出狀態就是比其他的狀態具有高的狀態層次,那麼我們就要將其他的狀態封裝在    //合適的與退出狀態同層次的一個高階的狀態層次中    return app.exec();}

                                               

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.