Python – wxPython segfault for the editor

wxPython segfault for the editor… here is a solution to the problem.

wxPython segfault for the editor

I’ve created a wx.grid.Grid

with the wx.grid.PyGridTableBase derived class to provide its data. I also want to control the editor used on the table. To do this, I define the following methods

def GetAttr(self, row, col, kind):
    attr = wx.grid.GridCellAttr()
    if col == 0:
        attr. SetEditor( wx.grid.GridCellChoiceEditor() )
    return attr

However, whenever I try to create an editor in the grid, this results in a segfault. I did try creating the editor beforehand and passing it as a parameter but getting an error :

    TypeError: in method 'GridCellAttr_SetEditor', expected argument 2 of type 
'wxGridCellEditor *'

I suspect the second error was caused by GridCellAttr taking ownership and then destroying my editor.

I’ve also tried using the SetDefaultEditor method on wx.grid.Grid and it works, but naturally doesn’t allow me to have column-specific editing strategies.

See a full example of a crashing program: http://pastebin.com/SEbhvaKf

Solution

I found the problem :

The wxWidgets code assumes that the same editor will always return from GetCellAttr. Each return to a different editor results in a segfault.

In order to return to the same editor multiple times, I also need to call IncRef() on the editor to keep it in the event state.

For others who encounter the same issue later, see my working code:

import wx.grid 

app = wx. PySimpleApp()

class Source(wx.grid.PyGridTableBase):
    def __init__(self):
        super(Source, self).__init__()
        self._editor = wx.grid.GridCellChoiceEditor()

def IsEmptyCell(self, row, col):
        return False

def GetValue(self, row, col):
        return repr( (row, col) )

def SetValue(self, row, col, value):
        pass

def GetNumberRows(self):
        return 5

def GetNumberCols(self):
        return 5

def GetAttr(self, row, col, kind):
        attr = wx.grid.GridCellAttr()
        self._editor. IncRef()
        attr. SetEditor( self._editor )
        return attr

frame = wx. Frame(None)
grid = wx.grid.Grid(frame)
grid. SetTable( Source() )
frame. Show()

.app. MainLoop()

Related Problems and Solutions