Introduction
Occasionally, when working with wxPython
, you run up against the coding limitations of the provided widgets. For instance, in the wx.Gauge
widget, color selection isn't customizable. If this is an option you'd like to explore, consider the code snippet below.
Background
My personal frustration began when I wished to indicate the progress of a process and also indicate if the process was encountering an error or was working as expected. Also, the behavior of wx.Gauge
differed somewhat when viewed under Linux and when viewed under Windows. After fruitless searches of the internet for a solution, I came up with the "bright" idea that I could write my own progress bar widget. Surprisingly, this ended up being a very simple task.
Using the Code
The simplest approach to using this progress bar is to cut and paste the code snippet into your pre-existing wxPython
code. If you are interested in experimenting with a crude wxPython
application, I am including a very basic GUI interface for your perusal. Please modify the code as necessary to fit your requirements.
########################################################
#
# A simple color-selectable Progress Bar widget
#
# Member functions are as follows:
#
# __init__(self,parent,id,position(0,0),size=(20,100),progress)
#
# SetProgress(self,progress,errorflag)
#
# Sets the progress from 0 to 100 as a percentage, if error
# is non-zero, the progress bar changes from a defined
# normal color to a defined error color
#
# SetBGColor(self,color)
#
# Sets the background color of the progress bar.
#
# SetProgColor(self,color)
#
# Sets the color that the progress bar will normally be
# displayed.
#
# SetErrColor(self,color)
#
# Sets the color of the progress bar when an error occurs.
#
# GetProgress(self)
#
# Returns the current progress value from the progress
# bar widget.
#
########################################################
class MyProgBar(wx.Panel):
def __init__(self,parent,id=-1, position=(0,0),size=(20,100),prog=50):
self.myWidth = size[0]
self.myHeight = size[1]
self.myprogress = 0
self.myerror = 0
self.BasePanel = wx.Panel(parent,id,position,size,wx.BORDER)
self.ProgPanel = wx.Panel(self.BasePanel,-1,(0,0),(1,self.myHeight))
self.bgcolor = wx.WHITE
self.progcolor = wx.GREEN
self.errcolor = wx.RED
self.BasePanel.SetBackgroundColour(self.bgcolor)
self.SetProgress(0)
def SetProgress(self,prog=50,error=0):
width = self.myWidth*prog/100
self.myerror = error
if(prog<0):
prog = 0
if(prog>100):
prog = 100
self.myprogress = prog
width = self.myWidth*prog/100
if(width<1):
width = 1
if(error):
self.ProgPanel.SetBackgroundColour(self.errcolor)
else:
self.ProgPanel.SetBackgroundColour(self.progcolor)
self.ProgPanel.SetSize((0,0))
self.ProgPanel.SetSize((width,self.myHeight))
def SetBGColor(self,color=wx.WHITE):
self.bgcolor = color
self.BasePanel.SetBackgroundColour(color)
def SetProgColor(self,color=wx.GREEN):
self.progcolor = color
self.ProgPanel.SetBackgroundColour(color)
def SetErrColor(self,color=wx.RED):
self.errcolor = color
def GetProgress(self):
return self.myprogress
Using the widget is quite simple. You can attach it to a pre-existing wx.Panel
as shown below. The background color, progress bar color, and error color can be customized here as well. Theoretically, the colors can be changed any time you feel the need, but that is beyond the scope of this tip. Have at!
Use in your initializer as follows:
...
self.panel = wx.Panel(parent,id,(0,0),(500,500))
self.progress = wx.MyProgBar(self.panel,-1,(50,50),(128,20))
self.progress.SetBGColor(wx.WHITE)
self.progress.SetProgColor(wx.GREEN)
self.progress.SetErrColor(wx.RED)
...
Use the progress bar as follows:
self.progress.SetProgress(50) # Sets progress to 50%
..or..
self.progress.SetProgress(99,1) #sets progress to 99& but indicates an error.
Points of Interest
Essentially, this progress bar consists of two cascaded panels. A background panel called BasePanel
, and a progress panel (the thing which indicates the progress), which is a child of the background panel. Panels can have their colors set at any time, so that's what is being done here. Sizing the progress panel had one gotcha to it. The panel had to be pre-sized to zero width to clear out the previously painted panel before setting the new size of the progress bar. This can be seen in the code snippet below:
self.ProgPanel.SetSize((0,0))
self.ProgPanel.SetSize((width,self.myHeight))
History
- Version 1.0: Wednesday, October 16, 2013
- Version 1.1: Thursday, October 17, 2013