每 wx.App.MainLoop 次执行执行一次方法,无需重复 wx.CallAfter 次调用

Executing method once per wx.App.MainLoop execution without repeat wx.CallAfter calls

我正在使用 wxpython 创建一个使用 MVC 设计模式的 GUI。我正在使用带有控制器的状态机来跟踪应用程序的状态,并且希望在每次 wx.App.MainLoop() 函数运行时只执行一次状态转换方法。我希望它在 MainLoop() 函数期间在一致的位置执行,所以我宁愿避免线程或 wx.CallLater().

有没有办法使用 wx.CallAfter() 或类似方法永久添加方法,以便每次通过 MainLoop() 执行一次?

我曾尝试查看 wx.App.GetMainLoop() 的 return 对象,但没有找到如何使用该对象实现上述功能的方法。

也许你认为它比实际情况更复杂。在空闲时间强制轮询 GUI 会导致处理器负载过高。假设您的程序包含一个 GUI、状态机和一些不是来自 GUI 的输入(例如来自网络)。大概你的状态机会在三种情况下改变状态:

  1. 用户在 GUI 中输入内容
  2. 内部状态改变
  3. 外部 I/O(不通过 GUI)正在发生

对于这些情况,您will/can执行以下操作:

  1. GUI 输入是事件驱动的:您决定将哪些用户输入视为状态改变。这可以从单击 OK 按钮到捕获 EVT_TEXT 或鼠标事件。此处无需投票

  2. 内部状态变化:

    • 状态机事件循环中的状态变化(如果有的话)。如果状态机中有事件循环,则需要在单独的线程中将其关闭,否则 GUI 会阻塞。您必须以线程安全的方式将状态机中的更改反馈给 GUI(最简单的方法是 wx.CallAfter)。参见 the very helpful wxPython wiki
    • 每隔一段时间(例如,每 100 毫秒)使用 wx.Timer 调用状态机。在这种情况下,状态机甚至不需要自己的线程和线程安全通信。
  3. 原则上,与第 2 点相同的事情可以为 I/O 完成。分拆线程或使用计时器定期调用 I/O-machinery.

您还可以绑定到 EVT_IDLE,每当事件循环中没有更多事件挂起时,它就会被调用。但是当然这只会导致不必要的轮询。