How to create a customized collapsible pane (Phoenix)

Keywords : Collapsible pane, Drop down panel, Foldable panel.


Demonstrating :

Tested py3.x, wx4.x and Win10.

Are you ready to use some samples ? ;)

Test, modify, correct, complete, improve and share your discoveries ! (!)


Customized collapsible pane :

First example

img_sample_one.png

   1 # !/usr/bin/env python3
   2 # -*- coding : utf-8 -*-
   3 
   4 #-------------------------------------------------------------------------------
   5 # Name       : sample_one.py
   6 # Purpose    : Simple foldable panels.
   7 #
   8 # Author     : Seaba & Komoto48g
   9 # Link       : https://discuss.wxpython.org/t/interactive-panel-resizing/35557
  10 # Created    : -
  11 # Copyright  : -
  12 # Licence    : -
  13 #-------------------------------------------------------------------------------
  14 
  15 """
  16 
  17 ...
  18 
  19 """
  20 
  21 
  22 #-------------------------------------------------------------------------------
  23 # Import python packages
  24 #-------------------------------------------------------------------------------
  25 import os
  26 import sys
  27 
  28 
  29 #-------------------------------------------------------------------------------
  30 # Import wxPython packages
  31 #-------------------------------------------------------------------------------
  32 import wx
  33 
  34 
  35 #-------------------------------------------------------------------------------
  36 # wxPython version
  37 #-------------------------------------------------------------------------------
  38 print("wxPython version :", wx.VERSION_STRING)
  39 
  40 
  41 #-------------------------------------------------------------------------------
  42 # Path
  43 #-------------------------------------------------------------------------------
  44 app_dir = os.path.split(os.path.abspath(sys.argv[0]))[0]
  45 icon_dir = os.path.join(app_dir, "icons")
  46 
  47 
  48 #-------------------------------------------------------------------------------
  49 # Class
  50 #-------------------------------------------------------------------------------
  51 # class MyFoldPanel
  52 # class MyFrame
  53 # class MyApp
  54 
  55 
  56 #-------------------------------------------------------------------------------
  57 
  58 class MyFoldPanel(wx.Panel):
  59     def __init__(self, parent, label):
  60         wx.Panel.__init__(self, parent, size=(-1, 95))
  61 
  62         self.parent = parent
  63 
  64         self.SetBackgroundColour(wx.Colour(255, 100, 100))
  65 
  66         self.btn = wx.Button(self, label = f"Pane {label}")
  67         self.btn.Bind(wx.EVT_BUTTON, self.OnBtn)
  68 
  69         #-----------------
  70 
  71         colour = self.GetBackgroundColour()
  72         colour.Set(colour.Red(), colour.Green(), colour.Blue(),
  73                    wx.ALPHA_TRANSPARENT)
  74         self.SetBackgroundColour(colour)
  75 
  76         self.btn.SetForegroundColour(self.GetForegroundColour())
  77 
  78     #---------------------------------------------------------------------------
  79 
  80     def OnBtn(self, event):
  81         w, h = self.btn.GetSize()
  82 
  83         y = self.GetSize()[1]
  84         if y == 95:   self.SetMinSize([-1, h])
  85         else:          self.SetMinSize([-1, 95])
  86         self.Parent.Layout()
  87 
  88 
  89     def DetachAll(self):
  90         self.sizer.Clear()
  91 
  92 
  93     def AttachAll(self):
  94         for panel in self.panels:
  95             self.sizer.Add(panel, 0, wx.EXPAND | wx.ALL, 5)
  96 
  97 #-------------------------------------------------------------------------------
  98 
  99 class MyFrame(wx.Frame):
 100     def __init__(self):
 101         wx.Frame.__init__(self, None)
 102 
 103         #------------
 104 
 105         # Simplified init method.
 106         self.SetProperties()
 107 
 108         #------------
 109 
 110         self.panel = wx.Panel(self)
 111         self.panel.SetBackgroundColour(wx.Colour(100, 100, 200))
 112         self.sizer = wx.BoxSizer(wx.VERTICAL)
 113 
 114         self.panels = []
 115         for i in range(5):
 116             self.panels.append(MyFoldPanel(self.panel, i))
 117             self.sizer.Add(self.panels[-1], 0, wx.EXPAND | wx.ALL, 5)
 118 
 119         self.panel.SetSizer(self.sizer)
 120 
 121     #---------------------------------------------------------------------------
 122 
 123     def SetProperties(self):
 124         """
 125         Set the frame properties (title, icon...).
 126         """
 127 
 128         self.SetTitle("Sample_one")
 129 
 130         #------------
 131 
 132         frm_icon = wx.Icon(os.path.join(icon_dir,
 133                                         "wxwin.ico"),
 134                            type=wx.BITMAP_TYPE_ICO)
 135         self.SetIcon(frm_icon)
 136 
 137 #-------------------------------------------------------------------------------
 138 
 139 if __name__ == '__main__':
 140     app = wx.App()
 141     frame = MyFrame()
 142     frame.Show()
 143     app.MainLoop()


Second example

img_sample_two.png

   1 # !/usr/bin/env python3
   2 # -*- coding : utf-8 -*-
   3 
   4 #-------------------------------------------------------------------------------
   5 # Name       : sample_two.py
   6 # Purpose    : Drop down panel example.
   7 #
   8 # Author     : ???
   9 # Link       : wxPython forum.
  10 # Created    : -
  11 # Copyright  : -
  12 # Licence    : -
  13 #-------------------------------------------------------------------------------
  14 
  15 """
  16 
  17 ...
  18 
  19 """
  20 
  21 
  22 #-------------------------------------------------------------------------------
  23 # Import python packages
  24 #-------------------------------------------------------------------------------
  25 import os
  26 import sys
  27 
  28 
  29 #-------------------------------------------------------------------------------
  30 # Import wxPython packages
  31 #-------------------------------------------------------------------------------
  32 import wx
  33 import wx.lib.scrolledpanel as scrolled
  34 import wx.lib.buttons as buttons
  35 
  36 
  37 #-------------------------------------------------------------------------------
  38 # wxPython version
  39 #-------------------------------------------------------------------------------
  40 print("wxPython version :", wx.VERSION_STRING)
  41 
  42 
  43 #-------------------------------------------------------------------------------
  44 # Path
  45 #-------------------------------------------------------------------------------
  46 app_dir = os.path.split(os.path.abspath(sys.argv[0]))[0]
  47 icon_dir = os.path.join(app_dir, "icons")
  48 
  49 
  50 #-------------------------------------------------------------------------------
  51 # Class
  52 #-------------------------------------------------------------------------------
  53 # class MyWxExpandPanel
  54 # class MyButtonPanel
  55 # class MyAbsolute
  56 # class MyFrame
  57 
  58 
  59 #-------------------------------------------------------------------------------
  60 
  61 class MyWxExpandPanel(wx.Panel):
  62     """
  63     A Custom DropDown Panel.
  64     """
  65     def __init__(self, parent, title="Frame Layout", expand=False):
  66         wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.SUNKEN_BORDER)
  67 
  68         self.expand = expand # Expand status.
  69         self.parent = parent # Parent of this panel.
  70         self.title = title
  71 
  72         # This will be the main sizer for this panel.
  73         self.vbox = wx.FlexGridSizer(100, 1, 3, 0)
  74         self.vbox.AddGrowableCol(0)
  75 
  76         # Create button for collapse/expand.
  77         self.btn = buttons.GenBitmapTextButton(self, wx.ID_ANY,
  78                                                bitmap=wx.Bitmap("Bitmaps/img.png"),
  79                                                label=title,
  80                                                size=(200, -1),
  81                                                style=wx.ALIGN_LEFT,
  82                                                name="cpbtn")
  83         self.btn.SetUseFocusIndicator(True)
  84         self.btn.SetBezelWidth(2)
  85         # Define the button color.
  86         self.btn.SetBackgroundColour("#ff8080")
  87         self.btn.SetForegroundColour(wx.BLACK)
  88 
  89         self.btn.Bind(wx.EVT_BUTTON, self.onClick)
  90 
  91         self.vbox.Add(self.btn, 1, wx.EXPAND | wx.ALL, 0)
  92         self.SetSizer(self.vbox)
  93 
  94     #---------------------------------------------------------------------------
  95 
  96     def addWidget(self, widget):
  97         """
  98         ...
  99         """
 100 
 101         self.vbox.Add(widget, 0, wx.GROW)
 102         if not self.expand:
 103             widget.Hide()
 104 
 105 
 106     def addSizer(self, sizer):
 107         """
 108         ...
 109         """
 110 
 111         self.vbox.Add(sizer, 0, wx.EXPAND|wx.ALL, 1)
 112         if not self.expand:
 113             sizer.Hide()
 114 
 115 
 116     def onClick(self, event=None):
 117         """
 118         ...
 119         """
 120 
 121         self.update()
 122 
 123 
 124     def update(self):
 125         """
 126         ...
 127         """
 128 
 129         # Toggle the status of 'expand'.
 130         self.expand = not self.expand
 131 
 132         # Either hide or show the children.
 133         for child in self.GetChildren():
 134             # Ignore button.
 135             if child.GetName() == "cpbtn":  continue
 136             # Do not show disabled widgets.
 137             #~ if child.IsEnabled():
 138                 #~ child.Show(self.expand)
 139             #~ else:
 140                 #~ child.Hide()
 141             child.Show(self.expand)
 142 
 143         # This works
 144         # self.parent.Layout()
 145         # make scrollbars visible if parent is scrolledWindow
 146         # and if they are required automatically
 147         # self.parent.SendSizeEvent()
 148         # self.parent.Refresh()
 149 
 150         # This I am not sure.
 151         self.parent.SetupScrolling()
 152         self.parent.Refresh()
 153 
 154 #-------------------------------------------------------------------------------
 155 
 156 class MyButtonPanel(wx.Panel):
 157     def __init__(self, parent):
 158         wx.Panel.__init__(self, parent, -1)
 159 
 160         b1 = wx.Button(self, -1, "Button-1")
 161         b2 = wx.Button(self, -1, "Button-2")
 162         b3 = wx.Button(self, -1, "Button-3")
 163 
 164         vbox = wx.BoxSizer(wx.VERTICAL)
 165         vbox.Add(b1, 1)
 166         vbox.Add(b2, 1)
 167         vbox.Add(b3, 1)
 168 
 169         self.SetSizer(vbox)
 170 
 171 #-------------------------------------------------------------------------------
 172 
 173 class MyAbsolute(wx.Panel):
 174     def __init__(self, parent):
 175         wx.Panel.__init__(self, parent)
 176 
 177         self.parent = parent
 178 
 179         self.SetBackgroundColour("#c0c0c0")
 180 
 181         vbox = wx.BoxSizer(wx.VERTICAL)
 182         self.scp = scrolled.ScrolledPanel(self, wx.ID_ANY,
 183                                           style=wx.TAB_TRAVERSAL,
 184                                           name="panel")
 185         self.scpSizer = wx.BoxSizer(wx.VERTICAL)
 186 
 187         vbox.Add(self.scp, 1, wx.EXPAND)
 188 
 189         # Create MyWxExpandPanel.
 190         self.expandPanel = MyWxExpandPanel(self.scp, " Drop down panel - A", 0)
 191         self.expandPanel.SetBackgroundColour("#eceade")
 192 
 193         # Create Three button panel.
 194         btnPanel = MyButtonPanel(self.expandPanel)
 195 
 196         # Add btn panel to expandPanel.
 197         # This will add btnPanel to a sizer in expandPanel.
 198         self.expandPanel.addWidget(btnPanel)
 199 
 200         # Finally add expandPanel to scrollWindow.
 201         self.scpSizer.Add(self.expandPanel, 0, wx.EXPAND)
 202 
 203         # Create MyWxExpandPanel.
 204         self.expandPanel = MyWxExpandPanel(self.scp, " Drop down panel - B", 0)
 205         self.expandPanel.SetBackgroundColour("#eceade")
 206 
 207         # Create Three button panel.
 208         btnPanel = MyButtonPanel(self.expandPanel)
 209 
 210         # Add btn panel to expandPanel.
 211         # This will add btnPanel to a sizer in expandPanel.
 212         self.expandPanel.addWidget(btnPanel)
 213 
 214         # Finally add expandPanel to scrollWindow.
 215         self.scpSizer.Add(self.expandPanel, 0, wx.EXPAND)
 216 
 217         # Create MyWxExpandPanel.
 218         self.expandPanel = MyWxExpandPanel(self.scp, " Drop down panel - C", 0)
 219         self.expandPanel.SetBackgroundColour("#eceade")
 220 
 221         # Create Three button panel.
 222         btnPanel = MyButtonPanel(self.expandPanel)
 223 
 224         # Add btn panel to expandPanel.
 225         # This will add btnPanel to a sizer in expandPanel.
 226         self.expandPanel.addWidget(btnPanel)
 227 
 228         # Finally add expandPanel to scrollWindow.
 229         self.scpSizer.Add(self.expandPanel, 0, wx.EXPAND)
 230 
 231         # Create MyWxExpandPanel.
 232         self.expandPanel = MyWxExpandPanel(self.scp, " Drop down panel - D", 0)
 233         self.expandPanel.SetBackgroundColour("#eceade")
 234 
 235         # Create Three button panel.
 236         btnPanel = MyButtonPanel(self.expandPanel)
 237 
 238         # Add btn panel to expandPanel.
 239         # This will add btnPanel to a sizer in expandPanel.
 240         self.expandPanel.addWidget(btnPanel)
 241 
 242         # Finally add expandPanel to scrollWindow.
 243         self.scpSizer.Add(self.expandPanel, 0, wx.EXPAND)
 244 
 245         self.scp.SetSizer(self.scpSizer)
 246         self.scp.SetAutoLayout(1)
 247 
 248         self.scp.SetupScrolling(scroll_x=False, scroll_y=True,
 249                                 rate_y=10, scrollToTop=True)
 250 
 251         self.SetSizer(vbox)
 252         self.Layout()
 253 
 254 #-------------------------------------------------------------------------------
 255 
 256 class MyFrame(wx.Frame):
 257     def __init__(self):
 258         wx.Frame.__init__(self, None, wx.ID_ANY,
 259                           title="Sample_two",
 260                           pos=wx.DefaultPosition,
 261                           size=(400, 250),
 262                           style=wx.DEFAULT_FRAME_STYLE)
 263 
 264         self.Bind(wx.EVT_CLOSE, self.onCloseWindow)
 265 
 266         self.panel = MyAbsolute(self)
 267 
 268         self.Centre()
 269         self.Show()
 270 
 271         #------------
 272 
 273         # Simplified init method.
 274         self.SetProperties()
 275 
 276     #---------------------------------------------------------------------------
 277 
 278     def SetProperties(self):
 279         """
 280         Set the frame properties (title, icon...).
 281         """
 282 
 283         # Set frame icon.
 284         frameicon = wx.Icon("icons/wxwin.ico")
 285         self.SetIcon(frameicon)
 286 
 287 
 288     def onClose(self, event):
 289         self.Close(True)
 290 
 291 
 292     def onCloseWindow(self, event):
 293         self.Destroy()
 294 
 295 #-------------------------------------------------------------------------------
 296 
 297 if __name__ == '__main__':
 298     app = wx.App()
 299     frame = MyFrame()
 300     frame.Show()
 301     app.MainLoop()


Third example

img_sample_three.png

   1 # !/usr/bin/env python3
   2 # -*- coding : utf-8 -*-
   3 
   4 #-------------------------------------------------------------------------------
   5 # Name       : sample_three.py
   6 # Purpose    : Simple foldable panels. Layout lifted off Windows.
   7 #              Use at your own risk!
   8 # Author     : Egor Zindy
   9 #              Modified and updated for wxPython Phoenix by Ecco
  10 # Link       : wxPython forum.
  11 # Created    : A long time ago...
  12 # Copyright  : -
  13 # Licence    : Code put in the public domain, for someone else
  14 #              could find a use for it
  15 #-------------------------------------------------------------------------------
  16 
  17 """
  18 
  19 ...
  20 
  21 """
  22 
  23 
  24 #-------------------------------------------------------------------------------
  25 # Import python packages
  26 #-------------------------------------------------------------------------------
  27 import os
  28 import sys
  29 
  30 
  31 #-------------------------------------------------------------------------------
  32 # Import wxPython packages
  33 #-------------------------------------------------------------------------------
  34 import wx
  35 
  36 
  37 #-------------------------------------------------------------------------------
  38 # wxPython version
  39 #-------------------------------------------------------------------------------
  40 print("wxPython version :", wx.VERSION_STRING)
  41 
  42 
  43 #-------------------------------------------------------------------------------
  44 # Path
  45 #-------------------------------------------------------------------------------
  46 app_dir = os.path.split(os.path.abspath(sys.argv[0]))[0]
  47 icon_dir = os.path.join(app_dir, "icons")
  48 bmp_dir = os.path.join(app_dir, "bitmaps")
  49 
  50 
  51 #-------------------------------------------------------------------------------
  52 # Class
  53 #-------------------------------------------------------------------------------
  54 # class MyFoldPanel
  55 # class MyColorPanel
  56 # class MyMainPanel
  57 # class MyFrame
  58 # class MyApp
  59 
  60 
  61 #-------------------------------------------------------------------------------
  62 
  63 class MyFoldPanel(wx.Panel):
  64     def __init__(self, parent, psizer, title, tooltip=None,
  65                  rimcolour="light grey", bgcolour="white",
  66                  txtcolour="black", is_open=1):
  67         wx.Panel.__init__(self, parent, -1)
  68 
  69         #------------
  70 
  71         # Attributes
  72         self.is_open = is_open
  73         self.parent = parent
  74         self.rimcolour, self.bgcolour, self.txtcolour = rimcolour, bgcolour, txtcolour
  75         self.title = title
  76         self.tooltip = tooltip
  77         # XXX It won't work properly without
  78         # refreshing the parent sizer/panel.
  79         self.parentsizer = psizer
  80 
  81         #------------
  82 
  83         # Simplified init method.
  84         self.SetProperties()
  85         self.CreateCtrls()
  86         self.BindEvents()
  87         self.DoLayout()
  88 
  89     #---------------------------------------------------------------------------
  90 
  91     def SetProperties(self):
  92         """
  93         Set the panel properties (color...).
  94         """
  95 
  96         self.SetBackgroundColour(self.rimcolour)
  97 
  98 
  99     def CreateCtrls(self):
 100         """
 101         Create some controls for my panel.
 102         """
 103 
 104         self.bmp_bu = wx.Bitmap(os.path.join(bmp_dir,  # bottom/open/state-1
 105                                              "sm_down.png"),
 106                                 type=wx.BITMAP_TYPE_PNG)
 107 
 108         self.bmp_bd = wx.Bitmap(os.path.join(bmp_dir,  # bottom
 109                                              "sm_up.png"),
 110                                 type=wx.BITMAP_TYPE_PNG)
 111 
 112         self.bmp_wu = wx.Bitmap(os.path.join(bmp_dir,  # top
 113                                              "sm_down.png"),
 114                                 type=wx.BITMAP_TYPE_PNG)
 115 
 116         self.bmp_wd = wx.Bitmap(os.path.join(bmp_dir,  # top/close/state-2
 117                                              "sm_up.png"),
 118                                 type=wx.BITMAP_TYPE_PNG)
 119 
 120         self.bmp_bub = wx.Bitmap(os.path.join(bmp_dir,  # bottom
 121                                               "sm_down.png"),
 122                                  type=wx.BITMAP_TYPE_PNG)
 123 
 124         self.bmp_bdb = wx.Bitmap(os.path.join(bmp_dir,  # bottom/close/state-2
 125                                               "sm_up.png"),
 126                                  type=wx.BITMAP_TYPE_PNG)
 127 
 128         self.bmp_wub = wx.Bitmap(os.path.join(bmp_dir,  # top/open/state-1
 129                                               "sm_down.png"),
 130                                  type=wx.BITMAP_TYPE_PNG)
 131 
 132         self.bmp_wdb = wx.Bitmap(os.path.join(bmp_dir,  # top
 133                                               "sm_up.png"),
 134                                  type=wx.BITMAP_TYPE_PNG)
 135 
 136         #------------
 137 
 138         # Title panel.
 139         self.tpanel = wx.Panel(self, -1)
 140         if self.tooltip is not None:
 141             self.tpanel.SetToolTip(self.tooltip)
 142 
 143         self.title = wx.StaticText( self.tpanel, -1, self.title)
 144         self.title.SetFont(wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD))
 145         self.title.SetForegroundColour(self.txtcolour)
 146 
 147         if self.is_open==1:
 148             if self.txtcolour == "black": bmp = self.bmp_bu
 149             else: bmp = self.bmp_wu
 150         else:
 151             if self.txtcolour == "black": bmp = self.bmp_bd
 152             else: bmp = self.bmp_wd
 153 
 154         self.sb = wx.StaticBitmap(self.tpanel, -1, bmp,
 155                                   size=(bmp.GetWidth(),
 156                                         bmp.GetHeight()))
 157 
 158         cursor = wx.Cursor(wx.CURSOR_HAND)
 159         self.tpanel.SetCursor(cursor)
 160 
 161 
 162     def BindEvents(self):
 163         """
 164         Bind all the events related to my panel.
 165         """
 166 
 167         self.title.Bind(wx.EVT_LEFT_UP, self.OnButton)
 168         self.sb.Bind(wx.EVT_LEFT_UP, self.OnButton)
 169         self.tpanel.Bind(wx.EVT_LEFT_UP, self.OnButton)
 170         self.tpanel.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter)
 171         self.tpanel.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
 172 
 173 
 174     def DoLayout(self):
 175         """
 176         Do layout.
 177         """
 178 
 179         self.vbox = wx.BoxSizer(wx.VERTICAL)
 180         box = wx.BoxSizer(wx.HORIZONTAL)
 181 
 182         box.Add(self.title, 1, wx.EXPAND | wx.LEFT | wx.TOP, 5)
 183         box.Add(self.sb, 0, wx.ALL, 4)
 184 
 185         self.tpanel.SetSizer(box)
 186 
 187         self.vbox.Add(self.tpanel, 0, wx.EXPAND)
 188 
 189         # Page panel.
 190         self.ppanel = wx.Panel(self, -1)
 191         self.ppanel.SetBackgroundColour(self.bgcolour)
 192 
 193         self.pbox = wx.BoxSizer(wx.VERTICAL)
 194         self.pbox.Layout()
 195         self.ppanel.SetSizer(self.pbox)
 196 
 197 
 198         self.vbox.Add(self.ppanel, 1, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 1)
 199 
 200         if self.is_open == 0:
 201             self.vbox.Hide(self.ppanel)
 202 
 203         self.vbox.Layout()
 204         self.SetSizer(self.vbox)
 205 
 206 
 207     def OnEnter(self,event):
 208         """
 209         ...
 210         """
 211 
 212         if self.txtcolour == "black":
 213             if self.is_open == 1: bmp = self.bmp_bub
 214             else: bmp = self.bmp_bdb
 215         else:
 216             if self.is_open == 1: bmp = self.bmp_wub
 217             else: bmp = self.bmp_wdb
 218 
 219         self.sb.SetBitmap(bmp)
 220 
 221 
 222     def OnLeave(self,event):
 223         """
 224         ...
 225         """
 226 
 227         if self.txtcolour == "black":
 228             if self.is_open == 1: bmp = self.bmp_bu
 229             else: bmp = self.bmp_bd
 230         else:
 231             if self.is_open == 1: bmp = self.bmp_wu
 232             else: bmp = self.bmp_wd
 233 
 234         self.sb.SetBitmap(bmp)
 235 
 236 
 237     def OnButton(self,event):
 238         """
 239         ...
 240         """
 241 
 242         if self.is_open == 1:
 243             self.vbox.Hide(self.ppanel)
 244             if self.txtcolour == "black": bmp = self.bmp_bdb
 245             else: bmp = self.bmp_wdb
 246         else:
 247             self.vbox.Show(self.ppanel)
 248             if self.txtcolour == "black": bmp = self.bmp_bub
 249             else: bmp = self.bmp_wub
 250 
 251         # Ugly, all three statements are needed
 252         # (only tested in windows, though)
 253         # self.parentsizer.RecalcSizes()
 254         self.parentsizer.Layout()
 255         self.parent.Refresh()
 256 
 257         self.sb.SetBitmap(bmp)
 258         self.is_open = 1-self.is_open
 259         event.Skip()
 260 
 261 
 262     def SetPage(self, page, setbg=0):
 263         """
 264         ...
 265         """
 266 
 267         page.Reparent(self.ppanel)
 268         self.page = page
 269 
 270         self.pbox.Add(page, 1, wx.EXPAND | wx.ALL, 5)
 271         self.pbox.Layout()
 272 
 273         if setbg:
 274             page.SetBackgroundColour(self.bgcolour)
 275 
 276 #-------------------------------------------------------------------------------
 277 
 278 class MyColorPanel(wx.Panel):
 279     def __init__(self, parent, color):
 280         wx.Panel.__init__(self, parent, -1, size=(-1, -1))
 281 
 282         #------------
 283 
 284         # Attributes
 285         self.color = color
 286 
 287         #------------
 288 
 289         # Simplified init method.
 290         self.SetProperties()
 291 
 292         itemList = ['item 1', 'item 2', 'item 3', 'item 4']
 293 
 294         self.txt = wx.StaticText(self, -1, "This is a sample text !")
 295         self.btn = wx.Button(self, -1, "&Button")
 296         self.chk = wx.CheckBox(self, -1, "&CheckBox")
 297         self.chk.SetValue(True)
 298         self.rdb = wx.RadioBox(self, label="RadioBox :",
 299                                choices=itemList,
 300                                majorDimension=4,
 301                                style=wx.RA_SPECIFY_COLS)
 302 
 303         self.Bind(wx.EVT_BUTTON, self.OnButton, self.btn)
 304         self.Bind(wx.EVT_CHECKBOX, self.OnCheckBox, self.chk)
 305         self.Bind(wx.EVT_RADIOBOX, self.OnRadioBox, self.rdb)
 306 
 307         #-----------------
 308 
 309         colour = self.GetBackgroundColour()
 310         colour.Set(colour.Red(), colour.Green(), colour.Blue(),
 311                    wx.ALPHA_TRANSPARENT)
 312         self.btn.SetBackgroundColour(colour)
 313         #self.chk.SetBackgroundColour(colour)
 314         #self.rdb.SetBackgroundColour(colour)
 315 
 316         #------------
 317 
 318         self.sizer = wx.BoxSizer(wx.VERTICAL)
 319 
 320         self.sizer.Add(self.txt, 0, wx.ALL, 5)
 321         self.sizer.Add(self.btn, 0, wx.ALL, 5)
 322         self.sizer.Add(self.chk, 0, wx.ALL, 5)
 323         self.sizer.Add(self.rdb, 0, wx.ALL, 5)
 324 
 325         #------------
 326 
 327         self.SetSizer(self.sizer)
 328         self.sizer.Layout()
 329 
 330     #---------------------------------------------------------------------------
 331 
 332     def SetProperties(self):
 333         """
 334         Set the panel properties (color...).
 335         """
 336 
 337         self.SetBackgroundColour(self.color)
 338 
 339 
 340     def OnButton(self, event):
 341         """
 342         ...
 343         """
 344 
 345         print("\nOnButton: %s" % event.GetId())
 346 
 347         checkBox = event.GetEventObject()
 348         label = checkBox.GetLabel()
 349         print("OnButton label: %s" % label)
 350 
 351 
 352     def OnCheckBox(self, event):
 353         """
 354         ...
 355         """
 356 
 357         print("\nOnCheckBox checked: %d" % event.IsChecked())
 358 
 359         checkBox = event.GetEventObject()
 360         val = checkBox.GetValue()
 361         print("OnCheckBox value: %s" % val)
 362 
 363 
 364     def OnRadioBox(self, event):
 365         """
 366         ...
 367         """
 368 
 369         print("\nOnRadioBox int: %d" % event.GetInt())
 370 
 371         radioBox = event.GetEventObject()
 372         select = radioBox.GetStringSelection()
 373         print("OnRadioBox get string selection: %s\n" % select)
 374 
 375 #-------------------------------------------------------------------------------
 376 
 377 class MyMainPanel(wx.Panel):
 378     def __init__(self, parent):
 379         wx.Panel.__init__(self, parent, -1)
 380 
 381         #------------
 382 
 383         # Simplified init method.
 384         self.SetProperties()
 385         self.CreateCtrls()
 386         self.DoLayout()
 387 
 388     #---------------------------------------------------------------------------
 389 
 390     def SetProperties(self):
 391         """
 392         Set the panel properties (color...).
 393         """
 394 
 395         self.SetBackgroundColour("white")
 396 
 397 
 398     def CreateCtrls(self):
 399         """
 400         Create some controls for my panel.
 401         """
 402 
 403         # self.vbox is the top-level one that manages everything.
 404         self.vbox = wx.BoxSizer(wx.VERTICAL)
 405 
 406         #------------
 407 
 408         tooltip = "Click to unfold the green panel"
 409         self.p1 = MyFoldPanel(self, self.vbox, "Green Panel",
 410                               tooltip, wx.Colour(10, 10, 96),
 411                               "white", "white", is_open=0)
 412 
 413         tooltip = "The titlebar arrow icon is only available in two colours\n"\
 414                   "... but is transparent."
 415         self.p2 = MyFoldPanel(self, self.vbox, "Red Panel",
 416                               tooltip, "light grey", "white",
 417                               "black", is_open=1)
 418 
 419         self.p1.SetPage(MyColorPanel(self.p1, wx.Colour(128, 255, 128)), 0)
 420         self.p2.SetPage(MyColorPanel(self.p2, wx.Colour(255, 128, 128)), 0)
 421 
 422 
 423     def DoLayout(self):
 424         """
 425         Do layout.
 426         """
 427 
 428         self.vbox.Add(self.p1, 0, wx.EXPAND | wx.ALL, 5)
 429         self.vbox.Add(self.p2, 0, wx.EXPAND | wx.ALL, 5)
 430 
 431         #------------
 432 
 433         self.SetSizer(self.vbox)
 434         self.vbox.Layout()
 435 
 436 #-------------------------------------------------------------------------------
 437 
 438 class MyFrame(wx.Frame):
 439     def __init__(self, pos=wx.DefaultPosition, size=(300, 305)):
 440         wx.Frame.__init__(self, None, -1, "", pos, size)
 441 
 442         #------------
 443 
 444         self.CreateStatusBar()
 445 
 446         #------------
 447 
 448         # Simplified init method.
 449         self.SetProperties()
 450         self.CreateCtrls()
 451 
 452     #---------------------------------------------------------------------------
 453 
 454     def SetProperties(self):
 455         """
 456         Set the frame properties (title, icon...).
 457         """
 458 
 459         self.SetTitle("Sample_three")
 460 
 461         #------------
 462 
 463         frm_icon = wx.Icon(os.path.join(icon_dir,
 464                                         "wxwin.ico"),
 465                            type=wx.BITMAP_TYPE_ICO)
 466         self.SetIcon(frm_icon)
 467 
 468 
 469     def CreateCtrls(self):
 470         """
 471         Make widgets for my frame.
 472         """
 473 
 474         self.pnl = MyMainPanel(self)
 475 
 476 #-------------------------------------------------------------------------------
 477 
 478 class MyApp(wx.App):
 479     def OnInit(self):
 480 
 481         #------------
 482 
 483         frame = MyFrame()
 484         self.SetTopWindow(frame)
 485         frame.Show(True)
 486 
 487         return True
 488 
 489 #-------------------------------------------------------------------------------
 490 
 491 def main():
 492     app = MyApp(False)
 493     app.MainLoop()
 494 
 495 #-------------------------------------------------------------------------------
 496 
 497 if __name__ == "__main__" :
 498     main()


Fourth example

img_sample_four.png

   1 # !/usr/bin/env python3
   2 # -*- coding : utf-8 -*-
   3 
   4 #-------------------------------------------------------------------------------
   5 # Name       : sample_four.py
   6 # Purpose    : Simple foldable panels.
   7 # Author     : .
   8 # Created    : 02/08/22 (d/m/y)
   9 # Copyright  : .
  10 # Licence    : wxWindows license
  11 #-------------------------------------------------------------------------------
  12 
  13 """
  14 
  15 ...
  16 
  17 """
  18 
  19 
  20 #-------------------------------------------------------------------------------
  21 # Import wxPython packages
  22 #-------------------------------------------------------------------------------
  23 import wx
  24 import wx.lib.mixins.inspection  # Ctrl+Alt+I
  25 
  26 
  27 #-------------------------------------------------------------------------------
  28 # Event ID'S
  29 #-------------------------------------------------------------------------------
  30 ID_BTN_ONE   = wx.NewIdRef()
  31 ID_BTN_TWO   = wx.NewIdRef()
  32 ID_BTN_THREE = wx.NewIdRef()
  33 ID_BTN_FOUR  = wx.NewIdRef()
  34 ID_BTN_CLOSE = wx.NewIdRef()
  35 
  36 
  37 #-------------------------------------------------------------------------------
  38 # Constant
  39 #-------------------------------------------------------------------------------
  40 __APP_TITLE__   = "Sample_four"
  41 __APP_VERSION__ = "1.0.0"
  42 
  43 
  44 #-------------------------------------------------------------------------------
  45 # wxPython version
  46 #-------------------------------------------------------------------------------
  47 print("wxPython version :", wx.VERSION_STRING)
  48 
  49 
  50 #-------------------------------------------------------------------------------
  51 # Class
  52 #-------------------------------------------------------------------------------
  53 # class MyPanel
  54 # class MyFrame
  55 # class MyApp
  56 
  57 
  58 #-------------------------------------------------------------------------------
  59 
  60 class MyPanel(wx.Panel):
  61     """
  62     Main panel for my widgets.
  63     """
  64     def __init__(self, parent,):
  65         wx.Panel.__init__(self, parent)
  66 
  67         #------------
  68 
  69         self.parent = parent
  70 
  71         #------------
  72 
  73         self.SetDoubleBuffered(True)
  74 
  75 #-------------------------------------------------------------------------------
  76 
  77 class MyFrame(wx.Frame):
  78     """
  79     We simply derive a new class of frame.
  80     """
  81     def __init__(self, parent, id, title=""):
  82         super(MyFrame, self).__init__(parent, id, title)
  83 
  84         #------------
  85 
  86         # Simplified init method.
  87         self.SetProperties()
  88         self.CreateCtrls()
  89         self.BindEvents()
  90         self.DoLayout()
  91 
  92         #------------
  93 
  94         self.Centre()
  95 
  96     #---------------------------------------------------------------------------
  97 
  98     def SetProperties(self):
  99         """
 100         Set the frame properties (title, icon...).
 101         """
 102 
 103         # Set frame icon.
 104         frameicon = wx.Icon("icons/wxwin.ico")
 105         self.SetIcon(frameicon)
 106 
 107         #------------
 108 
 109         # Set frame title.
 110         appName = "%s" % (wx.GetApp().GetAppName())
 111         appVersion = "%s" % (__APP_VERSION__)
 112         self.SetTitle("{} v{}".format(appName, appVersion))
 113 
 114         #------------
 115 
 116         # Set frame foreground and background.
 117         # dark orange | cornflower blue
 118         # yellow green | yellow | wheat4
 119         self.SetBackgroundColour("#eceade")
 120         self.SetForegroundColour("black")
 121 
 122         self.SetSize(300, -1)
 123         self.SetMaxSize((300, -1))
 124         self.SetMinSize((300, -1))
 125 
 126 
 127     def CreateCtrls(self):
 128         """
 129         Create some controls for my frame.
 130         """
 131 
 132         self.panel = MyPanel(self)
 133 
 134         #-----------------
 135 
 136         # A font can be retrieved from the OS default font
 137         # and modified.
 138         font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
 139         font.SetStyle(wx.NORMAL)
 140         font.SetWeight(wx.BOLD)
 141 
 142         #-----------------
 143 
 144         self.btn1 = wx.Button(self.panel,
 145                               ID_BTN_ONE,
 146                               "Pane 1")
 147         # Thank you da-dada !
 148         self.btn1.SetLabelMarkup(''.join(('<b>', '&First pane', '</b>')))
 149 
 150         self.sz1 = wx.StaticBoxSizer(wx.VERTICAL,
 151                                      self.panel,
 152                                      label="")
 153 
 154         self.szb1 = self.sz1.GetStaticBox()
 155         self.szb1.Show(not self.szb1.IsShown())
 156 
 157         itemList = ['item 1', 'item 2', 'item 3', 'item 4']
 158 
 159         self.rdb1 = wx.RadioBox(self.szb1, label="RadioBox :",
 160                                 choices=itemList,
 161                                 majorDimension=4,
 162                                 style=wx.RA_SPECIFY_COLS)
 163 
 164         self.sz1.Add(self.rdb1, 0, 0)
 165 
 166         #-----------------
 167 
 168         self.btn2 = wx.Button(self.panel,
 169                               ID_BTN_TWO,
 170                               "Pane 2")
 171         self.btn2.SetLabelMarkup(''.join(('<b>', '&Second pane', '</b>')))
 172 
 173         self.sz2 = wx.StaticBoxSizer(wx.VERTICAL,
 174                                      self.panel,
 175                                      label="")
 176 
 177         self.szb2 = self.sz2.GetStaticBox()
 178         self.szb2.Show(not self.szb2.IsShown())
 179 
 180         self.rdb2 = wx.RadioBox(self.szb2, label="RadioBox :",
 181                                 choices=itemList,
 182                                 majorDimension=4,
 183                                 style=wx.RA_SPECIFY_COLS)
 184 
 185         self.sz2.Add(self.rdb2, 0, 0)
 186 
 187         #-----------------
 188 
 189         self.btn3 = wx.Button(self.panel,
 190                               ID_BTN_THREE,
 191                               "Pane 3")
 192         self.btn3.SetLabelMarkup(''.join(('<b>', '&Third pane', '</b>')))
 193 
 194         self.sz3 = wx.StaticBoxSizer(wx.VERTICAL,
 195                                      self.panel,
 196                                      label="")
 197 
 198         self.szb3 = self.sz3.GetStaticBox()
 199         self.szb3.Show(not self.szb3.IsShown())
 200 
 201         self.rdb3 = wx.RadioBox(self.szb3, label="RadioBox :",
 202                                 choices=itemList,
 203                                 majorDimension=4,
 204                                 style=wx.RA_SPECIFY_COLS)
 205 
 206         self.sz3.Add(self.rdb3, 0, 0)
 207 
 208         #-----------------
 209 
 210         self.btn4 = wx.Button(self.panel,
 211                               ID_BTN_FOUR,
 212                               "Pane 4")
 213         self.btn4.SetLabelMarkup(''.join(('<b>', 'F&ourth pane', '</b>')))
 214 
 215         self.sz4 = wx.StaticBoxSizer(wx.VERTICAL,
 216                                      self.panel,
 217                                      label="")
 218 
 219 
 220         self.szb4 = self.sz4.GetStaticBox()
 221         self.szb4.Show(not self.szb4.IsShown())
 222 
 223         self.rdb4 = wx.RadioBox(self.szb4, label="RadioBox :",
 224                                 choices=itemList,
 225                                 majorDimension=4,
 226                                 style=wx.RA_SPECIFY_COLS)
 227 
 228         self.sz4.Add(self.rdb4, 0, 0)
 229 
 230         #-----------------
 231 
 232         colour = self.GetBackgroundColour()
 233         colour.Set(colour.Red(), colour.Green(), colour.Blue(),
 234                    wx.ALPHA_TRANSPARENT)
 235         self.SetBackgroundColour(colour)
 236 
 237         self.btn1.SetForegroundColour(self.GetForegroundColour())
 238         self.btn2.SetForegroundColour(self.GetForegroundColour())
 239         self.btn3.SetForegroundColour(self.GetForegroundColour())
 240         self.btn4.SetForegroundColour(self.GetForegroundColour())
 241 
 242 
 243     def BindEvents(self):
 244         """
 245         Bind all the events related to my frame.
 246         """
 247 
 248         self.Bind(wx.EVT_CHAR_HOOK, self.OnKeyUp)
 249         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 250 
 251         self.btn1.Bind(wx.EVT_BUTTON, self.OnButton)
 252         self.btn2.Bind(wx.EVT_BUTTON, self.OnButton)
 253         self.btn3.Bind(wx.EVT_BUTTON, self.OnButton)
 254         self.btn4.Bind(wx.EVT_BUTTON, self.OnButton)
 255 
 256         self.panel.Bind(wx.EVT_RIGHT_UP, self.OnCloseWindow)  # Panel right clic.
 257 
 258 
 259     def DoLayout(self):
 260         """
 261         Do layout.
 262         """
 263 
 264         self.panelSizer = wx.BoxSizer(wx.VERTICAL)
 265         self.panelSizer.Add(self.btn1, proportion=0, flag=wx.EXPAND)
 266         self.panelSizer.Add(self.sz1, proportion=1, flag=wx.EXPAND)
 267         self.panelSizer.Add(self.btn2, proportion=0, flag=wx.EXPAND)
 268         self.panelSizer.Add(self.sz2, proportion=1, flag=wx.EXPAND)
 269         self.panelSizer.Add(self.btn3, proportion=0, flag=wx.EXPAND)
 270         self.panelSizer.Add(self.sz3, proportion=1, flag=wx.EXPAND)
 271         self.panelSizer.Add(self.btn4, proportion=0, flag=wx.EXPAND)
 272         self.panelSizer.Add(self.sz4, proportion=1, flag=wx.EXPAND)
 273 
 274         self.panel.SetSizer(self.panelSizer)
 275 
 276         #------------
 277 
 278         mainSizer = wx.BoxSizer()
 279         mainSizer.Add(self.panel, proportion=1, flag=wx.EXPAND)
 280 
 281         #------------
 282 
 283         self.SetSizer(mainSizer)
 284         self.Fit()
 285 
 286 
 287 
 288     def OnButton(self, evt):
 289         """
 290         ...
 291         """
 292 
 293         event_id = evt.GetId()
 294 
 295         #------------
 296 
 297         if event_id == ID_BTN_ONE :
 298             self.szb1.Show(not self.szb1.IsShown())
 299 
 300         elif event_id == ID_BTN_TWO :
 301             self.szb2.Show(not self.szb2.IsShown())
 302 
 303         elif event_id == ID_BTN_THREE :
 304             self.szb3.Show(not self.szb3.IsShown())
 305 
 306         elif event_id == ID_BTN_FOUR :
 307             self.szb4.Show(not self.szb4.IsShown())
 308 
 309         self.panelSizer.Fit(self)
 310 
 311 
 312     def OnKeyUp(self, event):
 313         """
 314         ...
 315         """
 316 
 317         if event.GetKeyCode() == wx.WXK_ESCAPE:
 318             # Close the frame, no action.
 319             self.OnCloseWindow(event)
 320         event.Skip()
 321 
 322 
 323     def OnBtnClose(self, event):
 324         """
 325         ...
 326         """
 327 
 328         self.Close()
 329 
 330 
 331     def OnCloseWindow(self, event):
 332         """
 333         ...
 334         """
 335 
 336         self.Destroy()
 337 
 338 #---------------------------------------------------------------------------
 339 
 340 class MyApp(wx.App, wx.lib.mixins.inspection.InspectionMixin):
 341     """
 342     We create an application object.
 343     """
 344     def OnInit(self):
 345 
 346         #------------
 347 
 348         # Initialize the inspection tool.
 349         self.Init()
 350 
 351         #------------
 352 
 353         self.SetAppName(__APP_TITLE__)
 354 
 355         #------------
 356 
 357         frame = MyFrame(parent=None, id=-1, title="")
 358         self.SetTopWindow(frame)
 359         frame.Show(True)
 360 
 361         return True
 362 
 363 #---------------------------------------------------------------------------
 364 
 365 def main():
 366     app = MyApp(redirect=False)
 367     app.MainLoop()
 368 
 369 #---------------------------------------------------------------------------
 370 
 371 if __name__ == "__main__" :
 372     main()


Download source

source.zip


Additional Information

Link :

https://discuss.wxpython.org/t/i-modified-my-foldpanel-code-a-bit-attached/12860

https://discuss.wxpython.org/t/ann-very-simple-foldable-panels-png-py-convert-utility/12664


https://wiki.wxpython.org/TitleIndex

https://docs.wxpython.org/


Thanks to

Seaba & Komoto48g (sample_one.py coding), Egor Zindy (sample_three.py coding), The wxPython community...


About this page

Date (d/m/y) Person (bot) Comments :

12/08/22 - Ecco (Created page for wxPython Phoenix).


Comments

- blah, blah, blah....

How to create a customized collapsible pane (Phoenix) (last edited 2023-01-18 14:46:52 by Ecco)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.