如何安全管理wxPython进度对话框线程? [英] How Can I Safely Manage wxPython Progress Dialog Threading?

查看:107
本文介绍了如何安全管理wxPython进度对话框线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以在没有任何用户输入的情况下运行多个计算,并且无需用户担心程序被冻结,因此我试图显示一个进度栏弹出窗口,以使他们了解正在发生的事情.

I have several calculations to run without any user input and without the user worrying about the program having frozen, so I am trying to show a progress bar popup to keep them aware of what's happening.

环顾四周使我相信我需要使用一个单独的线程来执行此操作,因此我想到了这个示例.

Looking around has lead me to believe that I need to use a separate thread to do this, and I came up with this example.

import threading, wx, time

MAX_INT = 10
TEST_TUPLE = [[11, 22],[33,44]]

class mainFrame(wx.Frame):
    def __init__(self, parent, ID, title):
        wx.Frame.__init__(self, parent, ID, title)
        bt = wx.Button(self, wx.ID_OK)
        self.Bind(wx.EVT_BUTTON, self.onBt, bt)

    def onBt(self,event):
        self.dlg = wx.ProgressDialog("title", "message", maximum=MAX_INT)
        workThread = threading.Thread(target=self.doWork, args=(TEST_TUPLE,) )
        workThread.start()
        self.dlg.ShowModal()

    def doWork(self, testArg):
        # time consuming stuff that affects main GUI
        print testArg
        for i in range(1, MAX_INT+1):
            self.SetPosition((i*4*MAX_INT, i*2*MAX_INT))
            time.sleep(1)
            print str(i)+" of "+str(MAX_INT)
            wx.CallAfter(self.dlg.Update, i, "%i of %i"%(i, MAX_INT))
        self.dlg.Destroy()


app = wx.App(False)
fr = mainFrame(None, -1, "Title")
fr.Show()
app.MainLoop()

它似乎按预期工作,但是我在这里跳过了一些家政服务吗?

It seems to work as intended, but is there some housekeeping that I am skipping here?

我用小框架替换了对话框,因此主窗口不会冻结,禁用了按钮,因此不会产生多个框架,并添加了一种粗略的取消方法.

I replaced the dialog with a miniframe so the main window would not freeze, disabled the button so there wouldn't be several frames spawned, and added a crude cancelling method.

import threading, wx, time

MAX_INT = 10
TEST_TUPLE = [[11, 22],[33,44]]

class GaugeFrame(wx.MiniFrame):
    def __init__(self, parent, title, maximum):
        wx.MiniFrame.__init__(self, parent, title=title, size=(200, 60) )

        self.bar = wx.Gauge(self, range=maximum)
        self.buCancel = wx.Button(self, label="Cancel")
        self.SetBackgroundColour("LTGRAY")

        siMainV = wx.BoxSizer(wx.VERTICAL)
        siMainV.Add(self.bar)
        siMainV.Add(self.buCancel, flag=wx.CENTER)
        self.SetSizer(siMainV)
        self.Fit()

        self.Bind(wx.EVT_BUTTON, self.onCancel, self.buCancel)

    def updateGauge(self, value, message=""):
        self.bar.SetValue(value)
        if message!="":
            self.SetTitle(message)

    def onCancel(self, e):
        self.SetTitle("Cancelling...")

class MainFrame(wx.Frame):
    def __init__(self, parent, ID, title):
        wx.Frame.__init__(self, parent, ID, title)
        self.bt = wx.Button(self, wx.ID_OK)
        self.Bind(wx.EVT_BUTTON, self.onBt, self.bt)

    def onBt(self, event):
        self.gFr = GaugeFrame(self, title="0 of "+str(MAX_INT), maximum=MAX_INT)
        self.gFr.Show()
        self.gFr.Center()
        self.bt.Disable()
        workThread = threading.Thread(target=self.doWork, args=(TEST_TUPLE,) )
        workThread.start()

    def doWork(self, testArg):
        # time consuming stuff that affects main GUI
        print testArg
        for i in range(1, MAX_INT+1):
            time.sleep(1)
            if self.gFr.GetTitle()=="Cancelling...":
                break
            print str(i)+" of "+str(MAX_INT)
            wx.CallAfter(self.gFr.updateGauge, i, "%i of %i"%(i, MAX_INT))
        wx.CallAfter(self.gFr.Destroy)
        wx.CallAfter(self.bt.Enable)


app = wx.App(False)
fr = MainFrame(None, -1, "Title")
fr.Show()
app.MainLoop()

推荐答案

看起来不错,只需观察几个即可.

Looks pretty good, just a couple of observations.

  • 您不应在辅助线程上调用任何窗口函数.这包括SetPositionDestroy.您可以像在Update中那样使用wx.CallAfter在主线程上调用它们.
  • 您可能应该允许用户取消处理.
  • You should not call ANY window functions on the worker thread. This includes SetPosition and Destroy. You can use wx.CallAfter to invoke these on the main thread just like you are for Update.
  • You probably should allow the user to cancel the processing.

这篇关于如何安全管理wxPython进度对话框线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆