最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt中狀態(tài)機(jī)框架QState的實(shí)現(xiàn)

 更新時(shí)間:2025年11月11日 10:52:49   作者:MzKyle  
這篇文章主要介紹了Qt中狀態(tài)機(jī)框架QState的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

QState是Qt狀態(tài)機(jī)框架(Qt State Machine Framework)的核心類,用于建模離散狀態(tài)以及狀態(tài)間的轉(zhuǎn)換邏輯,廣泛應(yīng)用于UI交互流程、設(shè)備狀態(tài)管理、工作流控制等場(chǎng)景。它基于UML狀態(tài)圖規(guī)范設(shè)計(jì),支持層次化狀態(tài)、并行狀態(tài)、歷史狀態(tài)等高級(jí)特性,能夠簡(jiǎn)化復(fù)雜狀態(tài)邏輯的實(shí)現(xiàn)。

一、核心定位與繼承關(guān)系

QState繼承自QAbstractState(抽象狀態(tài)基類),而QAbstractState又繼承自QObject,因此QState具備Qt對(duì)象模型的所有特性(如信號(hào)槽、元對(duì)象系統(tǒng)、父子關(guān)系管理)。其核心作用是:

  • 封裝一個(gè)離散狀態(tài)的l行為(進(jìn)入/退出時(shí)的動(dòng)作);
  • 管理狀態(tài)間的轉(zhuǎn)換規(guī)則(QAbstractTransition);
  • 支持子狀態(tài)嵌套,構(gòu)建層次化狀態(tài)機(jī);
  • QStateMachine配合,實(shí)現(xiàn)狀態(tài)的自動(dòng)切換。

狀態(tài)機(jī)的基本構(gòu)成包括:

  • 狀態(tài)(State):如QState、QParallelState(并行狀態(tài))、QHistoryState(歷史狀態(tài));
  • 轉(zhuǎn)換(Transition):如QSignalTransition(信號(hào)觸發(fā))、QEventTransition(事件觸發(fā));
  • 事件(Event):觸發(fā)狀態(tài)轉(zhuǎn)換的信號(hào)、Qt事件或自定義事件;
  • 狀態(tài)機(jī)(State Machine)QStateMachine,負(fù)責(zé)調(diào)度狀態(tài)切換與事件處理。

二、基礎(chǔ)用法:狀態(tài)創(chuàng)建與轉(zhuǎn)換

1. 狀態(tài)的創(chuàng)建與添加

通過QStateMachine管理狀態(tài),需先創(chuàng)建狀態(tài)實(shí)例并添加到狀態(tài)機(jī)中:

#include <QStateMachine>
#include <QState>
#include <QPushButton>

QStateMachine *machine = new QStateMachine;

// 創(chuàng)建狀態(tài)
QState *s1 = new QState(machine);  // 直接指定父對(duì)象為狀態(tài)機(jī)
QState *s2 = new QState;
machine->addState(s2);  // 或通過addState()添加

// 設(shè)置初始狀態(tài)(狀態(tài)機(jī)啟動(dòng)時(shí)進(jìn)入的第一個(gè)狀態(tài))
machine->setInitialState(s1);

2. 狀態(tài)轉(zhuǎn)換的定義

狀態(tài)轉(zhuǎn)換(QAbstractTransition)是狀態(tài)切換的規(guī)則,需指定“觸發(fā)條件”和“目標(biāo)狀態(tài)”。QState通過addTransition()方法添加轉(zhuǎn)換,常用轉(zhuǎn)換類型包括:

(1)信號(hào)觸發(fā)轉(zhuǎn)換(QSignalTransition)

最常用的轉(zhuǎn)換類型,當(dāng)特定信號(hào)發(fā)射時(shí)觸發(fā)狀態(tài)切換:

QPushButton *btn = new QPushButton("Next");

// 當(dāng)btn發(fā)射clicked()信號(hào)時(shí),從s1轉(zhuǎn)換到s2
s1->addTransition(btn, &QPushButton::clicked, s2);

// 進(jìn)階:轉(zhuǎn)換可攜帶動(dòng)作(通過onTransition()信號(hào))
QSignalTransition *trans = s1->addTransition(btn, &QPushButton::clicked, s2);
connect(trans, &QSignalTransition::onTransition, [](){
    qDebug() << "從s1切換到s2";  // 轉(zhuǎn)換過程中執(zhí)行的動(dòng)作
});

(2)事件觸發(fā)轉(zhuǎn)換(QEventTransition)

基于Qt事件(如QKeyEvent、QMouseEvent)觸發(fā)轉(zhuǎn)換:

#include <QEventTransition>

// 當(dāng)s1收到QEvent::KeyPress事件時(shí),轉(zhuǎn)換到s2
QEventTransition *keyTrans = new QEventTransition(btn, QEvent::KeyPress);
keyTrans->setTargetState(s2);
s1->addTransition(keyTrans);

(3)守衛(wèi)條件(Guard)

轉(zhuǎn)換可設(shè)置守衛(wèi)條件(布爾函數(shù)),僅當(dāng)條件為true時(shí)才執(zhí)行轉(zhuǎn)換:

// 定義守衛(wèi)函數(shù)(返回bool)
bool canTransition() {
    return someCondition;  // 例如:檢查輸入是否合法
}

// 為轉(zhuǎn)換設(shè)置守衛(wèi)
trans->setGuard(canTransition);  // 僅當(dāng)canTransition()為true時(shí),轉(zhuǎn)換才生效

三、狀態(tài)行為:進(jìn)入與退出動(dòng)作

QState在進(jìn)入(entered)和退出(exited)時(shí)會(huì)發(fā)射對(duì)應(yīng)信號(hào),可通過信號(hào)槽機(jī)制綁定狀態(tài)切換時(shí)的動(dòng)作。此外,還可通過onEntry()onExit()方法直接設(shè)置動(dòng)作函數(shù)。

1. 信號(hào)綁定方式

// 進(jìn)入s1時(shí)執(zhí)行動(dòng)作
connect(s1, &QState::entered, [](){
    qDebug() << "進(jìn)入狀態(tài)s1";
    // 例如:更新UI顯示、啟動(dòng)定時(shí)器
});

// 退出s1時(shí)執(zhí)行動(dòng)作
connect(s1, &QState::exited, [](){
    qDebug() << "退出狀態(tài)s1";
    // 例如:停止定時(shí)器、保存臨時(shí)數(shù)據(jù)
});

2. 動(dòng)作函數(shù)方式

通過assignProperty()可在進(jìn)入狀態(tài)時(shí)自動(dòng)為對(duì)象設(shè)置屬性,簡(jiǎn)化UI狀態(tài)管理:

QPushButton *btn = new QPushButton("Click me");

// 進(jìn)入s1時(shí),將btn的text屬性設(shè)為"狀態(tài)1",enabled設(shè)為true
s1->assignProperty(btn, "text", "狀態(tài)1");
s1->assignProperty(btn, "enabled", true);

// 進(jìn)入s2時(shí),更新btn屬性
s2->assignProperty(btn, "text", "狀態(tài)2");
s2->assignProperty(btn, "enabled", false);

當(dāng)狀態(tài)激活時(shí),assignProperty()設(shè)置的屬性會(huì)自動(dòng)應(yīng)用到目標(biāo)對(duì)象,退出狀態(tài)時(shí)不會(huì)自動(dòng)恢復(fù)(需手動(dòng)在exited信號(hào)中處理)。

四、層次化狀態(tài):父狀態(tài)與子狀態(tài)

QState支持嵌套子狀態(tài),形成層次化結(jié)構(gòu)(父狀態(tài)包含子狀態(tài)),這是實(shí)現(xiàn)復(fù)雜狀態(tài)邏輯的核心特性。

1. 子狀態(tài)的添加與初始子狀態(tài)

// 創(chuàng)建父狀態(tài)
QState *parentState = new QState;

// 創(chuàng)建子狀態(tài)(指定父狀態(tài))
QState *child1 = new QState(parentState);
QState *child2 = new QState(parentState);

// 設(shè)置父狀態(tài)的初始子狀態(tài)(進(jìn)入父狀態(tài)時(shí)自動(dòng)進(jìn)入該子狀態(tài))
parentState->setInitialState(child1);

2. 層次化狀態(tài)的行為規(guī)則

  • 進(jìn)入父狀態(tài):先執(zhí)行父狀態(tài)的entered動(dòng)作,再進(jìn)入其初始子狀態(tài)(執(zhí)行子狀態(tài)的entered動(dòng)作);
  • 退出父狀態(tài):先退出當(dāng)前活躍的子狀態(tài)(執(zhí)行子狀態(tài)的exited動(dòng)作),再執(zhí)行父狀態(tài)的exited動(dòng)作;
  • 子狀態(tài)轉(zhuǎn)換限制:子狀態(tài)的轉(zhuǎn)換默認(rèn)只能在同一父狀態(tài)的子狀態(tài)間進(jìn)行,若需轉(zhuǎn)換到外部狀態(tài),需顯式指定目標(biāo)。

示例:播放器的“播放中”狀態(tài)(父狀態(tài))包含“正常播放”和“快進(jìn)”子狀態(tài):

QState *playing = new QState;  // 父狀態(tài):播放中
QState *normalPlay = new QState(playing);  // 子狀態(tài):正常播放
QState *fastForward = new QState(playing); // 子狀態(tài):快進(jìn)

playing->setInitialState(normalPlay);

// 子狀態(tài)間轉(zhuǎn)換:正常播放 → 快進(jìn)(按快進(jìn)鍵)
normalPlay->addTransition(fastForwardBtn, &QPushButton::clicked, fastForward);
// 子狀態(tài)轉(zhuǎn)換到外部狀態(tài):任何子狀態(tài)下按停止鍵 → 停止?fàn)顟B(tài)
playing->addTransition(stopBtn, &QPushButton::clicked, stopped);

五、特殊狀態(tài)類型

1. 并行狀態(tài)(QParallelState)

用于建模同時(shí)活躍的多個(gè)狀態(tài)(如設(shè)備同時(shí)處于“聯(lián)網(wǎng)”和“充電”狀態(tài))。QParallelStateQState的子類,其所有子狀態(tài)會(huì)同時(shí)進(jìn)入和退出。

#include <QParallelState>

QParallelState *parallel = new QParallelState;

// 兩個(gè)并行子狀態(tài)
QState *networkState = new QState(parallel);  // 網(wǎng)絡(luò)狀態(tài)
QState *powerState = new QState(parallel);    // 電源狀態(tài)

// 進(jìn)入parallel時(shí),networkState和powerState同時(shí)激活
machine->setInitialState(parallel);

并行狀態(tài)的退出規(guī)則:所有子狀態(tài)退出后,并行狀態(tài)才會(huì)退出。

2. 歷史狀態(tài)(QHistoryState)

用于保存父狀態(tài)中最后活躍的子狀態(tài),當(dāng)父狀態(tài)再次進(jìn)入時(shí),自動(dòng)恢復(fù)到該子狀態(tài)(避免重復(fù)初始化)。分為兩種類型:

  • 淺歷史(默認(rèn)):僅恢復(fù)直接子狀態(tài)的歷史;
  • 深歷史:遞歸恢復(fù)所有嵌套子狀態(tài)的歷史(通過setDeepHistory(true)啟用)。
#include <QHistoryState>

QState *parent = new QState;
QState *child1 = new QState(parent);
QState *child2 = new QState(parent);
parent->setInitialState(child1);

// 創(chuàng)建歷史狀態(tài)(作為parent的子狀態(tài))
QHistoryState *history = new QHistoryState(parent);
// 啟用深歷史(可選)
history->setDeepHistory(true);

// 從外部狀態(tài)轉(zhuǎn)換到history時(shí),恢復(fù)parent的最后活躍子狀態(tài)
externalState->addTransition(backBtn, &QPushButton::clicked, history);

六、狀態(tài)機(jī)的運(yùn)行與生命周期

1. 狀態(tài)機(jī)的啟動(dòng)與停止

// 啟動(dòng)狀態(tài)機(jī)(開始處理事件并進(jìn)入初始狀態(tài))
machine->start();

// 停止?fàn)顟B(tài)機(jī)(退出當(dāng)前狀態(tài),暫停事件處理)
machine->stop();

狀態(tài)機(jī)啟動(dòng)后,會(huì)觸發(fā)初始狀態(tài)的entered信號(hào),并開始監(jiān)聽事件以驅(qū)動(dòng)轉(zhuǎn)換。

2. 狀態(tài)機(jī)的完成與終止

當(dāng)狀態(tài)機(jī)進(jìn)入“終止?fàn)顟B(tài)”(QFinalState)時(shí),會(huì)發(fā)射finished()信號(hào)并停止運(yùn)行:

#include <QFinalState>

QFinalState *final = new QFinalState(machine);

// 從s2轉(zhuǎn)換到終止?fàn)顟B(tài)
s2->addTransition(quitBtn, &QPushButton::clicked, final);

// 狀態(tài)機(jī)完成時(shí)退出程序
connect(machine, &QStateMachine::finished, qApp, &QApplication::quit);

七、高級(jí)特性與底層機(jī)制

1. 事件優(yōu)先級(jí)與處理順序

狀態(tài)機(jī)的事件處理遵循以下規(guī)則:

  • 子狀態(tài)的事件處理器優(yōu)先于父狀態(tài);
  • 同一狀態(tài)的多個(gè)轉(zhuǎn)換按添加順序檢查(守衛(wèi)條件先滿足者觸發(fā));
  • 并行狀態(tài)的子狀態(tài)獨(dú)立處理事件,互不干擾。

2. 自定義轉(zhuǎn)換與事件

通過繼承QAbstractTransition可實(shí)現(xiàn)自定義轉(zhuǎn)換邏輯,通過QEvent子類可定義自定義事件:

// 自定義事件
class MyEvent : public QEvent {
public:
    static const QEvent::Type Type = static_cast<QEvent::Type>(QEvent::User + 1);
    MyEvent() : QEvent(Type) {}
};

// 自定義轉(zhuǎn)換(監(jiān)聽MyEvent)
class MyTransition : public QAbstractTransition {
protected:
    bool eventTest(QEvent *e) override {
        return e->type() == MyEvent::Type;  // 僅響應(yīng)MyEvent
    }
    void onTransition(QEvent *) override {
        // 轉(zhuǎn)換動(dòng)作
    }
};

// 使用自定義轉(zhuǎn)換
MyTransition *trans = new MyTransition;
trans->setTargetState(s2);
s1->addTransition(trans);

3. 調(diào)試與狀態(tài)監(jiān)控

Qt提供QStateMachine::setDebuggingEnabled(true)開啟調(diào)試日志,輸出狀態(tài)轉(zhuǎn)換過程:

machine->setDebuggingEnabled(true);  // 控制臺(tái)會(huì)打印狀態(tài)切換日志

也可通過QState::active()方法實(shí)時(shí)檢查狀態(tài)是否活躍:

if (s1->active()) {
    qDebug() << "當(dāng)前處于s1狀態(tài)";
}

八、常見問題

  1. 狀態(tài)轉(zhuǎn)換循環(huán):避免無守衛(wèi)條件的循環(huán)轉(zhuǎn)換(如s1→s2→s1),可能導(dǎo)致狀態(tài)機(jī)無限切換;
  2. 子狀態(tài)與父狀態(tài)的信號(hào)沖突:子狀態(tài)的entered信號(hào)會(huì)在父狀態(tài)之后觸發(fā),需注意動(dòng)作執(zhí)行順序;
  3. 并行狀態(tài)的同步:并行子狀態(tài)的轉(zhuǎn)換獨(dú)立,若需同步退出,可統(tǒng)一轉(zhuǎn)換到同一個(gè)終止?fàn)顟B(tài);
  4. 歷史狀態(tài)的濫用:僅在需要恢復(fù)狀態(tài)時(shí)使用,過度使用會(huì)增加狀態(tài)機(jī)復(fù)雜度;
  5. 性能考量:復(fù)雜狀態(tài)機(jī)(>100個(gè)狀態(tài))需避免頻繁轉(zhuǎn)換,可通過合并狀態(tài)減少開銷。

QState作為Qt狀態(tài)機(jī)框架的核心,通過封裝狀態(tài)行為、轉(zhuǎn)換規(guī)則和層次化結(jié)構(gòu),大幅簡(jiǎn)化了復(fù)雜狀態(tài)邏輯的實(shí)現(xiàn)。其特性包括:支持信號(hào)/事件觸發(fā)的轉(zhuǎn)換、狀態(tài)進(jìn)入/退出動(dòng)作、屬性自動(dòng)賦值、層次化與并行狀態(tài)、歷史狀態(tài)恢復(fù)等。

到此這篇關(guān)于Qt中狀態(tài)機(jī)框架QState的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Qt 狀態(tài)機(jī)框架QState內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言實(shí)現(xiàn)三子棋游戲附注釋

    C語(yǔ)言實(shí)現(xiàn)三子棋游戲附注釋

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)三子棋游戲附注釋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C++的幾種編譯器的實(shí)現(xiàn)

    C++的幾種編譯器的實(shí)現(xiàn)

    本文主要介紹了C++的幾種編譯器的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • 使用VScode搭建ROS開發(fā)環(huán)境的教程詳解

    使用VScode搭建ROS開發(fā)環(huán)境的教程詳解

    這篇文章主要介紹了使用VScode搭建ROS開發(fā)環(huán)境,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • matlab遺傳算法求解車間調(diào)度問題分析及實(shí)現(xiàn)源碼

    matlab遺傳算法求解車間調(diào)度問題分析及實(shí)現(xiàn)源碼

    這篇文章主要為大家介紹了matlab遺傳算法求解車間調(diào)度問題解析,文中附含詳細(xì)實(shí)現(xiàn)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-02-02
  • OpenGL通過中點(diǎn)法繪制直線和圓

    OpenGL通過中點(diǎn)法繪制直線和圓

    這篇文章主要為大家詳細(xì)介紹了OpenGL通過中點(diǎn)法繪制直線和圓,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • C++實(shí)現(xiàn)學(xué)生宿舍管理系統(tǒng)

    C++實(shí)現(xiàn)學(xué)生宿舍管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)學(xué)生宿舍管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語(yǔ)言中g(shù)etchar()與putchar()函數(shù)詳解

    C語(yǔ)言中g(shù)etchar()與putchar()函數(shù)詳解

    本文主要介紹了C語(yǔ)言中g(shù)etchar()與putchar()函數(shù)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • C語(yǔ)言例題講解指針與數(shù)組

    C語(yǔ)言例題講解指針與數(shù)組

    在C語(yǔ)言和C++等語(yǔ)言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲(chǔ)類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來指向若干個(gè)字符串,使字符串處理更加方便、靈活
    2022-07-07
  • C++實(shí)現(xiàn)旋轉(zhuǎn)數(shù)組的二分查找

    C++實(shí)現(xiàn)旋轉(zhuǎn)數(shù)組的二分查找

    這篇文章主要介紹了C++實(shí)現(xiàn)旋轉(zhuǎn)數(shù)組的二分查找方法,涉及數(shù)組的操作,有值得借鑒的技巧,需要的朋友可以參考下
    2014-09-09
  • c++11 新特性——智能指針使用詳解

    c++11 新特性——智能指針使用詳解

    這篇文章主要介紹了c++11 新特性——智能指針使用的相關(guān)資料,幫助大家更好的理解和使用c++,感興趣的朋友可以了解下
    2021-02-02

最新評(píng)論

沾益县| 德惠市| 安溪县| 永川市| 广州市| 绥芬河市| 项城市| 虎林市| 深水埗区| 福泉市| 洪湖市| 和硕县| 永丰县| 武清区| 平阳县| 湖南省| 余庆县| 深水埗区| 洪泽县| 高密市| 山阳县| 闽清县| 堆龙德庆县| 桦南县| 永安市| 宜春市| 平原县| 登封市| 晋江市| 凤台县| 永定县| 泉州市| 武义县| 冀州市| 馆陶县| 临夏市| 宽甸| 珲春市| 灵宝市| 天长市| 绥棱县|