首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何安全地管理wxPython进度对话框线程?

如何安全地管理wxPython进度对话框线程?
EN

Stack Overflow用户
提问于 2013-11-15 23:36:56
回答 1查看 1.6K关注 0票数 2

我可以在没有任何用户输入的情况下运行几个计算,而且用户也不必担心程序已经冻结,所以我试图显示一个进度条弹出,以使他们知道正在发生的事情。

环顾四周让我相信我需要使用一个单独的线程来完成这个任务,于是我想出了这个例子。

代码语言:javascript
复制
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()

它看起来像预期的那样起作用了,但是有什么我跳过的管家吗?

编辑:我用miniframe替换了对话框,这样主窗口就不会冻结,关闭按钮就不会产生几个框架,并添加了一个粗略的取消方法。

代码语言:javascript
复制
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()
EN

回答 1

Stack Overflow用户

发布于 2013-11-16 15:20:18

看上去不错,只是观察了几次。

  • 您不应该在工作线程上调用任何窗口函数。这包括SetPositionDestroy。您可以使用wx.CallAfter在主线程上调用这些线程,就像用于Update一样。
  • 您可能应该允许用户取消处理。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20012542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档