2015-10-18 125 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);