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