Search code examples
pythonwxpython

wxPython: Sizer: Hide/Show object in a column, while shifting other entries


I am trying to create a frame with 3 StaticText entries (in a vertical BoxSizer). When you click on an entry, I want a second StaticText object to appear directly below it (and all other entries below it to shift down).

Right now, I can display the second StaticText when the first is clicked, but I'm missing how to get the second text object underneath the first, without overwriting anything. My code is attached below.

I'd appreciate your help!

import wx

class myFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, 'Hiding t2 properly')
        self.panel = wx.Panel(self, -1)
        self.panel.SetMaxSize((200,-1))
        self.t1s = []
        self.t2s = []
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        for i in xrange(3):
            ## t1 is always visible.
            t1 = wx.StaticText(self.panel, label="t1-"+str(i))
            ## t2 should appear under its respective t1 when t1 is clicked.
            ##(it should also disappear, without leaving blank space, when
            ## t1 is clicked again).
            t2 = wx.StaticText(self.panel, label="t2-"+str(i))
            self.t1s.append(t1)
            self.t2s.append(t2)
            self.sizer.Add(t1, 0, wx.EXPAND)
            self.sizer.Add(t2, 0, wx.EXPAND)
            t1.Bind(wx.EVT_LEFT_UP, lambda evt: self.onClick(evt))
            t2.Hide()
        self.panel.SetSizer(self.sizer)
        self.panel.SetAutoLayout(True)
        self.sizer.Fit(self.panel)

    def onClick(self, evt):
        t1 = evt.GetEventObject()
        i = self.t1s.index(t1)
        t2 = self.t2s[i]

        if t2.IsShown(): ## hide t2 and eliminate empty space
            t2.Hide()
            ## What else goes here?

        else: #show t2
            t2.Show()
            ## What else goes here?


app = wx.App()
frame = myFrame()
frame.Show()
app.MainLoop()

Solution

  • You need to add this line to the code:

    self.panel.Layout()
    

    like this

    def onClick(self, evt):
        t1 = evt.GetEventObject()
        i = self.t1s.index(t1)
        t2 = self.t2s[i]
        if t2.IsShown():
            t2.Hide()
            self.panel.Layout()    
        else:
            t2.Show()
            self.panel.Layout()
    

    This redraws the panel layout and all its components. You can also use the Layout() method of the sizer : self.sizer.Layout()