1

だから私はQtのQStateMachineの問題を理解しようとしています。そして、誰かがこれが起こっている理由を説明するのを手伝ってくれることを望んでいます。修正だけでなく、QStateMachineの基本的な理解に非常に興味があります。

まず、状態A、B、およびイベント1のステートマシンについて考えます。イベント1は、AからBに移動します。Aは初期状態です。

具体的には、これはネイバーを維持するためのものです。デバイスXIで、ネイバーYがhelloと言うメッセージを受け取ります。これにより、ネイバーXはこの新しいネイバーYのネイバーステートマシンをmallocします。これにより、ネイバーステートマシンが作成され、QStateMachine :: start();が呼び出されます。

このステートマシンが起動した後、このhelloメッセージの処理を続行する必要があります。だから最初はやっていた:

QStateMachine::start( ) ;
emit event 1 ;

私の理解では、startは非同期呼び出しであり、開始が完了するまでステートマシンは最初の起動にないため、これは機能しません。それが私の最初の質問につながります。

1)それで、ステートマシンの開始はqappイベントキューに入れられますが、非同期呼び出しも発行しませんか?イベント1は開始後にイベントキューに入れられないので、初期状態になるということではないでしょうか。または、emitは非同期呼び出しではありませんか?

これが問題だと思って、ステートマシンの開始信号に関数を接続してコードを少し変更しました。次に、ステートマシンが開始されていない場合にイベントをキューに入れるようにコードを変更し、開始シグナルが呼び出された後、保留中のイベントのこのキューを処理します(そしてそれらをステートマシンに発行します)。

さて、私が信号を開始したとき、初期状態はまだ設定されていないことがわかりました。例:QStateMachine :: configuration().contains(initialstate)==false。これは私の2番目のより大きな質問につながります。

2)開始信号が出たときに初期状態になっていないのはなぜですか。

ここでのイベントのシーケンスは次のとおりです。

  1. ステートマシンを作成する
  2. 初期状態を設定する
  3. ステートマシンを起動します
  4. イベント1を受信する
  5. キューイベント1が開始されていないため
  6. 信号受信を開始しました
  7. イベント1を処理します
  8. 状態が不明なので何もしません
  9. イベント1を受信する
  10. イベント1を処理します
  11. 現在、状態Aにあります。状態Bに移行します。

シーケンスは次のようになります。

  1. ステートマシンを作成する
  2. 初期状態を設定する
  3. ステートマシンを起動します
  4. イベント1を受信する
  5. キューイベント1が開始されていないため
  6. 信号受信を開始しました
  7. イベント1を処理します
  8. これで状態Aになります。状態Bに移行します。
  9. イベント1を受信する
  10. イベント1を処理します
  11. 現在は状態Bです。何もしません。

または、イベントの方が良いです。イベントをキューに入れる必要がなかったらいいのにと思います。私はこれができたらいいのにと思います:

  1. ステートマシンを作成する
  2. 初期状態を設定する
  3. ステートマシンを起動します
  4. イベント1を受信する
  5. イベント1を処理します
  6. これで状態Aになります。状態Bに移行します。
  7. イベント1を受信する
  8. イベント1を処理します
  9. 現在は状態Bです。何もしません。
4

1 に答える 1

6

遷移信号は、状態が変化した後にのみ接続され(in QStateMachinePrivate::registerSignalTransition)、接続はキューに入れられた接続ではありません。

bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
                                   signalEventGenerator->metaObject()->methodOffset());

「イベント1」を受信するには、マシンがその信号に反応する状態になっている必要があります。キューに入れられた接続であっても、スロットはキューに入れられますが、信号が受信された後でのみ、その時点ではまだ接続がないため、キューに入れられません。

問題を解決するには、マシンが「状態A」になるのを待ってから、信号を送信します。

machine->start();
qApp->processEvents();
emit event1();

または、信号の放出を遅らせて、他のすでにキューに入れられている操作の後にキューに入れることができます。

machine->start();
QTimer::singleShot(0, emitter, SIGNAL(event1()));
// or
QMetaObject::invokeMethod(emitter, "event1", Qt::QueuedConnection);

started信号は、初期状態が設定される前に発行されます(ソースコードによる)。これは、状態が設定される前に初期化を行う場合に役立ちます。初期状態を待つ必要がある場合は、シグナルを使用できますQState::entered

于 2012-04-08T02:16:03.353 に答える