Creating a custom renderer

To create your own custom cell renderer, create a subclass of wx.grid.PyGridCell-Renderer—as with other wxPython classes, the Py version of the class allows for a Python class to subclass the base C++ class and properly reflect virtual method

Wxpython Grid Image Cells
Figure 14.6 A custom grid renderer, setting background colors

calls to the Python methods. Creating a custom cell renderer allows you to do things like display a numerical value as a mini-bar graph or perform special formatting on a string or date.

Figure 14.6 displays a sample custom renderer that randomly draws a background color for the cell. The renderer is set for a specific row. You'll notice if you execute the code that the grid will flicker on redraw, as it reassigns the random color.

Listing 14.7 lists the code used to create the custom renderer, displaying the overridden renderer class and the overridden methods.

Listing 14.7 The code for a custom grid renderer that changes color randomly import wx import wx.grid import random class RandomBackgroundRenderer(wx.grid.PyGridCellRenderer):

wx.grid.PyGridCellRenderer.__init__(self)

def Draw(self, grid, attr, dc, rect, row, col, isSelected) text = grid.GetCellValue(row, col) hAlign, vAlign = attr.GetAlignment() dc.SetFont( attr.GetFont() ) if isSelected:

bg = grid.GetSelectionBackground() fg = grid.GetSelectionForeground() else:

bg = random.choice(["pink", "sky blue", "cyan",

"yellow", "plum"]) fg = attr.GetTextColour()

Defining the renderer

What to draw dc.SetTextBackground(bg) dc.SetTextForeground(fg)

dc.SetBrush(wx.Brush(bg, wx.SOLID))

dc.SetPen(wx.TRANSPARENT_PEN)

dc.DrawRectangleRect(rect)

grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign)

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 RandomBackgroundRenderer()

class TestFrame(wx.Frame):

wx.Frame._init_(self, None, title="Grid Renderer"

grid = wx.grid.Grid(self) grid.CreateGrid(50,50)

attr = wx.grid.GridCellAttr()

attr.SetRenderer(RandomBackgroundRenderer()) grid_SetRowAttr(4, attr) <-| Assigning t0 row 4

for row in range(10):

for col in range(10):

grid.SetCellValue(row, col,

app = wx.PySimpleApp() frame = TestFrame() frame.Show() app.MainLoop()

Your renderer class must override three methods of the base class.

The most important of these methods is Draw(grid, attr, dc, rect, row, col, isSelected) . The arguments to this method provide information about the grid that you will need to draw the cell. The grid argument is the grid instance containing this cell. The attr argument contains the grid attribute instance with the foreground and background color, among others. The dc argument is the device context to draw to if you need to use primitive drawing methods. The rect is the bounding rectangle of the cell in logical coordinates. The grid coordinates of the cell are given by the row and col elements, and isSelected is True if the cell is currently selected. Within your draw method, you are free to do whatever you want. You may find it convenient to call the super method of the base class, which draws the background color from the attr parameter and sets the foreground color and text font.

The second method to override is GetBestSize(grid, attr, dc, row, col). This method returns a wx.Size instance that represents the preferred size of the cell for that data, the size of which you can calculate on your own. The grid, attr, dc, row, and col attributes are defined exactly as they are in the Draw() method.

Finally, you should override the method Clone(), that returns a wx.grid.Grid-CellRenderer instance, which should be equal to the instance being called. Once the renderer is defined, you can use it just like the predefined renderer, by setting it as the renderer for specific cells.

Was this article helpful?

+2 -3

Post a comment