Progress gauge in status bar, using Cody Precord's ProgressStatusBar
- by MCXXIII
Hi. I am attempting to create a progress gauge in the status bar for my application, and I'm using the example in Cody Precord's wxPython 2.8 Application Development Cookbook. I've reproduced it below.
For now I simply wish to show the gauge and have it pulse when the application is busy, so I assume I need to use the Start/StopBusy() methods. Problem is, none of it seems to work, and the book doesn't provide an example of how to use the class.
In the __init__ of my frame I create my status bar like so:
self.statbar = status.ProgressStatusBar( self )
self.SetStatusBar( self.statbar )
Then, in the function which does all the work, I have tried things like:
self.GetStatusBar().SetRange( 100 )
self.GetStatusBar().SetProgress( 0 )
self.GetStatusBar().StartBusy()
self.GetStatusBar().Run()
# work done here
self.GetStatusBar().StopBusy()
And several combinations and permutations of those commands, but nothing happens, no gauge is ever shown. The work takes several seconds, so it's not because the gauge simply disappears again too quickly for me to notice.
I can get the gauge to show up by removing the self.prog.Hide() line from Precord's __init__ but it still doesn't pulse and simply disappears never to return once work has finished the first time.
Here's Precord's class:
class ProgressStatusBar( wx.StatusBar ):
'''Custom StatusBar with a built-in progress bar'''
def __init__( self, parent, id_=wx.ID_ANY,
style=wx.SB_FLAT, name='ProgressStatusBar' ):
super( ProgressStatusBar, self ).__init__( parent, id_, style, name )
self._changed = False
self.busy = False
self.timer = wx.Timer( self )
self.prog = wx.Gauge( self, style=wx.GA_HORIZONTAL )
self.prog.Hide()
self.SetFieldsCount( 2 )
self.SetStatusWidths( [-1, 155] )
self.Bind( wx.EVT_IDLE, lambda evt: self.__Reposition() )
self.Bind( wx.EVT_TIMER, self.OnTimer )
self.Bind( wx.EVT_SIZE, self.OnSize )
def __del__( self ):
if self.timer.IsRunning():
self.timer.Stop()
def __Reposition( self ):
'''Repositions the gauge as necessary'''
if self._changed:
lfield = self.GetFieldsCount() - 1
rect = self.GetFieldRect( lfield )
prog_pos = (rect.x + 2, rect.y + 2)
self.prog.SetPosition( prog_pos )
prog_size = (rect.width - 8, rect.height - 4)
self.prog.SetSize( prog_size )
self._changed = False
def OnSize( self, evt ):
self._changed = True
self.__Reposition()
evt.Skip()
def OnTimer( self, evt ):
if not self.prog.IsShown():
self.timer.Stop()
if self.busy:
self.prog.Pulse()
def Run( self, rate=100 ):
if not self.timer.IsRunning():
self.timer.Start( rate )
def GetProgress( self ):
return self.prog.GetValue()
def SetProgress( self, val ):
if not self.prog.IsShown():
self.ShowProgress( True )
if val == self.prog.GetRange():
self.prog.SetValue( 0 )
self.ShowProgress( False )
else:
self.prog.SetValue( val )
def SetRange( self, val ):
if val != self.prog.GetRange():
self.prog.SetRange( val )
def ShowProgress( self, show=True ):
self.__Reposition()
self.prog.Show( show )
def StartBusy( self, rate=100 ):
self.busy = True
self.__Reposition()
self.ShowProgress( True )
if not self.timer.IsRunning():
self.timer.Start( rate )
def StopBusy( self ):
self.timer.Stop()
self.ShowProgress( False )
self.prog.SetValue( 0 )
self.busy = False
def IsBusy( self ):
return self.busy