我希望有人能够帮助我使用wxPython显示长时间运行任务的进度。
我目前有一个函数,它由一个按钮调用,并执行其他5个函数,例如。
def sum(self, event):
self.processSents()
self.processWords()
self.repSents()
self.measSim()
self.selCont()
我想在执行这些功能时显示进度条,因为程序有时会挂起并且不理想。
我看过很多解决方案都建议使用线程,但我对Python中的线程缺乏经验,而且我的尝试让我无法快速完成任务。我不确定例如,对话框应该在线程,执行代码还是两者中。
我目前的尝试如下:
def sum(self, event):
progress = wx.ProgressDialog("sum in progress", "please wait", maximum=100, parent=self, style=wx.PD_SMOOTH|wx.PD_AUTO_HIDE)
self.Start(self.DoWork, progress)
progress.ShowModal()
def Start(func, *args):
thread = threading.Thread(target=func, args=args)
thread.setDaemon(True)
thread.start()
def DoWork(self, progress):
for i in range(101):
ex.CallAfter(progress.Update, i)
time.sleep(0.2)
self.processSents()
self.processWords()
self.repSents()
self.measSim()
self.selCont()
wx.CallAfter(progress.Destroy)
到目前为止我看过的解决方案是:
Updating a wxPython progress bar after calling app.MainLoop()
How to thread wxPython progress bar
How Can I Safely Manage wxPython Progress Dialog Threading?
http://wiki.wxpython.org/LongRunningTasks
任何帮助或建议都会受到赞赏,因为我很遗憾:(
由于
克里斯
更新为工作版本(根据Corley的建议将Jerry的回复与wx.Yield()相结合
def sum(self, event):
progress = wx.ProgressDialog("sum in progress", "please wait", maximum=100, parent=self, style=wx.PD_SMOOTH|wx.PD_AUTO_HIDE)
self.processSents()
percent = 20
progress.Update(percent)
self.processWords()
percent += 20
progress.Update(percent)
// repSends, measSim and selCont omitted to save space
progress.Destroy()
从每个函数中调用wx.Yield(),例如
def processSents(self):
// some long running process
wx.Yield()
// end of long running process
答案 0 :(得分:2)
1)单击按钮时将创建线程DoWork
。
2)在DoWork
中,将创建另一个线程showProgress
以显示进度对话框
3)在DoWork
,doSomething
模拟一些耗时的事情
4)在此示例中的每个updateProgress
之前创建线程doSomething
以避免进度条冻结,但实际上您应该在self.progress.Update
时调用sum progress
更新进度条{1}}
import wx
import threading
import time
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None)
panel = wx.Panel(self)
btn1 = wx.Button(panel, label="test1")
btn1.Bind(wx.EVT_BUTTON, self.onButton1)
btn2 = wx.Button(panel, label="test2")
btn2.Bind(wx.EVT_BUTTON, self.onButton2)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(btn1)
sizer.Add(btn2)
panel.SetSizer(sizer)
self.maxPercent = 100
self.percent = 0
def onButton1(self, evt):
self.StartThread(self.DoWork1)
def onButton2(self, evt):
self.StartThread(self.DoWork2)
def StartThread(self, func, *args):
thread = threading.Thread(target=func, args=args)
thread.setDaemon(True)
thread.start()
def showProgress(self):
self.progress = wx.ProgressDialog("sum in progress", "please wait", maximum=self.maxPercent, parent=self, style=wx.PD_SMOOTH|wx.PD_AUTO_HIDE)
def destoryProgress(self):
self.progress.Destroy()
def updateProgress(self, percent):
keepGoing = True
time.sleep(1)
while keepGoing and self.percent < percent:
self.percent += 1
(keepGoing, skip) = self.progress.Update(self.percent)
time.sleep(0.1)
def doSomething(self, take_time, taskPercent, say_something):
time.sleep(take_time)
(keepGoing, skip) = self.progress.Update(taskPercent, say_something+" done!")
def DoWork1(self):
self.StartThread(self.showProgress)
taskPercent = 25
self.StartThread(self.updateProgress, taskPercent)
self.doSomething(5, taskPercent, "1st")
taskPercent +=25
self.StartThread(self.updateProgress, taskPercent)
self.doSomething(5, taskPercent, "2nd")
taskPercent +=25
self.StartThread(self.updateProgress, taskPercent)
self.doSomething(5, taskPercent, "3rd")
taskPercent +=25
self.StartThread(self.updateProgress, taskPercent)
self.doSomething(5, taskPercent, "4th")
self.destoryProgress()
def DoWork2(self):
self.StartThread(self.showProgress)
taskPercent = 25
self.doSomething(5, taskPercent, "1st")
taskPercent +=25
self.doSomething(5, taskPercent, "2nd")
taskPercent +=25
self.doSomething(5, taskPercent, "3rd")
taskPercent +=25
self.doSomething(5, taskPercent, "4th")
self.destoryProgress()
if __name__ == '__main__':
app = wx.App(0)
frame = MyFrame()
frame.Show()
app.MainLoop()
答案 1 :(得分:1)
一个可能更简单的选择就是在代码中定期调用wx.Yield()
;这允许GUI刷新/处理输入。当然,没有其他任何东西可以运行,但它确实允许您的进度条正确更新。
进度条可能应该是全局的,或传递给子功能,以便它可以随时更新进度。