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

How to change state from the state object itself not outside?

本文关键字:状态 外部 改变 对象      更新时间:2023-10-16
    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:"QAbstractState::exited":无法将参数1从"QEvent::Type"转换为'QAbstractState::QPrivateSignal'没有用户定义的转换运算符可用,可以执行此转换,或者运算符不能称为

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

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

当我处于原始状态时,有没有办法触发从一种状态到另一种状态的转换?

首先,状态的生存期与进入或退出状态的时间关系不大。只要状态机存在,状态通常就存在,或者它们可能在飞行中被创建和摧毁。您正在连接一个状态的构造函数和析构函数,期望它们在进入或退出状态时被调用。事实并非如此。

要检查何时进入或退出状态,可以使用以下方法:

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));
  }
};