wxpython wxgrid attributes

838 views Asked by At

I'm having trouble highlighting alternative rows in a grid. Having created the grid and filled it with data, highlighting alternative rows works as expected. But when new data is loaded, I delete all rows, then add new rows as required, and this time grid highlighting raises the exception unhandled TypeError. This has me stumped- any suggestions? The code below produces the same error (click the button twice):-

import wx
import wx.grid as gridlib
app = wx.App()

def highlightrows(event):
   for row in range(0, myGrid.GetNumberRows(), 2):
      if row < myGrid.GetNumberRows():
         myGrid.SetRowAttr(row, attr)
   myGrid.ForceRefresh()
   myGrid.Refresh()

frame = wx.Frame(None, title="Highlight woes")
panel = wx.Panel(frame)
myGrid = gridlib.Grid(panel)
myGrid.CreateGrid(12, 8)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(myGrid, 1, wx.EXPAND)
panel.SetSizer(sizer)

btn = wx.Button(panel,  -1, 'Highlight rows')
sizer.Add(btn)
btn.Bind(wx.EVT_BUTTON, highlightrows)

attr = wx.grid.GridCellAttr()
attr.SetBackgroundColour('#eeeeee')

frame.Show()
app.MainLoop()
3

There are 3 answers

9
Mike Driscoll On

In your example, your GridCellAttr instance has gone out of scope and been deleted by the second time you press the button. I'm surprised it worked the first time, to be honest. When I click the button twice, I get the following error:

TypeError: in method 'Grid_SetRowAttr', expected argument 3 of type 'wxGridCellAttr *'

Digging a bit deeper, if you look at the 3rd argument, you will see that it is the following:

<wx.grid.GridCellAttr; proxy of wxPython wrapper for DELETED GridCellAttr object! (The C++ object no longer exists.) >

Anyway, here's one simple approach that worked every time for me:

import wx
import wx.grid as gridlib

########################################################################
class MyForm(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, parent=None, title="A Simple Grid")
        panel = wx.Panel(self)

        self.myGrid = gridlib.Grid(panel)
        self.myGrid.CreateGrid(12, 8)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.myGrid, 1, wx.EXPAND)

        btn = wx.Button(panel, label='Highlight rows')
        sizer.Add(btn)
        btn.Bind(wx.EVT_BUTTON, self.highlightrows)

        panel.SetSizer(sizer)

    #----------------------------------------------------------------------
    def highlightrows(self, event):
        """"""
        attr = wx.grid.GridCellAttr()
        attr.SetBackgroundColour('#eeeeee')
        for row in range(0, self.myGrid.GetNumberRows(), 2):
            if row < self.myGrid.GetNumberRows():
                self.myGrid.SetRowAttr(row, attr)
        self.myGrid.ForceRefresh()
        self.myGrid.Refresh()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()
1
lawrie On

A bit late but, try this. I had the same problem...

myGrid.SetRowAttr(row, attr.Clone())
0
alex314159 On

Weird - similar issue with code that worked fine in wxPython 2.8. Upon upgrading to 3.0 I had to Clone() the attribute for each row otherwise I would get the type error above:

TypeError: in method 'Grid_SetRowAttr', expected argument 3 of type 'wxGridCellAttr *'

Thanks to Jim and Lawrie for the suggestion. Could this be a bug? Here's my code:

def initialPaint(self):
    wx.lib.colourdb.updateColourDB()
    self.oddLineColour = wx.NamedColour('GAINSBORO')
    oddlineattr = wx.grid.GridCellAttr()
    oddlineattr.SetBackgroundColour(self.oddLineColour)

    for (j, header) in enumerate(self.columnList):
        self.SetColLabelValue(j, header)
        for (i, bond) in enumerate(self.bondList):
            if bond in self.bdm.df.index:
                if i % 2:
                    self.SetRowAttr(i,oddlineattr.Clone())#NOT NEEDED IN 2.8