如何从状态对象本身改变状态而不是外部?

时间:2015-06-23 16:30:15

标签: c++ qt qstatemachine

    class ListenState : public QState
    {
    public:
        ListenState();
        ~ListenState();

    signals:
        void nextState();

    public slots:
        void getSettings();
    };

cpp文件是

ListenState::ListenState()
{
    qDebug() << "Entering ListenState";
}

ListenState::~ListenState()
{
    qDebug() << "Leaving ListenState";
}

void ListenState::getSettings()
{
    Commands cmd;

    cmd.getSettings();

    emit exited( QEvent::None ); // i want to change state now
}

我想要做的是在调用getSettings()时,我想将状态更改为下一个。我以为我会emit exited(),但它不会构建。我尝试创建自己的信号nextState(),但如果我在此函数中发出,则不会编译。

使用上面的代码,错误是:

  

ListenState.cpp:23:错误:C2664:&#39; QAbstractState :: exited&#39; :不能   转换参数1来自&#39; QEvent :: Type&#39;至   &#39; QAbstractState :: QPrivateSignal&#39;没有用户定义的转换运算符   可以执行此转换,或运营商不能   称为

如果我用emit nextState();发出自己的信号,则错误为:

  

ListenState.obj:-1:错误:LNK2001:未解析的外部符号   &#34; public:void __thiscall ListenState :: nextState(void)&#34;   (?nextState @ @@ ListenState QAEXXZ)

当我处于原始状态时,有没有办法从一个州到另一个州触发交易?

1 个答案:

答案 0 :(得分:3)

首先,状态的生命周期与进入或退出状态时几乎没有关系。只要状态机存在,状态通常就存在,或者它们可以在运行中创建和销毁。您正在连接状态的构造函数和析构函数,期望在进入或退出状态时调用它们。事实并非如此。

要检查状态何时进入或退出,您可以使用以下内容:

void exposeStateTransitions(QState * state, QString name) {
  if (name.isEmpty()) name = state->objectName();
  QObject::connect(state, &QState::entered, []{
    qDebug() << "state" << name << "was entered";
  });
  QObject::connect(state, &QState::exited, []{
    qDebug() << "state" << name << "was exited";
  });
}

其次,状态只能通过使用过渡对象来改变。您需要为所需的转换创建一个转换对象,并提供一个信号或事件来触发它:

class ListenState : public QState {
  Q_OBJECT
  QSignalTransition m_transition;
  Q_SIGNAL void settingsTransition();
public:
  ListenState(QState * settingsTarget, QState * parent = 0) : 
    QState(parent), m_transition(this, SIGNAL(settingsTransition())
  {
    m_transition.setTargetState(settingsTarget);
    addTransition(&m_transition);
  }
  void getSettings() {
    ...
    emit settingsTransition();
  }
};

如果您愿意,也可以动态触发过渡:

class ListenState : public QState {
  Q_OBJECT
  QSignalTransition m_transition;
  Q_SIGNAL void settingsTransition();
public:
  ListenState(QState * parent = 0) : 
    QState(parent), m_transition(this, SIGNAL(settingsTransition())
  {
    addTransition(&m_transition);
  }
  void getSettings(QState * target) {
    ...
    m_transition.setTargetState(target);
    emit settingsTransition();
  }
};

您可以使用事件而不是信号:

class ListenState : public QState {
  QEventTransition m_transition;
public:
  ListenState(QState * parent = 0) : 
    QState(parent), m_transition(this, QEvent::Leave) {
    addTransition(&m_transition);
  }
  void getSettings(QState * target) {
    ...
    m_transition->setTargetState(target);
    QCoreApplication::postEvent(this, new QEvent(QEvent::Leave));
  }
};