My app frame contains a default large panel and two sub-panels inside it. When clicking on a particular menu-item, I want this default panel to change to another panel. My code:
This is the main frame shown when the app is opened. It contains one panel, which also contains two more panels:
import wx
class MainFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title="My Sample App.", size=(1280, 720))
self.InitMenuBar()
self.home_panel = HomePanels(self)
def InitMenuBar(self):
# Create Menu Bar
menubar = wx.MenuBar()
# Create File Menu
fileMenu = wx.Menu()
about_item = fileMenu.Append(wx.ID_ABOUT, 'About', 'Show About')
self.Bind(wx.EVT_MENU, self.on_about, about_item)
quit = fileMenu.Append(wx.ID_EXIT, '&Quit', 'Close')
self.Bind(wx.EVT_MENU, self.OnQuit, quit)
menubar.Append(fileMenu, '&File')
self.SetMenuBar(menubar)
self.Center()
def OnQuit(self, event):
self.Close()
def on_about(self, event):
# Show the About panel and hide the Main panel
self.about_panel = AboutPanel(self)
self.home_panel.Hide()
self.about_panel.Show()
self.SetAutoLayout(True)
self.Layout()
if __name__ == '__main__':
app = wx.App()
frame = MainFrame()
frame.Show()
app.MainLoop()
Below is the panel that's holding two sub-panels in the main frame:
class HomePanels(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
main_sizer = wx.BoxSizer(wx.HORIZONTAL)
# Left panel-----------------------------------------------------
left_panel = wx.Panel(self, style=wx.BORDER_SIMPLE, size=(250, 600))
left_panel.SetBackgroundColour('blue')
main_sizer.Add(left_panel, 0, wx.EXPAND | wx.ALL, 1)
# Right panel-----------------------------------------------------
right_panel = wx.Panel(self, style=wx.BORDER_SIMPLE)
right_panel.SetBackgroundColour('#f8f8ff')
main_sizer.Add(right_panel, 1, wx.RIGHT | wx.BOTTOM | wx.EXPAND, 2)
self.Center()
self.SetSizer(main_sizer)
self.SetAutoLayout(True)
self.Layout()
My AboutPanel.py
. This is what I want to replace with the HomePanel
panel when the About
option in the File
menu is clicked on:
class AboutPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
about_main_sizer = wx.BoxSizer(wx.HORIZONTAL)
abt_text = wx.StaticText(self, label="About Panel", pos=(10, 10))
about_main_sizer.Add(abt_text, 1, wx.EXPAND, 2)
self.SetSizer(about_main_sizer)
Running this code produces this output:
And clicking on the About
option in File
menu produces this output:
I can't figure out the problem! What's causing the About
panel to appear like this?
This code does it. The problem you had is that you have not structured your code properly. Panels should belong to the Frame and should be in sizers. Your code was just placing the about panel on the raw frame and so was appearing as a small square in the top left hand corner - A sure sign that it was not in a sizer.
import wx
class MainFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title="My Sample App.", size=(1280, 720))
self.InitMenuBar()
self.home_panel = HomePanels(self)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.home_panel)
self.SetSizer(self.sizer)
self.Show()
def InitMenuBar(self):
# Create Menu Bar
menubar = wx.MenuBar()
# Create File Menu
fileMenu = wx.Menu()
about_item = fileMenu.Append(wx.ID_ABOUT, 'About', 'Show About')
self.Bind(wx.EVT_MENU, self.on_about, about_item)
quit = fileMenu.Append(wx.ID_EXIT, '&Quit', 'Close')
self.Bind(wx.EVT_MENU, self.OnQuit, quit)
menubar.Append(fileMenu, '&File')
self.SetMenuBar(menubar)
self.Center()
def OnQuit(self, event):
wx.CallAfter(self.Destroy)
def on_about(self, event):
# Show the About panel and hide the Main panel
self._clear_sizer(self.sizer)
self.about_panel = AboutPanel(self)
self.sizer.Add(self.about_panel)
self.Layout()
def _clear_sizer(self, sizer):
"""Remove all of the widgets from the sizer."""
for child in sizer.GetChildren():
if child.IsSizer():
if child.IsSizer():
self._clear_sizer(child.GetSizer())
else:
child.GetWindow().Destroy()
sizer.Clear()
class HomePanels(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
main_sizer = wx.BoxSizer(wx.HORIZONTAL)
# Left panel-----------------------------------------------------
left_panel = wx.Panel(self, style=wx.BORDER_SIMPLE, size=(250, 600))
left_panel.SetBackgroundColour('blue')
main_sizer.Add(left_panel, 0, wx.EXPAND | wx.ALL, 1)
# Right panel-----------------------------------------------------
right_panel = wx.Panel(self, style=wx.BORDER_SIMPLE)
right_panel.SetBackgroundColour('#f8f8ff')
main_sizer.Add(right_panel, 1, wx.RIGHT | wx.BOTTOM | wx.EXPAND, 2)
self.Center()
self.SetSizer(main_sizer)
self.SetAutoLayout(True)
self.Layout()
class AboutPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
about_main_sizer = wx.BoxSizer(wx.HORIZONTAL)
abt_text = wx.StaticText(self, label="About Panel", pos=(10, 10))
about_main_sizer.Add(abt_text, 1, wx.EXPAND, 2)
self.SetSizer(about_main_sizer)
if __name__ == '__main__':
wx_app = wx.App()
MainFrame()
wx_app.MainLoop()
If you really want to display About wouldn't a dialog be better or even wx.adv.AboutDialogInfo?