'How to avoid stopping the wx.Gauge progress with python when the program takes time?
My program uses a recursive function that takes a few seconds. This function is used several times in a loop. I want to show the progress of the loop with a gauge. But after a few passes through the loop, the gauge freezes and the program seems to stop working: "don't answer" appears in the title while the program is really running. Once the main loop is finished, the gauge fills up to 100% at once.
import wx
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title=title, size=(300, 200))
self.InitUI()
def InitUI(self):
self.count = 0
pnl = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
self.gauge = wx.Gauge(pnl, range=20, size=(250, 25), style=wx.GA_HORIZONTAL)
self.btn1 = wx.Button(pnl, label="Start")
self.Bind(wx.EVT_BUTTON, self.OnStart, self.btn1)
hbox1.Add(self.gauge, proportion=1, flag=wx.ALIGN_CENTRE)
hbox2.Add(self.btn1, proportion=1, flag=wx.RIGHT, border=10)
vbox.Add((0, 30))
vbox.Add(hbox1, flag=wx.ALIGN_CENTRE)
vbox.Add((0, 20))
vbox.Add(hbox2, proportion=1, flag=wx.ALIGN_CENTRE)
pnl.SetSizer(vbox)
self.SetSize((300, 200))
self.Centre()
self.Show(True)
def Recursive(self, param1, param2):
for i in range(1000): # complex work simulated by for loop in my recursive function
print(i)
# list1 is modified in my function
return
def OnStart(self, e):
nb_elements = 150
for n in range(nb_elements):
list1 = []
list2 = []
self.Recursive(list1, list2)
self.gauge.SetValue(int((n/nb_elements)*100))
ex = wx.App()
Mywin(None, 'wx.Gauge')
ex.MainLoop()
Solution 1:[1]
First be careful with that range value on the gauge.
Use wx.GetApp().Yield() to momentarily pass control back to the main loop, so the update to the gauge can occur.
If you don't want to unnecessarily pass back control, moderate the yields by only yielding occasionally.
Here I do that with divmod.
import wx
import time
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title=title, size=(300, 200))
self.InitUI()
def InitUI(self):
self.count = 0
pnl = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
self.gauge = wx.Gauge(pnl, range=1000, size=(250, 25), style=wx.GA_HORIZONTAL)
self.btn1 = wx.Button(pnl, label="Start")
self.Bind(wx.EVT_BUTTON, self.OnStart, self.btn1)
hbox1.Add(self.gauge, proportion=1, flag=wx.ALIGN_CENTRE)
hbox2.Add(self.btn1, proportion=1, flag=wx.RIGHT, border=10)
vbox.Add((0, 30))
vbox.Add(hbox1, flag=wx.ALIGN_CENTRE)
vbox.Add((0, 20))
vbox.Add(hbox2, proportion=1, flag=wx.ALIGN_CENTRE)
pnl.SetSizer(vbox)
self.SetSize((300, 200))
self.Centre()
self.Show(True)
def Recursive(self, param1, param2):
for i in range(1000): # complex work simulated by for loop in my recursive function
time.sleep(0.001)
quo,rem = divmod(i,50)
if rem == 0:
self.gauge.SetValue(i)
wx.GetApp().Yield()
# list1 is modified in my function
return
def OnStart(self, e):
nb_elements = 10
for n in range(nb_elements):
list1 = []
list2 = []
self.Recursive(list1, list2)
print("Finished")
ex = wx.App()
Mywin(None, 'wx.Gauge')
ex.MainLoop()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Rolf of Saxony |
