wxPython 编辑器段错误

3 投票
2 回答
1824 浏览
提问于 2025-04-16 00:45

我创建了一个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()

撰写回答