segfault on ListCtrl.InsertStringItem

Hi,
The crashing line is called before the OnCreate method of the list is
called, so the List is apparently not yet ready to receive items.

The crashing line is part of the OnInit of the main frame with data that
are related to the functionality of my program.

The structure looks like this:
class MainFrame(wx.Frame):
  def __init__(self, res):
    <snip>

  def OnCreate(self, event):
    self.Unbind(wx.EVT_WINDOW_CREATE)
    self.my_list = xrc.XRCCTRL(self, "my_list")
    # self.my_list.OnCreate(None) # Makes it work
    self._init_data()
  
  def _init_data(self):
    <snip>
    self.my_list.InsertStringItem(RowNum, M) # Crash

When I manually call the OnInit of the list before the _init_data(),
everhthing works nicely, but this seems to me a dirty hack.

Is there an elegant way to solve this? I already call the data
initialisation at the very end of the OnCreate method of the frame.

Martijn

P.S. platform is linux/gtk

···

On Thu, 2008-04-03 at 16:31 -0700, Robin Dunn wrote:

Martijn wrote:
> Hi all,
>
> I encounter a segfault in ListCtrl.InsertStringItem()
>
>
> The list control is created from xrc using two phase creation:
>
> The xrc code:
>
> <object class="wxListCtrl" name="my_list"
> subclass="WxEllips.AutoWidthListCtrl">
>
> the python code:
>
> class AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
> def __init__(self):
> Pre = wx.PreListCtrl()
> self.PostCreate(Pre)
> ListCtrlAutoWidthMixin.__init__(self)
> self.Bind(wx.EVT_WINDOW_CREATE, self.OnCreate)
>
> def OnCreate(self, event):
> self.Unbind(wx.EVT_WINDOW_CREATE)
> self.InsertColumn(0, "Column1")
> self.InsertStringItem(0, "Item1") # this works!
> self.InsertStringItem(1, "Item2") # this too
>
>
> self.my_list = xrc.XRCCTRL(self, "my_list")
> self.my_list.InsertStringItem(RowNum, M)
>
> In this last line I get the segfault.
> I checked that the RowNum is a correct number and that M is a string.

I'm not sure if it's possible, but could you check if OnCreate is being
called before the crashing line is? (BTW, which platform?)

This e-mail and its contents are subject to the DISCLAIMER at http://www.tno.nl/disclaimer/email.html

The OnCreate() method of the list consists now only of the line that
adds a column. But when I put this line into __init__ and remove the
call to Oncreate() my application does not run. Why is that?

Martijn

···

On Mon, 2008-04-07 at 10:18 -0700, Robin Dunn wrote:

Martijn wrote:
> Hi,
> The crashing line is called before the OnCreate method of the list is
> called, so the List is apparently not yet ready to receive items.

Ok, that's what I thought. So what you've done is the correct thing to
do since you can't add items to a listctrl until it has columns, and
you're delaying that until the create event.

Martijn Brouwer wrote:

The OnCreate() method of the list consists now only of the line that
adds a column. But when I put this line into __init__ and remove the
call to Oncreate() my application does not run. Why is that?

Please show the code again so I can see what change you've made.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

This code works:

class AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
  def __init__(self):
    Pre = wx.PreListCtrl()
    self.PostCreate(Pre)
    ListCtrlAutoWidthMixin.__init__(self)
    # Useless, running upon creation is too late:
    # self.Bind(wx.EVT_WINDOW_CREATE, self.OnCreate)

  def OnCreate(self, event):
    # self.Unbind(wx.EVT_WINDOW_CREATE) # superfluous
    self.InsertColumn(0, "Materials")

class MainFrame(wx.Frame):
  def __init__(self, res):
    < two phase creation code, using PreFrame + PostCreate>

  def OnCreate(self, event):
    self.Unbind(wx.EVT_WINDOW_CREATE)
    self.material_list = xrc.XRCCTRL(self, "materials_list")
    self.material_list.OnCreate(None)
    self.material_list.InsertStringItem(RowNum, "My item")

In this way, AutoWidthListCtrl.OnCreate is not an event handler anymore,
and does not contain much code anyways. Therefore I tried to move its
code to __init__ and remove its call:

class AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
  def __init__(self):
    Pre = wx.PreListCtrl()
    self.PostCreate(Pre)
    ListCtrlAutoWidthMixin.__init__(self)
    self.InsertColumn(0, "Materials")

class MainFrame(wx.Frame):
  def __init__(self, res):
    < two phase creation code>

  def OnCreate(self, event):
    self.Unbind(wx.EVT_WINDOW_CREATE)
    self.material_list = xrc.XRCCTRL(self, "materials_list")
    self.material_list.InsertStringItem(RowNum, "My item")

With this code I get a segfault in the InsertStringItem line. My first
segfault from python (or the underlying library).

···

On Mon, 2008-04-07 at 18:44 -0700, Robin Dunn wrote:

Martijn Brouwer wrote:
> The OnCreate() method of the list consists now only of the line that
> adds a column. But when I put this line into __init__ and remove the
> call to Oncreate() my application does not run. Why is that?

Please show the code again so I can see what change you've made.