Как изменить состояние самого объекта состояния не снаружи?

    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)

Есть ли способ вызвать переход из одного состояния в другое, когда я нахожусь в исходном состоянии?

1

Решение

Во-первых, время жизни состояния очень мало связано с тем, когда оно входит или выходит. Состояния обычно существуют до тех пор, пока существует конечный автомат, или они могут создаваться и уничтожаться на лету. Вы подключаете конструктор и деструктор состояния, ожидая, что они будут вызваны при входе или выходе из состояния. Это не вариант.

Чтобы проверить, когда состояние было введено или вышло, вы можете использовать следующее:

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

Другие решения


По вопросам рекламы [email protected]