应用程序中实现我自己的事件循环

应用程序中实现我自己的事件循环

本文介绍了在 wxPython 应用程序中实现我自己的事件循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 wxPython 应用程序,它将进行大量的数据分析和显示.到目前为止,当两个线程试图同时更改 GUI 中的某些内容时,我编写它的方式会导致问题.我想要做的是设置我自己的在主线程上运行的简单队列,以便我可以确保 UI 更新一次发生一个.

I’m writing a wxPython application that will be doing quite a bit of data analysis and display. The way I’ve written it so far has led to problems when two threads try to change something in the GUI at the same time. What I want to do is to set up my own simple queue running on the main thread so that I can ensure that UI updates happen one at a time.

不过,我无法理解如何设置事件循环.一般来说,你会做类似的事情

I’m having trouble getting my head around how I’d set up my event loop, though. In general you’d do something like

while True:
    try:
        callback = queue.get(False)
    except Queue.Empty:
        break
    callback()

我假设如果我按原样运行该代码,那么 WX 将无法完成它的工作,因为它永远不会接收任何事件或任何东西,因为控制永远不会离开我的无限循环.如何让这种结构与 WX 事件循环共存?或者更一般地说,在 WX 应用程序中,我如何确保某个任务只在主线程上运行?

I assume that if I run that code as-is then WX will not be able to do its thing because it will never receive any events or anything because control never leaves my infinite loop. How can I make this kind of structure coexist with the WX event loop? Or more generally, in a WX application how can I ensure that a certain task is only ever run on the main thread?

推荐答案

您可以使用 wx.callafter,它需要一个可调用对象,在当前和挂起的事件处理程序完成后,它会在 guis 主循环中调用.任何额外的位置或关键字参数都会在调用时传递给可调用对象.

You can use wx.callafter, it takes a callable object that is called in the guis mainloop after the current and pending event handlers have been completed. Any extra positional or keyword args are passed on to the callable when it is called.

这是一个gui代码示例,它在运行单独的线程并在主线程中更新GUI时利用了wx.CallAfter.

Here is an example of gui code that takes advantage of wx.CallAfter when running a separate thread and updating the GUI in the main thread.

代码由 Andrea Gavana 提供,可在 wxpython Phoenix 文档

The code is by Andrea Gavana which is found in the wxpython Phoenix docs

#!/usr/bin/env python

# This sample shows how to take advantage of wx.CallAfter when running a
# separate thread and updating the GUI in the main thread

import wx
import threading
import time

class MainFrame(wx.Frame):

    def __init__(self, parent):
        wx.Frame.__init__(self, parent, title='CallAfter example')

        panel = wx.Panel(self)
        self.label = wx.StaticText(panel, label="Ready")
        self.btn = wx.Button(panel, label="Start")
        self.gauge = wx.Gauge(panel)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.label, proportion=1, flag=wx.EXPAND)
        sizer.Add(self.btn, proportion=0, flag=wx.EXPAND)
        sizer.Add(self.gauge, proportion=0, flag=wx.EXPAND)

        panel.SetSizerAndFit(sizer)
        self.Bind(wx.EVT_BUTTON, self.OnButton)

    def OnButton(self, event):
        """ This event handler starts the separate thread. """
        self.btn.Enable(False)
        self.gauge.SetValue(0)
        self.label.SetLabel("Running")

        thread = threading.Thread(target=self.LongRunning)
        thread.start()

    def OnLongRunDone(self):
        self.gauge.SetValue(100)
        self.label.SetLabel("Done")
        self.btn.Enable(True)

    def LongRunning(self):
        """This runs in a different thread.  Sleep is used to
         simulate a long running task."""
        time.sleep(3)
        wx.CallAfter(self.gauge.SetValue, 20)
        time.sleep(5)
        wx.CallAfter(self.gauge.SetValue, 70)
        time.sleep(4)
        wx.CallAfter(self.OnLongRunDone)

if __name__ == "__main__":
    app = wx.App(0)
    frame = MainFrame(None)
    frame.Show()
    app.MainLoop()

这篇关于在 wxPython 应用程序中实现我自己的事件循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 13:39