Qt GUI-Ereignisaufnahme und -wiedergabe

8

Ich versuche ein einfaches, leichtgewichtiges System zur Aufzeichnung von Qt-GUI-Ereignissen und zur Wiedergabe von einem Skript zu implementieren. Ich dachte, das wäre ziemlich einfach, wenn man die Magie von Qts Event-System benutzt, aber ich stoße auf ein Problem, das ich nicht verstehe.

Hier ist eine kurze Zusammenfassung dessen, was ich mache:

AUFNAHME:

Ich verwende QApplication.instance().eventFilter() , um alle GUI-Ereignisse zu erfassen, die mich interessieren * und sie in einem Python-Skript zu speichern, in dem jeder Schritt etwa so aussieht:

%Vor%

WIEDERGABE:

Ich führe einfach das obige Skript in einem Worker-Thread ( non-GUI ) aus. (Ich kann den GUI-Thread nicht verwenden, da ich weiterhin Skriptereignisse an die Anwendung senden möchte, selbst wenn die Ereignisschleife 'main' blockiert ist, während ein modaler Dialog-Eventloop ausgeführt wird.)

Die wichtigen Dinge passieren in meiner Funktion post_event() , die zwei Dinge tun muss:

  • Rufen Sie zuerst QApplication.postEvent(obj, recorded_event) auf
  • Warten Sie, bis alle Ereignisse verarbeitet wurden: **
    • Veröffentlichen Sie ein spezielles Ereignis in derselben Ereignisschleife, in der obj ausgeführt wird.
    • Wenn das besondere Ereignis behandelt wird:
      • Aufruf QApplication.processEvents()
      • Setzen Sie ein Flag, das dem Wiedergabethread sagt, dass es OK ist, fortzufahren

Nachdem der zweite Teil abgeschlossen ist, erwarte ich, dass alle Effekte des ersten Teils (des aufgezeichneten Ereignisses) abgeschlossen sind , da das spezielle Ereignis nach in die Warteschlange gestellt wurde aufgezeichnetes Ereignis.

Das ganze System meist scheint bei Mausereignissen, Schlüsselereignissen usw. gut zu funktionieren. Aber ich habe ein Problem mit QAction handlers, wenn ich versuche, Ereignisse für mein Haupt-% abzuspielen. co_de%.

Egal was ich versuche, es scheint, dass Ich kann nicht zwingen, dass mein Playback-Thread den Abschluss aller QMenuBar Handler blockiert , die sich aus dem Klicken auf meine QAction.triggered -Elemente ergeben. Soweit ich das beurteilen kann, gibt QMenu zurück, bevor der QApplication.processEvents() -Handler fertig ist.

Gibt es etwas Besonderes an QAction widgets oder QMenu signals, das die normalen Regeln für QAction und / oder QApplication.postEvent() bricht? Ich benötige eine Möglichkeit, die Verarbeitung meiner QApplication.processEvents() QMenu Handler zu blockieren.

[*] Nicht jedes Ereignis wird aufgezeichnet. Ich zeichne nur QAction -Ereignisse auf, und ich filtere auch ein paar andere Typen heraus (z. B. spontaneous() -Ereignisse und normale Mausbewegungen).

[**] Dies ist wichtig, da sich das nächste Ereignis im Skript möglicherweise auf ein Widget bezieht, das durch das vorherige Ereignis erstellt wurde .

    
Stuart Berg 03.04.2013, 10:19
quelle

2 Antworten

1

Ich denke, Ihr Problem könnte am besten durch die Verwendung von QFuture und QFutureWatcher behoben werden (das heißt, wenn Sie den QtConcurrent-Namespace für Threads und nicht QThreads verwenden). Grundsätzlich behandelt das Qt-Event-Handling-System Ereignisse NICHT unbedingt in der Reihenfolge, in der sie gepostet werden. Wenn Sie blockieren müssen, bis eine bestimmte Aktion abgeschlossen ist und Sie diese Aktion in einem separaten Thread ausführen, können Sie das von QtConcurrent :: run () mit einem QFutureWatcher zurückgegebene QFuture-Objekt verwenden, um zu blockieren, bis der betreffende Thread seine Verarbeitung beendet hat .

Etwas anderes ist die Art, wie Sie mit Ereignissen umgehen. Wenn Sie QApplication.postEvent () verwenden, wird das Ereignis, das Sie erstellen, der Ereigniswarteschlange des Empfängers hinzugefügt, um später behandelt zu werden. Hinter den Kulissen kann Qt diese Ereignisse neu anordnen und komprimieren, um Prozessorzeit zu sparen. Ich vermute, das ist eher dein Problem.

Ziehen Sie in Ihrer Funktion, die die Wiedergabe behandelt, die Verwendung von QCoreApplication :: processEvents () in Betracht, die erst zurückgegeben wird, wenn alle Ereignisse abgeschlossen sind. Dokumentation für QCoreApplication ist hier.

    
gankoji 05.04.2013 17:10
quelle
1

QMenu-Widgets und QAction-Signale sind ein Sonderfall. QMenu hat eine exec () -Funktion, die normalerweise für Popups verwendet wird. Ich vermute (aber ich weiß nicht sicher), dass QMenuBar diesen Mechanismus verwenden würde, wenn er ein normales Pull-Down-Menü öffnet. Die Docs sind sich darüber nicht im Klaren, aber Menus verhalten sich ähnlich wie Dialogfelder, da sie alle anderen Benutzeraktivitäten blockieren. Wie würde Qt dies tun, außer, Menüs eine eigene Ereignisschleife zu geben? Ich kann nicht alle Leerstellen aus den Informationen in Ihrem Beitrag ausfüllen, aber ich sehe nicht, wie Ihr Wiedergabe-Thread mit einer neuen Ereignisschleife zurechtkommen würde.

    
Paul Cornelius 01.06.2013 06:05
quelle

Tags und Links