I'm probably missing something very obvious here, but what is the correct procedure for (dynamically) hiding and showing widgets (panels, etc.) in wxWidgets/wxPython?
The documentation seems to suggest that calling Show()/Hide(), followed by Layout(), would be enough to make the change visible. However, in the following little sample app, things do not seem to work quite that way:
--- 8< ---
#!/usr/bin/env python
# -*- encoding: utf-8
import wx
import random
class ButtonPanel(wx.Panel):
def __init__(self, *args, **kwargs):
color = kwargs.pop('color')
wx.Panel.__init__(self, *args, **kwargs)
self.SetBackgroundColour(color)
button = wx.Button(self, label="Toggle yellow panel")
colorpanel = ColorPanel(
self, style=wx.SUNKEN_BORDER,
color=wx.Colour(240,240,0)
)
sizer = wx.BoxSizer(orient=wx.VERTICAL)
sizer.Add(button, 0, wx.ALL|wx.ALIGN_RIGHT, 8)
sizer.Add(colorpanel, 0, wx.EXPAND|wx.ALL^wx.TOP, 8)
# Hide yellow colorpanels initially!
colorpanel.Hide()
self.SetSizer(sizer)
self.Bind(wx.EVT_BUTTON, self.OnButton, button)
self.colorpanel = colorpanel
def OnButton(self, evt):
""" Toggle the visibility of the yellow pane """
if self.colorpanel.IsShown():
self.colorpanel.Hide()
else:
self.colorpanel.Show()
self.GetSizer().Layout()
class ColorPanel(wx.Panel):
def __init__(self, *args, **kwargs):
color = kwargs.pop('color')
wx.Panel.__init__(self, *args, **kwargs)
self.SetBackgroundColour(color)
self.SetMinSize((10,50))
class ContainerPanel(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
container = wx.ScrolledWindow(
self,
style=wx.SUNKEN_BORDER
)
container.SetScrollRate(8, 8)
self.container = container
contentsizer = wx.BoxSizer(orient=wx.VERTICAL)
container.SetSizer(contentsizer)
self.contentsizer = contentsizer
color1 = wx.Colour(100, 200, 100)
color2 = wx.Colour(190, 240, 190)
for i in xrange(10):
self.AddPanel(color1)
self.AddPanel(color2)
bordersizer = wx.BoxSizer()
bordersizer.Add(container, 1, wx.EXPAND|wx.ALL, 2)
self.SetSizer(bordersizer)
def AddPanel(self, color):
panel = ButtonPanel(self.container, color=color)
self.contentsizer.Add(panel, 0, wx.EXPAND)
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(
self,
parent=None,
title=u"Dynamic Panel Show/Hide Test",
size=(300,300)
)
panel = ContainerPanel(self)
sizer = wx.BoxSizer()
sizer.Add(panel, 1, wx.EXPAND)
self.SetSizer(sizer)
class TestApp(wx.App):
def __init__(self):
wx.App.__init__(self, redirect=False)
frame = TestFrame()
frame.Show(True)
if __name__ == '__main__':
app = TestApp()
app.MainLoop()
--- 8< ---
Each colored panel on the list has a button that should toggle the visibility of a yellow (sunken) subpanel. This toggling happens in the OnButton() button event handler.
But while the Show()/Hide() calls will toggle the state of the panel in the internal bookkeeping of wxPython, this change will only have visible effect on the screen after the user has resized the frame or otherwise caused a repaint event to occur, at least on Windows.
So... what am I doing wrong here?
(I've also tried calling Refresh() etc., but to no avail.)
···
--
znark