Interactive panel resizing

I am trying to make a customized fold panel. Say, the default panel height is 100 and by clicking a button in the panel, it goes to 50. This was done easily, but the panel goes back to the default height as a parent panel got refreshed. Please see the example code and further description below.

WHAT I INTENDED

  • Before any button is clicked

._______________________________.
| [ Button 0 ] . . . . . . . . . . . . . . . . . . . . . |
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . (Default height = 100 ) . . . . . |
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| ______________________________ |

._______________________________.
| [ Button 1 ] . . . . . . . . . . . . . . . . . . . . … |
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| ______________________________ |

._______________________________.
| [ Button 2 ] . . . . . . . . . . . . . . . . . . . . . |
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| ______________________________ |

._______________________________.
| [ Button 3 ] . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| ______________________________ |

._______________________________.
| [ Button 4 ] . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| ______________________________ |

  • After ‘Button 1’ is clicked

._______________________________.
| [ Button 0 ] . . . . . . . . . . . . . . . . . . . . . |
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . |
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| ______________________________ |

._______________________________.
| [ Button 1 ] . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . (Folded height = 50). . . . . . .|
| ______________________________ |

._______________________________.
| [ Button 2 ] . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| ______________________________ |

._______________________________.
| [ Button 3 ] . . . . . . . . . . . . . . . . . . . . . |
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| ______________________________ |

._______________________________.
| [ Button 4 ] . . . . . . . . . . . . . . . . . . . . . |
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .|
| ______________________________ |

import wx

class MyFoldPanel(wx.Panel):

    def __init__(self, parent, label):
        wx.Panel.__init__(self, parent, size=(-1, 100))
        self.SetBackgroundColour(wx.Colour(255, 100, 100))
        self.btn = wx.Button(self, label=f"Button {label}")
        self.btn.Bind(wx.EVT_BUTTON, self.onBtn)
        self.parent = parent

    def onBtn(self, event):
        # self.detachAll()
        y = self.GetSize()[1]
        if y == 100:   self.SetSize([-1, 50])
        else:          self.SetSize([-1, 100])
        # self.attachAll()    

    def detachAll(self):
        self.sizer.Clear()

    def attachAll(self):
        for panel in self.panels:
            self.sizer.Add(panel, 0, wx.EXPAND|wx.ALL, 5)

class TestFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None)
        self.panel = wx.Panel(self)
        self.panel.SetBackgroundColour(wx.Colour(100, 100, 200))
        self.sizer = wx.BoxSizer(wx.VERTICAL)

        self.panels = []
        for i in range(5):
            self.panels.append(MyFoldPanel(self.panel, i))
            self.sizer.Add(self.panels[-1], 0, wx.EXPAND|wx.ALL, 5)

        self.panel.SetSizer(self.sizer)

if __name__ == '__main__':
    app = wx.App()
    frame = TestFrame()
    frame.Show()
    app.MainLoop()

As you can see from the code, I also tried cleaning the sizer and adding the widget but it was not helpful. How can I make it work?

Hi,

The size of the panel is changed, but the minimum size (i.e. the best size) is not. You also need to change the minimum size to tell the upstream sizer that is the best. Then do the layout again. Try this:

    def onBtn(self, event):
        # self.detachAll()
        y = self.GetSize()[1]
        if y == 100:   self.SetMinSize([-1, 50])
        else:          self.SetMinSize([-1, 100])
        self.Parent.Layout()
        # self.attachAll()    

I think wx.lib.agw.foldpanelbar.FoldPanelBar will also be of interest to you.

Oh it worked. I know wx already has FoldPanelBar but need a customized one.
Thank you so much!