QtGUI事件记录与播放

2024-05-16 06:33:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图实现一个简单、轻量级的系统,用于记录qtgui事件并从脚本中回放它们。我原以为使用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()
      • 设置一个标志,告诉回放线程可以继续

在第二部分完成后,我的期望是第一部分(记录事件)的所有效果都已完成,因为特殊事件在记录事件之后排队。在

整个系统似乎对鼠标事件、按键事件等都能正常工作,但是当我试图为我的mainQMenuBar回放事件时,QAction处理程序有问题。在

无论我做什么尝试,似乎我都不能强制我的回放线程阻止所有QAction.triggered处理程序的完成,这些处理程序是通过单击我的QMenu项来完成的。据我所知,QApplication.processEvents()QAction处理程序完成之前返回。在

关于QMenu小部件或QAction信号是否有什么特殊之处,它违反了QApplication.postEvent()和/或{}的正常规则?我需要一种方法来阻止我的QMenuQAction处理程序的完成。

[*]并非所有事件都会被记录。我只记录spontaneous()事件,还过滤出一些其他类型的事件(例如Paint事件和普通的鼠标移动)。在

[**]这一点很重要,因为脚本中的下一个事件可能引用上一个事件创建的小部件。在


Tags: 脚本eventobj处理程序系统记录事件gui
2条回答

我认为使用QFuture和QFutureWatcher(也就是说,如果您对线程使用QtConcurrent命名空间,而不是QThreads),可能会更好地解决您的问题。基本上,Qt事件处理系统不一定按照事件的发布顺序来处理事件。如果您需要阻塞直到某个操作完成,并且您在一个单独的线程中执行该操作,则可以使用QtConcurrent::run()返回的QFuture对象与QFutureWatcher一起阻止,直到该特定线程完成其处理。在

另外要考虑的是你处理事件的方式。当你使用QApplication.postEvent(),您创建的事件将添加到接收方的事件队列中,以便稍后处理。在幕后,Qt可以重新排序和压缩这些事件,以节省处理器时间。我怀疑这是你的问题。在

在处理回放的函数中,请考虑使用QCoreApplication::processEvents(),它在所有事件完成处理之前不会返回。QCoreApplication的文档是here.

QMenu小部件和QAction信号是一种特殊情况。QMenu有一个exec()函数,通常用于弹出窗口。我怀疑(但我不确定)QMenuBar在打开常规下拉菜单时会使用这种机制。文档并不清楚这一点,但是菜单的行为很像对话框,因为它们阻止了所有其他用户活动——除了给菜单自己的事件循环之外,Qt如何做到这一点呢?我无法从您的帖子中填写所有信息,但我不知道您的回放线程将如何处理新的事件循环。在

相关问题 更多 >