wxPython 编辑器段错误
我创建了一个wx.grid.Grid,并用一个从wx.grid.PyGridTableBase派生的类来提供数据。我还想控制表格中使用的编辑器。为此,我定义了以下方法:
def GetAttr(self, row, col, kind):
attr = wx.grid.GridCellAttr()
if col == 0:
attr.SetEditor( wx.grid.GridCellChoiceEditor() )
return attr
但是,每当我尝试在网格中创建编辑器时,就会出现段错误(segmentation fault)。我也试过提前创建编辑器并作为参数传入,但收到了以下错误:
TypeError: in method 'GridCellAttr_SetEditor', expected argument 2 of type
'wxGridCellEditor *'
我怀疑第二个错误是因为GridCellAttr接管了我的编辑器的所有权,然后把它销毁了。
我还尝试在wx.grid.Grid上使用SetDefaultEditor方法,这样是可以的,但自然就不能实现针对特定列的编辑策略了。
查看崩溃程序的完整示例: http://pastebin.com/SEbhvaKf
2 个回答
0
这应该能解决问题:
import wx
import wx.grid as gridlib
然后改成:
def GetAttr(self, row, col, kind):
attr = gridlib.GridCellAttr()
if col == 0:
attr.SetEditor( gridlib.GridCellChoiceEditor() )
return attr
注意:我不知道为什么你需要这样做,因为:
>>> import wx
>>> attr = wx.grid.GridCellAttr()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'grid'
这个不行,但是:
import wx.grid as gridlib
attr = gridlib.GridCellAttr()
这个可以...不过:
print attr
<wx.grid.GridCellAttr; proxy of <wx.grid.GridCellAttr; proxy of <Swig Object of type 'wxGridCellAttr *' at 0x97cb398> > >
它显示:<wx.grid.GridCellAttr; proxy of <wx.grid.GridCellAttr>...>
!
注意2:如果你在整个0列上使用ChoiceEditor,你也可以在显示网格之前只定义一次,方法是:
attr.SetEditor( gridlib.GridCellChoiceEditor() )
yourGrid.SetColAttr(0, attr)
这样你就可以把GetAttr方法里的所有代码都去掉(我觉得这样会更快,不过我从来没有计时过)。
4
我找到了问题所在:
wxWidgets的代码假设每次从GetCellAttr获取到的编辑器都是一样的。如果每次返回不同的编辑器,就像我之前那样,会导致程序崩溃。
为了多次返回同一个编辑器,我还需要调用IncRef()来保持这个编辑器的有效性。
如果将来还有其他人遇到同样的问题,可以参考我的工作代码:
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()