Hi All,

Been coding Python on and off for a year now, but only just started looking at wx. Got a problem in a larger project I'm working on, trying to remove all items from a GridSizer - I've created the following test code to demonstrate the problem, but to summarize:

  • calling .Remove(x) on the last element of the grid returns True but doesn't remove the object from the GUI
  • calling .Clear() doesn't remove any items from the GUI

Anyway, code sample...

import wx

class Test:
  def __init__(self):
    app = wx.App(False)
    frame = wx.Frame(None, wx.ID_ANY, "Test App")
    panel = wx.Panel(frame)
    vboxsizer = wx.BoxSizer(wx.VERTICAL)

    self.grid = wx.GridSizer(rows=0, cols=3)
    b0 = wx.Button(panel, label="Remove Button 0")
    b1 = wx.Button(panel, label="Remove Button 1")
    b2 = wx.Button(panel, label="Remove Button 2")
    b3 = wx.Button(panel, label="Clear Buttons")
    b4 = wx.Button(panel, label="Remove Button 4")
    self.grid.Add(b0)
    self.grid.Add(b1)
    self.grid.Add(b2)
    self.grid.Add(b3)
    self.grid.Add(b4)
    b0.Bind(wx.EVT_BUTTON, self.removeButton0)
    b1.Bind(wx.EVT_BUTTON, self.removeButton1)
    b2.Bind(wx.EVT_BUTTON, self.removeButton2)
    b3.Bind(wx.EVT_BUTTON, self.removeButton3)
    b4.Bind(wx.EVT_BUTTON, self.removeButton4)

    vboxsizer.Add(self.grid, 1, border=2, flag=wx.EXPAND|wx.ALL)

    panel.SetSizer(vboxsizer)

    frame.Show(True)

    app.MainLoop()

  def removeButton0(self,e):
    print self.grid.Remove(0)
    self.grid.Layout()
  def removeButton1(self,e):
    print self.grid.Remove(1)
    self.grid.Layout()
  def removeButton2(self,e):
    print self.grid.Remove(2)
    self.grid.Layout()
  def removeButton3(self,e):
    #print self.grid.Remove(3)
    self.grid.Clear()
    self.grid.Layout()
  def removeButton4(self,e):
    print self.grid.Remove(4)
    self.grid.Layout()


if __name__ == "__main__":
  t = Test()

..Oh and as a side note, I could not for the life of me, make a DirDialog that didn't have a create folder button - even though I set the wx.DD_DIR_MUST_EXIST style.

Development system is Fedora 12/Gnome but final code must be cross-platform.


All help/ideas/explanations appreciated..

Thanks in advance

You should first test that the button is active, as you may be trying to delete a button that doesn't exits. So, a dictionary to store the button makes sense as you can look it up before trying to delete.

import wx
 
class Test:
  def __init__(self):
    app = wx.App(False)
    frame = wx.Frame(None, wx.ID_ANY, "Test App")
    panel = wx.Panel(frame)
    vboxsizer = wx.BoxSizer(wx.VERTICAL)
 
    self.grid = wx.GridSizer(rows=0, cols=3)

    self.button_dict = {}
    for j in range(5):
        b = wx.Button(panel, label="Remove Button %d" % (j), id=j)
        self.grid.Add(b)
        b.Bind(wx.EVT_BUTTON, self.remove_button)
        self.button_dict[j] = b
 
    vboxsizer.Add(self.grid, 1, border=2, flag=wx.EXPAND|wx.ALL)
 
    panel.SetSizer(vboxsizer)
 
    frame.Show(True)
 
    app.MainLoop()
 
  def remove_button(self, e):
      button_num = e.GetId()
      print "ID =", button_num, type(button_num)
      if button_num in self.button_dict:
          self.button_dict[button_num].Hide()
 
if __name__ == "__main__":
  t = Test()

Edited 5 Years Ago by woooee: n/a

Forgive me if I'm mistaken but doesn't the above code 'Hide' buttons rather than removing them? The problem being that they're still in the grid taking up a space..

I would suggest you first try substituting Destroy for Hide, and then check the docs for methods associated with widgets so you can think for yourself and make associations in the future. And mark the thread "Solved".

Please see below code, with Remove substituted for Hide. As expected, when a button is clicked it is no longer visible but the remaining buttons don't rearrange to fill the now empty space...

So.. no, this thread isn't solved just yet..

import wx

class Test:
  def __init__(self):
    app = wx.App(False)
    frame = wx.Frame(None, wx.ID_ANY, "Test App")
    panel = wx.Panel(frame)
    vboxsizer = wx.BoxSizer(wx.VERTICAL)

    self.grid = wx.GridSizer(rows=0, cols=3)
    self.b0 = wx.Button(panel, label="Hide Button 0")
    self.b1 = wx.Button(panel, label="Hide Button 1")
    self.b2 = wx.Button(panel, label="Hide Button 2")
    self.b3 = wx.Button(panel, label="Hide Button 3")
    self.b4 = wx.Button(panel, label="Hide Button 4")
    self.grid.Add(self.b0)
    self.grid.Add(self.b1)
    self.grid.Add(self.b2)
    self.grid.Add(self.b3)
    self.grid.Add(self.b4)
    self.b0.Bind(wx.EVT_BUTTON, self.removeButton0)
    self.b1.Bind(wx.EVT_BUTTON, self.removeButton1)
    self.b2.Bind(wx.EVT_BUTTON, self.removeButton2)
    self.b3.Bind(wx.EVT_BUTTON, self.removeButton3)
    self.b4.Bind(wx.EVT_BUTTON, self.removeButton4)

    vboxsizer.Add(self.grid, 1, border=2, flag=wx.EXPAND|wx.ALL)

    panel.SetSizer(vboxsizer)

    frame.Show(True)

    app.MainLoop()

  def removeButton0(self,e):
    #print self.grid.Remove(0)
    print self.b0.Hide()
    self.grid.Layout()
  def removeButton1(self,e):
    #print self.grid.Remove(1)
    print self.b1.Hide()
    self.grid.Layout()
  def removeButton2(self,e):
    #print self.grid.Remove(2)
    print self.b2.Hide()
    self.grid.Layout()
  def removeButton3(self,e):
    #print self.grid.Remove(3)
    #self.grid.Clear()
    print self.b3.Hide()
    self.grid.Layout()
  def removeButton4(self,e):
    #print self.grid.Remove(4)
    print self.b4.Hide()
    self.grid.Layout()


if __name__ == "__main__":
  t = Test()

Figured it out - for anyone else having the same problem you need Destroy() to remove children from a GridSizer, not Hide or Remove :icon_rolleyes:

This question has already been answered. Start a new discussion instead.