Removing widgets

I have been struggling with this for a while now. I have created a simple GUI,
this is what I am trying to achieve.

When the user clicks "Buttons 1", 3 buttons, "A", "B" and "C" appear to the
left. When the user clicks "Buttons 2", those 3 buttons are removed and
replaced with buttons "C", "D" and "E".

I've tried everything I can think of but I don't seem to able to successfully
remove the old buttons before sticking the new ones in. Can anyone help?

I am running python version 2.4.2 on Ubuntu Linux (Breezy), the code is below:

#!/usr/bin/python

import wx

class Example(wx.Panel):
  
      def __init__(self, parent):
    
    wx.Panel.__init__(self, parent)
    
    topsizer = wx.BoxSizer(wx.VERTICAL)
    
    title = wx.StaticText(self, -1, "Example")
    
    topsizer.Add(title, 0, wx.ALIGN_CENTER_HORIZONTAL)
    
    lefttorightsizer = wx.BoxSizer(wx.HORIZONTAL)
    
    leftsizer = wx.BoxSizer(wx.VERTICAL)
    
    typelabel = wx.StaticText(self, -1, "Buttons: ")
    leftsizer.Add(typelabel, 0, wx.ALIGN_LEFT)
    self.typesizer = wx.BoxSizer(wx.VERTICAL)
    leftsizer.Add(self.typesizer, 1, wx.EXPAND)
    
    lefttorightsizer.Add(leftsizer, 2, wx.EXPAND)
    
    rightsizer = wx.BoxSizer(wx.VERTICAL)
    
    receiptbuttonssizer = wx.BoxSizer(wx.VERTICAL)
    
    buttons1button = wx.Button(self, -1, "Buttons 1")
    buttons1button.Bind(wx.EVT_BUTTON, self.Buttons1)
    receiptbuttonssizer.Add(buttons1button, 1, wx.EXPAND)
    
    buttons2button = wx.Button(self, -2, "Buttons 2")
    buttons2button.Bind(wx.EVT_BUTTON, self.Buttons2)
    receiptbuttonssizer.Add(buttons2button, 1, wx.EXPAND)
    
    rightsizer.Add(receiptbuttonssizer, 0, wx.EXPAND)
    
    lefttorightsizer.Add(rightsizer, 1, wx.EXPAND)
    
    topsizer.Add(lefttorightsizer, 1, wx.EXPAND)
    
    self.SetSizer(topsizer)
  
  def Buttons1(self, ID):
    
    frame = ID.GetEventObject().GetGrandParent()
    
    parent = ID.GetEventObject().GetParent()
    
    #typechildren = self.typesizer.GetChildren()
    
    #print "typechildren = " + str(typechildren)
    
    while len(self.typesizer.GetChildren()) > 1:
      
      self.typesizer.GetChildren()[0].Destroy()
      #self.typesizer.Remove(0)
    
    typesizer = wx.BoxSizer(wx.HORIZONTAL)
    
    self.abutton = wx.Button(self, -1, "A")
    typesizer.Add(self.abutton, 1, wx.EXPAND)
    
    self.bbutton = wx.Button(self, -1, "B")
    typesizer.Add(self.bbutton, 1, wx.EXPAND)
    
    self.cbutton = wx.Button(self, -1, "C")
    typesizer.Add(self.cbutton, 1, wx.EXPAND)
    
    self.typesizer.Add(typesizer, 1, 1, wx.EXPAND)
    
    self.Layout()
  
  def Buttons2(self, ID):
    
    frame = ID.GetEventObject().GetGrandParent()
    
    parent = ID.GetEventObject().GetParent()
    
    typechildren = self.typesizer.GetChildren()
    
    print "typechildren = " + str(typechildren)
    
    while len(typechildren) > 1:
      
      widget = self.typesizer.GetChildren()[0]
      self.typesizer.Remove(0)
      #print "Widget Removed"
      widget.Destroy()
      #print "Widget Destroyed"
    
    typesizer = wx.BoxSizer(wx.HORIZONTAL)
    
    self.dbutton = wx.Button(self, -1, "D")
    typesizer.Add(self.dbutton, 1, wx.EXPAND)
    
    self.ebutton = wx.Button(self, -1, "E")
    typesizer.Add(self.ebutton, 1, wx.EXPAND)
    
    self.fbutton = wx.Button(self, -1, "F")
    typesizer.Add(self.fbutton, 1, wx.EXPAND)
    
    self.typesizer.Add(typesizer, 1, 1, wx.EXPAND)
    
    self.Layout()

app = wx.App()

frame = wx.Frame(None, -1, "My Frame")

frame.Show()

Example(frame)

app.MainLoop()

Hope you can help

Adam.

Why must you replace the buttons

You can set the Label with self.btn1.SetLabel('D')

When you have events with this button you can get the Label
(self.btn1.GetLabel()) and with if lbl = 'A':
    Pass
Elif lbl = 'D':
    Pass

Etc. :wink:

···

-----Ursprüngliche Nachricht-----
Von: Adam Spencer [mailto:doctorwebbox@dsl.pipex.com]
Gesendet: Sonntag, 6. August 2006 12:34
An: wxpython-users@lists.wxwidgets.org
Betreff: [wxPython-users] Removing widgets

I have been struggling with this for a while now. I have created a simple
GUI,
this is what I am trying to achieve.

When the user clicks "Buttons 1", 3 buttons, "A", "B" and "C" appear to the
left. When the user clicks "Buttons 2", those 3 buttons are removed and
replaced with buttons "C", "D" and "E".

I've tried everything I can think of but I don't seem to able to
successfully
remove the old buttons before sticking the new ones in. Can anyone help?

I am running python version 2.4.2 on Ubuntu Linux (Breezy), the code is
below:

#!/usr/bin/python

import wx

class Example(wx.Panel):
  
      def __init__(self, parent):
    
    wx.Panel.__init__(self, parent)
    
    topsizer = wx.BoxSizer(wx.VERTICAL)
    
    title = wx.StaticText(self, -1, "Example")
    
    topsizer.Add(title, 0, wx.ALIGN_CENTER_HORIZONTAL)
    
    lefttorightsizer = wx.BoxSizer(wx.HORIZONTAL)
    
    leftsizer = wx.BoxSizer(wx.VERTICAL)
    
    typelabel = wx.StaticText(self, -1, "Buttons: ")
    leftsizer.Add(typelabel, 0, wx.ALIGN_LEFT)
    self.typesizer = wx.BoxSizer(wx.VERTICAL)
    leftsizer.Add(self.typesizer, 1, wx.EXPAND)
    
    lefttorightsizer.Add(leftsizer, 2, wx.EXPAND)
    
    rightsizer = wx.BoxSizer(wx.VERTICAL)
    
    receiptbuttonssizer = wx.BoxSizer(wx.VERTICAL)
    
    buttons1button = wx.Button(self, -1, "Buttons 1")
    buttons1button.Bind(wx.EVT_BUTTON, self.Buttons1)
    receiptbuttonssizer.Add(buttons1button, 1, wx.EXPAND)
    
    buttons2button = wx.Button(self, -2, "Buttons 2")
    buttons2button.Bind(wx.EVT_BUTTON, self.Buttons2)
    receiptbuttonssizer.Add(buttons2button, 1, wx.EXPAND)
    
    rightsizer.Add(receiptbuttonssizer, 0, wx.EXPAND)
    
    lefttorightsizer.Add(rightsizer, 1, wx.EXPAND)
    
    topsizer.Add(lefttorightsizer, 1, wx.EXPAND)
    
    self.SetSizer(topsizer)
  
  def Buttons1(self, ID):
    
    frame = ID.GetEventObject().GetGrandParent()
    
    parent = ID.GetEventObject().GetParent()
    
    #typechildren = self.typesizer.GetChildren()
    
    #print "typechildren = " + str(typechildren)
    
    while len(self.typesizer.GetChildren()) > 1:
      
      self.typesizer.GetChildren()[0].Destroy()
      #self.typesizer.Remove(0)
    
    typesizer = wx.BoxSizer(wx.HORIZONTAL)
    
    self.abutton = wx.Button(self, -1, "A")
    typesizer.Add(self.abutton, 1, wx.EXPAND)
    
    self.bbutton = wx.Button(self, -1, "B")
    typesizer.Add(self.bbutton, 1, wx.EXPAND)
    
    self.cbutton = wx.Button(self, -1, "C")
    typesizer.Add(self.cbutton, 1, wx.EXPAND)
    
    self.typesizer.Add(typesizer, 1, 1, wx.EXPAND)
    
    self.Layout()
  
  def Buttons2(self, ID):
    
    frame = ID.GetEventObject().GetGrandParent()
    
    parent = ID.GetEventObject().GetParent()
    
    typechildren = self.typesizer.GetChildren()
    
    print "typechildren = " + str(typechildren)
    
    while len(typechildren) > 1:
      
      widget = self.typesizer.GetChildren()[0]
      self.typesizer.Remove(0)
      #print "Widget Removed"
      widget.Destroy()
      #print "Widget Destroyed"
    
    typesizer = wx.BoxSizer(wx.HORIZONTAL)
    
    self.dbutton = wx.Button(self, -1, "D")
    typesizer.Add(self.dbutton, 1, wx.EXPAND)
    
    self.ebutton = wx.Button(self, -1, "E")
    typesizer.Add(self.ebutton, 1, wx.EXPAND)
    
    self.fbutton = wx.Button(self, -1, "F")
    typesizer.Add(self.fbutton, 1, wx.EXPAND)
    
    self.typesizer.Add(typesizer, 1, 1, wx.EXPAND)
    
    self.Layout()

app = wx.App()

frame = wx.Frame(None, -1, "My Frame")

frame.Show()

Example(frame)

app.MainLoop()

Hope you can help

Adam.

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Adam Spencer wrote:

I have been struggling with this for a while now. I have created a simple GUI, this is what I am trying to achieve.

When the user clicks "Buttons 1", 3 buttons, "A", "B" and "C" appear to the left. When the user clicks "Buttons 2", those 3 buttons are removed and replaced with buttons "C", "D" and "E".

I've tried everything I can think of but I don't seem to able to successfully remove the old buttons before sticking the new ones in. Can anyone help?

I am running python version 2.4.2 on Ubuntu Linux (Breezy), the code is below:

  def Buttons2(self, ID):
    
    frame = ID.GetEventObject().GetGrandParent()
    
    parent = ID.GetEventObject().GetParent()
    
    typechildren = self.typesizer.GetChildren()
    
    print "typechildren = " + str(typechildren)
    
    while len(typechildren) > 1:
      
      widget = self.typesizer.GetChildren()[0]
      self.typesizer.Remove(0)
      #print "Widget Removed"
      widget.Destroy()
      #print "Widget Destroyed"

You seem to be assuming that self.typesizer.GetChildren will give you with widgets contained in the sizer. But the only child of self.typesizer is the sizer created in Buttons1(), so that is all you will get back in the GetChildren list. So you need to get the children of that sizer and deal with them. Be aware however that the items returned by GetChildren are not the widgets themselves, but instances of a wx.SizerItem class that can hold either a sizer, a widget, or a spacer. It has methods that will help you determine what it is holding, and to get access to it.

On the other hand, since it appears that you just want to remove and destroy everything in self.typesizer, then you can do it like this:

         self.typesizer.Clear(True)

···

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

Adam Spencer wrote:

I have been struggling with this for a while now. I have created a simple GUI, this is what I am trying to achieve.

A few comments:

1) Thanks for posting a complete runnable sample -- that's the best way to get help here. However, next time send it as an enclosure, rather than inline in the email -- emails clients have a way of messing up whitespace, etc.

2) one of you IDs was specified as -2, which isn't valid -- weird. However, that's why I like to use: wx.ID_ANY rather than -1. Or better yet, use keyword arguments, and you can leave off the ID parameter altogether:

wx.Button(self, label="Buttons 1")

A few more comments as I go through the code:

    frame = ID.GetEventObject().GetGrandParent()
This is fragile: what if you re-factor the code and put another panel between here and the frame? You can use wx.GetTopLevelParent(self), or, better yet, keep track of your frame and/or data in a different way.

In: Buttons1, you've got:

typesizer and self.typesizer -- I think there is some confusion here.

Buttons1 is used as a handler - it will get called with an event as a parameter, not an ID. You seem to be using it correctly, but calling it "ID" is pretty confusing

The key issue:

You can hide and show stuff in a sizer by putting all the objects you want in it, then hide() the ones you don't' want. So I'd create the buttons first, then just call show() and Hide as you need in the handlers. You can add all the button to self.typesizer in __init__, then show them later.

I've enclosed a working version

I also took the liberty of cleaning up some style issues, and using a loop to create the buttons -- I subscribe heartily to the DRY (don't Repeat Yourself) principle. If you find yourself writing a bunch of lines of code that are almost identical -- you can probably automate it somehow.

If this were me, I'd probably put the buttons on a wx.Panel, you'd hove one panel for each set of three button, then you could just Show() and Hide() that panel.

-Chris

junk.py (2.61 KB)

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov