ProgressCellRenderer – Gauges for Grid Cells

Here’s another quickie I came up with for Grid controls – a ProgressCellRenderer.  Will take a value in a cell and convert it to a progress gauge background in the cell.  Also does a little formatting to add a % sign at the end of the value if it doesn’t have it.  Useful for read-only cells that are updated from another data source or calculation, but can be manually edited also.

# ProgressCellRenderer -- Takes a cell value
# and renders the background of it like a progress gauge
 
import wx
import wx.grid
 
class ProgressCellRenderer(wx.grid.PyGridCellRenderer):
    def __init__(self):
        wx.grid.PyGridCellRenderer.__init__(self)
        self.progColor = wx.Colour(124, 252, 0)
    # end __init__
 
    def Draw(self, grid, attr, dc, rect, row, col, isSelected):
        text = grid.GetCellValue(row, col)
        test_string = text.replace('%','')
        if test_string.strip() == '':
            prog = 0
        else:
            prog = int(test_string.strip())
 
        if prog > 100:
            prog = 100
 
        total_width = rect.width
        units = int( float(prog / 100.0) * rect.width)
 
        prog_rect = wx.Rect(rect.x, rect.y, units, rect.height)
        other_rect = wx.Rect(rect.x + units, rect.y, rect.width - prog_rect.width, rect.height)
        if text.find('%') == -1:
            text = text + "%"
 
        hAlign, vAlign = attr.GetAlignment()
 
        dc.SetFont( attr.GetFont() )
 
        if isSelected:
            bg = grid.GetSelectionBackground()
            fg = grid.GetSelectionForeground()
        else:
            bg = wx.Colour(255,255,255)
 
        dc.SetBrush(wx.Brush(self.progColor, wx.SOLID))
        dc.SetPen(wx.BLACK_PEN)
        dc.DrawRectangleRect(prog_rect)
 
        # This fills in the rest of the cell background
        # so it doesn't shear
        dc.SetBrush(wx.Brush(bg, wx.SOLID))
        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.DrawRectangleRect(other_rect)
 
        grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign)
    # end Draw
 
    def GetBestSize(self, grid, attr, dc, row, col):
        text = grid.GetCellValue(row, col)
        dc.SetFont( attr.GetFont() )
        w, h = dc.GetTextExtent(text)
        return wx.Size(w, h)
 
    def Clone(self):
        return ProgressCellRenderer()
#end of class
 
class TestFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Progress Renderer", size=(640,480))
 
        grid = wx.grid.Grid(self)
 
        grid.CreateGrid(101,2)
 
        attr = wx.grid.GridCellAttr()
        attr.SetRenderer(ProgressCellRenderer())
        grid.SetColAttr(0, attr)
        testFont = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "Tahoma")
 
        for row in range(101):
            grid.SetCellValue(row, 0, "%d%%" % row)
            grid.SetCellAlignment(row, 0, wx.ALIGN_CENTER, wx.ALIGN_CENTER)
            grid.SetCellFont(row, 0, testFont)
 
if __name__ == '__main__':
    app = wx.PySimpleApp()
    frame = TestFrame()
    frame.Show()
    app.MainLoop()

Here’s a screenshot:

ProgressCellRenderer in action

ProgressCellRenderer in action

One thought on “ProgressCellRenderer – Gauges for Grid Cells

  1. Hey, thanks for making this available. It was invaluable when I was trying to write my own custom cell renderer.

Comments are closed.

%d bloggers like this: