Допустим, у меня есть стая роботов, которые запускают QStateMachine
, Все конечные автоматы этих роботов имеют одинаковую базовую структуру:
from
-> to
на signal
:
// base.h
#include <QObject>
#include <QState>
#include <QStateMachine>
class Base : public QObject
{
Q_OBJECT
public:
Base(QObject* parent = 0);
~Base();
signals:
void next();
void back();
private:
QStateMachine m_machine;
QState* m_sleep;
QState* m_search;
QState* m_destroy;
QState* m_return;
};
// base.cpp
Base::Base(QObject* parent) : QObject(parent)
{
m_sleep = new QState(&m_machine);
m_search = new QState(&m_machine);
m_destroy = new QState(&m_machine);
m_return = new QState(&m_machine);
m_machine.setInitialState(m_sleep);
m_sleep->addTransition(this, &Base::next, m_search);
m_search->addTransition(this, &Base::next, m_destroy);
m_search->addTransition(this, &Base::back, m_return);
m_destroy->addTransition(this, &Base::next, m_search);
m_destroy->addTransition(this, &Base::back, m_return);
m_return->addTransition(this, &Base::next, m_search);
m_return->addTransition(this, &Base::back, m_sleep);
m_machine.start();
}
Теперь я хочу иметь робота, который может быть немного более конкретным. Скажем, он более детален в процессе уничтожения, показывая пару подсостояний, например, dismantel -> sprayWithAcid -> blowUp -> desintegrate
где он движется с каждым next
-сигнал, или он продолжает return
на back
-сигнал.
Как уже упоминалось, мой план состоял в том, чтобы просто добавить их в качестве подсостояний к штату destroy
, но как сигнал next
будет не только продолжать подсостояние машины до завершения, но и покинет родительское состояние.
Как я могу избежать этого? или есть другой хороший способ сделать подобное?
Я понял.
Хитрость заключается в том, чтобы явно создавать переходы, имея их в качестве членов класса. Вы можете настроить их так:
m_sleepSearch = new QSignalTransition(this, &Base::next, m_sleep);
m_searchDestroy = new QSignalTransition(this, &Base::next, m_search);
m_searchReturn = new QSignalTransition(this, &Base::back, m_search);
m_destroySearch = new QSignalTransition(this, &Base::next, m_destroy);
m_destroyReturn = new QSignalTransition(this, &Base::back, m_destroy);
m_returnSearch = new QSignalTransition(this, &Base::next, m_return);
m_returnSleep = new QSignalTransition(this, &Base::back, m_return);
m_sleepSearch->setTargetState(m_search);
m_searchDestroy->setTargetState(m_destroy);
m_searchReturn->setTargetState(m_return);
m_destroySearch->setTargetState(m_search);
m_destroyReturn->setTargetState(m_return);
m_returnSearch->setTargetState(m_search);
m_returnSleep->setTargetState(m_sleep);
То, что я сначала ошибся, было неправильные параметры для QSignalTransition(sender, signal, source_state)
конструктор, так как он слишком похож на синтаксис ->addTransition(sender, signal, target_state)
так что я перепутал source
а также target
,
После того, как они были созданы таким образом, должно быть легко перенаправить или отключить некоторые из этих переходов при создании подкласса этого объекта.
Других решений пока нет …