繁体   English   中英

Qt GUI事件录制和播放

[英]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()的常规规则? 我需要一种方法来阻止我的QMenuQAction处理程序的完成。

[*]并非每个事件都被记录下来。 我只记录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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM