2015-08-12 2 views
2

У меня есть экземпляр QStateMachine в моей программе. Я настраиваю его состояния, переходы и начальное состояние в его конструкторе. И, конечно, я начинаю его в конструкторе.Проблема синхронизации с QStateMachine

this->stateA = new StateA(this); 
this->stateB = new StateB(this); 
this->stateA->addTransition(this, &Machine::foo, this->stateB); 
this->setInitialState(this->stateA); 
this->start(); 
// At this point the machine is still not in the stateA 

Проблема я столкнулся, было то, что машина не перемещается в исходное состояние перед выполнением start() отделки. Это приводит к тому, что сигнал foo, который должен переместить машину из исходного состояния в другое, излучается до того, как было введено начальное состояние.

Machine* machine = new Machine(); 
// start() was already called here but the machine is still not in the initial state 
machine->foo(); 
// Signal is emitted here (It also may not be emitted. This is not an unconditional transition). But the machine is still not in the initial state and the transition does not happen. 
// ... 
// Here the machine enters the initial state... 

Как я могу убедиться, что машина находится в исходном состоянии в точке ее конструкции?

ответ

0

Государственные машины асинхронны и управляются контуром событий. Нет причин для использования сигнала для перемещения аппарата в другое состояние при запуске. В этом случае вы хотите перейти от stateA к stateB при запуске и всякий раз, когда вызывается foo.

  1. Помните, что целью соединения может быть либо сигнал, либо слот. Вы можете подключить сигнал started конечного автомата к сигналу foo. Таким образом, foo будет излучаться, когда машина запустится и находится в исходном состоянии.

  2. Если вам не нужен сигнал foo, вы можете настроить переход на триггер непосредственно на сигнал started аппарата.

  3. Если вы всегда хотите перейти от stateA к stateB, даже некоторое время после того, как машина была запущена и stateA как-то заново, вы можете объявления безусловный переход от начального состояния в stateB. Машина, после ввода stateA, покинет ее, затем введите stateB, автоматически.

Изучите решения, начиная с последнего, и двигайтесь вверх, если вам нужно менее общее решение.

+0

Спасибо за ваш ответ. Я, вероятно, не описал, чего я хочу добиться. Я не хочу всегда выполнять переход с 'A' на' B' при запуске машины. 'machine-> foo()' может или не может излучать сигнал в зависимости от некоторых условий. Я хочу, чтобы переход выполнялся только после сигнала. – Kolyunya

+0

Насколько я вижу, единственным обходным решением является ожидание, пока машина не войдет в исходное состояние (чтобы ждать от него «инициализированный» сигнал), и только после этого выполнить какие-либо операции над ним. – Kolyunya

+0

@ Kolyunya Это не обходной путь, это то, что вы должны были делать все это время. Подумайте асинхронно. Не дожидайтесь, пока машина не запустится, просто запустите некоторый код *, когда * он начнется. Это делается путем подключения сигнала «начального» к слоту или к функтору. –

0

Вы можете убедиться, что машина находится в его исходное состояние в момент его конструкцию, создавая цикл событий в конструкторе вроде этого:

// ... 
this->start(); 
QEventLoop* eventLoop = new QEventLoop(this); 
QObject::connect(
    this, &Machine::started, 
    eventLoop, &QEventLoop::quit 
); 
eventLoop->exec(); 
Смежные вопросы