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.triggered
QMenu
私が知る限り、ハンドラーが完了する前QApplication.processEvents()
に戻っています。QAction
および/またはの通常のルールを破るQMenu
ウィジェットまたはシグナルについて何か特別なことはありますか? のハンドラーの完了をブロックする方法が必要です。QAction
QApplication.postEvent()
QApplication.processEvents()
QMenu
QAction
[*] すべてのイベントが記録されているわけではありません。私はイベントのみを記録し、他のいくつかのタイプ (イベントや通常のマウスの動きなど)spontaneous()
も除外します。Paint
[**] スクリプト内の次のイベントは、前のイベントによって作成されたウィジェットを参照する可能性があるため、これは重要です。