9

Qt GUI イベントを記録し、スクリプトから再生するためのシンプルで軽量なシステムを実装しようとしています。これは Qt のイベント システムの魔法を使えばかなり簡単だと思っていましたが、理解できない問題に直面しています。

ここに私がやっていることの簡単な要約があります:

録音:

QApplication.instance().eventFilter()は興味のあるすべての GUI イベントをキャプチャし*、Python スクリプトに保存します。各ステップは次のようになります。

obj = get_named_object('MainWindow.my_menubar')
recorded_event = QMouseEvent(2, PyQt4.QtCore.QPoint(45, 8), 1, Qt.MouseButtons(0x1), Qt.KeyboardModifiers(0x0))
post_event(obj, recorded_event)

再生:

上記のスクリプトをワーカー (非 GUI ) スレッドで実行するだけです。(モーダル ダイアログ イベントループの実行中に「メイン」イベントループがブロックされても、スクリプト化されたイベントをアプリケーションに送信し続けたいため、GUI スレッドを使用できません。)

重要なことは、次のpost_event()2 つのことを行う必要がある関数で発生します。

  • まず、電話QApplication.postEvent(obj, recorded_event)
  • すべてのイベントの処理が完了するまで待ちます:**
    • 実行中の同じイベントループに特別なイベントを投稿objします。
    • 特別なイベントが処理される場合:
      • 電話QApplication.processEvents()
      • 続行しても問題ないことを再生スレッドに伝えるフラグを設定します

2 番目の部分が完了した後、特別なイベントが記録されたイベントの後にキューに入れられたため、最初の部分 (記録されたイベント) のすべての効果が完了したことを期待しています。

システム全体は、ほとんどの場合、マウス イベント、キー イベントなどで問題なく動作しているように見えます。しかしQAction、メインのイベントを再生しようとすると、ハンドラーに問題が発生しますQMenuBar

何を試しても、アイテムをクリックした結果として生じるすべてのハンドラーの完了のために、再生スレッドを強制的にブロックすることはできないようです。QAction.triggeredQMenu私が知る限り、ハンドラーが完了する前QApplication.processEvents()に戻っています。QAction

および/またはの通常のルールを破るQMenuウィジェットまたはシグナルについて何か特別なことはありますか? ハンドラーの完了をブロックする方法が必要です。QActionQApplication.postEvent()QApplication.processEvents()QMenuQAction

[*] すべてのイベントが記録されているわけではありません。私はイベントのみを記録し、他のいくつかのタイプ (イベントや通常のマウスの動きなど)spontaneous()も除外します。Paint

[**] スクリプト内の次のイベントは、前のイベントによって作成されたウィジェットを参照する可能性があるため、これは重要です。

4

2 に答える 2

1

あなたの問題は、QFuture と QFutureWatcher を使用することで解決できると思います (つまり、QThreads ではなく、スレッドに QtConcurrent 名前空間を使用している場合)。基本的に、Qt イベント処理システムは、必ずしもイベントがポストされた順序で処理するとは限りません。特定のアクションが完了するまでブロックする必要があり、そのアクションを別のスレッドで実行している場合は、QtConcurrent::run() によって返された QFuture オブジェクトを QFutureWatcher とともに使用して、その特定のスレッドが処理を完了するまでブロックすることができます。 .

他に考慮すべきことは、イベントの処理方法です。QApplication.postEvent() を使用すると、作成したイベントがレシーバーのイベント キューに追加され、後で処理されます。バックグラウンドで、Qt はこれらのイベントを並べ替えて圧縮し、プロセッサ時間を節約できます。これはもっとあなたの問題だと思います。

再生を処理する関数では、QCoreApplication::processEvents() の使用を検討してください。これは、すべてのイベントの処理が完了するまで返されません。QCoreApplication のドキュメントはこちらです。

于 2013-04-05T17:10:34.677 に答える