2015-10-18 66 views
3

問題Qt的狀態機:如何將單個過渡具有多種狀態

我目前正在對使用Qt的狀態機框架應用程序相關聯,我的目標是與多個源狀態的單個過渡關聯。這樣做的基本原理是引起轉換的信號獨立於源狀態,因此不是多次轉換(每個源狀態一次),我認爲最好有一個轉換。我在通過Qt實現上述問題時遇到了問題。下面用測試狀態機展示詳細信息。 (下面提到的是一個假設的狀態機,但我可以給出一些這樣的用例的真實世界的例子)。請爲實現上述目標提出一些有效的方法。

代碼片斷問題所在

m_s1.addTransition(&m_Trans); // Adding transition to state S1 
m_s2.addTransition(&m_Trans); // Adding the same transition to state S2 
           // As per Qt docs, it seems the ownership of thr transition will be transferred to s2 which is what is causing the problem. 

enter image description here

CState.hpp

​​

CTestMachine.hpp

class CTestStateMachine: public QObject 
{ 
    Q_OBJECT 

public: 
    CTestStateMachine(); 
    ~CTestStateMachine() {}; 

private: 
    QSignalTransition  m_Trans; 
    CState     m_s1; 
    CState     m_s2; 
    CState     m_s3; 
    QStateMachine   m_TestMachine; 
    QTimer     m_Timer; 

signals: 
    void SourceIndependentSignal(); 

public slots: 
    void TimetoInvokeTrans(); 


}; 

CTestMachine.cpp

#include <stdio.h> 
#include <iostream> 
#include <string> 
using namespace std; 

#include <QObject> 
#include <QCoreApplication> 
#include <QStateMachine> 
#include <QState> 
#include <QSignalTransition> 
#include <QTimer> 

#include "CState.hpp" 
#include "CTestStateMachine.hpp" 

void CTestStateMachine::TimetoInvokeTrans() 
{ 
    printf("Emitting source independent signal\n"); 
    emit SourceIndependentSignal(); 
} 

CTestStateMachine::CTestStateMachine(): 
    m_Trans(this, SIGNAL(SourceIndependentSignal())), 
    m_s1("s1"), 
    m_s2("s2"), 
    m_s3("s3") 
{ 
    /* Setup state machine */ 
    m_Trans.setTargetState(&m_s3); 
    m_s1.addTransition(&m_Trans); 
    m_s2.addTransition(&m_Trans); 
    m_TestMachine.addState(&m_s1); 
    m_TestMachine.addState(&m_s2); 
    m_TestMachine.addState(&m_s3); 
    m_TestMachine.setInitialState(&m_s1); 
    m_TestMachine.start(); 
    printf("Started state machine\n"); 

    /* Trigger timer to make transitions */ 
    connect(&m_Timer, SIGNAL(timeout()), this, SLOT(TimetoInvokeTrans())); 
    m_Timer.start(1000); 
} 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    CTestStateMachine TestMachine; 
    return a.exec(); 
} 
+0

爲什麼不使用addTransition'的'其他[重載(http://doc.qt.io/qt-5/qstate.html#addTransition-1)? – Rostislav

+0

因爲我想通過繼承'QSignalTransition'來重寫'OnTransition', –

+0

好吧,考慮到'QAbstractTransition'似乎總是隻有一個源狀態,我會說你必須找到一個不同的方法,比如傳遞一些共享狀態到QSignalTransition子類的幾個實例。 – Rostislav

回答

3

您可以在移動狀態進入過渡。

connect(m_state, &QState::entered, [m_state, m_tr]() -> void { m_state->addTransition(m_tr); }); 

或者只是有一個父狀態保持過渡和設置轉換類型爲內部。

QState *s = new QState(m_stateMachine); 
QState *s1 = new QState(s); 
QState *s2 = new QState(s); 
QState *s3 = new QState(s); 
QSignalTransition *sTr = new QSignalTransition(sender, SIGNAL(foobar), s); 
sTr->setTargetState(s3); 
sTr->setTransitionType(QAbstractTransition::InternalTransition);