[英]Qt GUI event recording and playback
我正在嘗試實現一個簡單,輕量級的系統來記錄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)
回放:
我只是在一個worker( 非GUI )線程中執行上面的腳本。 (我不能使用GUI線程,因為我想繼續向應用程序發送腳本事件,即使在模式對話框eventloop運行時'main'eventloop被阻止。)
重要的東西發生在我的post_event()
函數中,它需要做兩件事:
QApplication.postEvent(obj, recorded_event)
obj
的同一事件循環中。 QApplication.processEvents()
第二部分完成后,我的期望是第一部分(記錄的事件)的所有效果都已完成 ,因為特殊事件在記錄的事件之后排隊。
整個系統主要是似乎只是正常工作的鼠標事件,重要事件等,但我有一個問題QAction
處理程序,當我試圖播放我的主要活動QMenuBar
。
無論我嘗試什么,似乎我都不能強制我的回放線程阻止完成因點擊我的QMenu
項而產生的所有QAction.triggered
處理程序 。 據我所知, QApplication.processEvents()
在QAction
處理程序完成之前返回。
有關QMenu
小部件或QAction
信號的特殊內容QMenu
違反了QApplication.postEvent()
和/或QApplication.processEvents()
的常規規則? 我需要一種方法來阻止我的QMenu
的QAction
處理程序的完成。
[*]並非每個事件都被記錄下來。 我只記錄spontaneous()
事件,我還過濾掉了一些其他類型(例如Paint
事件和普通鼠標移動)。
[**]這很重要,因為腳本中的下一個事件可能引用上一個事件創建的窗口小部件。
我認為你的問題可能最好通過使用QFuture和QFutureWatcher來實現(也就是說,如果你為線程使用QtConcurrent命名空間而不是QThreads)。 基本上,Qt事件處理系統不一定按照發布的順序處理事件。 如果需要阻塞直到某個操作完成,並且您在單獨的線程中執行該操作,則可以使用QtConcurrent :: run()返回的QFuture對象與QFutureWatcher一起阻塞,直到該特定線程完成其處理。
還需要考慮的是處理事件的方式。 使用QApplication.postEvent()時,您創建的事件將添加到接收方的事件隊列中,以便稍后處理。 在幕后,Qt可以重新排序和壓縮這些事件以節省處理器時間。 我懷疑這更像是你的問題。
在處理回放的函數中,請考慮使用QCoreApplication :: processEvents(),它將在所有事件處理完畢后才返回。 QCoreApplication的文檔就在這里。
QMenu小部件和QAction信號是一個特例。 QMenu有一個exec()函數,通常用於彈出窗口。 我懷疑(但我不確定)QMenuBar在打開常規下拉菜單時會使用此機制。 文檔對此並不清楚,但Menus的行為很像對話框,因為它們阻止了所有其他用戶活動 - 除了通過給菜單提供自己的事件循環之外,Qt將如何做到這一點? 我無法填寫你帖子中信息的所有空白,但我看不到你的播放線程如何應對新的事件循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.