Reputation: 858
I am new to wxpython and working on my first app. I know there is a lot about this topic but I haven't seen anything helpful specificaly to my issue. I want to have more then two panels and switch like this
def switch(self, newactpanel)
self.actpanel.Hide()
self.actpanel=newactpanel
self.actpanel.Show()
So far this does not work. The app starts, the buttons appear but both panel views appear at once, or only one appears and I can not switch. How to build a def to switch between more panels?
Thank a lot for answers.
Here is my code:
import wx
ID_EXIT=200
ID_ADDKEYWORDS = 301
ID_WRITEINTERP = 302
h_frame = 750
w_frame = 325
class SubPanel(wx.Panel):
""""""
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
class AddKeyWordsPanel(wx.Panel):
def __init__(self, parent,size):
wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = size)
panel1 = SubPanel(self)
some_val = "Add KeyWords"
something = wx.TextCtrl(panel1, -1,some_val, size=(h_frame,24), style=wx.TE_READONLY|wx.SIMPLE_BORDER|wx.TE_CENTRE)
box = wx.BoxSizer(wx.VERTICAL)
box.Add(panel1, 1, wx.EXPAND)
self.SetAutoLayout(True)
self.SetSizer(box)
class WritePanel(wx.Panel):
def __init__(self, parent,size):
wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = size)
panel1 = SubPanel(self)
panel2 = SubPanel(self)
panel3 = SubPanel(self)
keys_val = self.GetKeyNames()
keys = wx.TextCtrl(panel1, -1,keys_val, size=(h_frame,24), style=wx.TE_READONLY|wx.SIMPLE_BORDER|wx.TE_CENTRE)
font = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
keys.SetFont(font)
keywords1_val = self.GetKeyWords(keys_val)
keywords1 = wx.TextCtrl(panel2, -1,keywords1_val, size=(h_frame,100), style=wx.TE_READONLY|wx.BORDER_NONE)
txtentry_val = ""
txtentry = wx.TextCtrl(panel3, -1, txtentry_val, size=(h_frame, 200))
txtentry.SetBackgroundColour("WHITE")
txtentry.SetInsertionPoint(0)
box = wx.BoxSizer(wx.VERTICAL)
box.Add(panel1, 3, wx.EXPAND)
box.Add(panel2, 2, wx.EXPAND)
box.Add(panel3, 1, wx.EXPAND)
self.SetAutoLayout(True)
self.SetSizer(box)
def GetKeyNames(self):
return "Blabla1"
def GetKeyWords(self,keys):
return "Blabla2"
class MainFrame(wx.Frame):
def __init__(self, parent, ID, title):
wx.Frame.__init__(self, parent, ID, title, size=(h_frame, w_frame))
self.CreateStatusBar()
menu= wx.Menu()
menu.Append(ID_ADDKEYWORDS,"&Add KeyWords"," Add Keywords")
menu.Append(ID_WRITEINTERP,"&Write Interpretations"," Write Interpretations")
menu.Append(ID_EXIT,"E&xit"," Terminate the program")
menuBar = wx.MenuBar()
menuBar.Append(menu,"&Menu")
self.SetMenuBar(menuBar)
self.wrtpnl = WritePanel(self,(h_frame,w_frame))
self.addkeywpnl = AddKeyWordsPanel(self,(h_frame,w_frame))
self.panel = self.wrtpnl
self.panel.Layout()
wx.EVT_MENU(self, ID_ADDKEYWORDS, self.SwitchPanel(self.addkeywpnl))
wx.EVT_MENU(self, ID_WRITEINTERP, self.SwitchPanel(self.wrtpnl))
wx.EVT_MENU(self, ID_EXIT, self.OnExit)
self.doiexit = wx.MessageDialog( self, " Exit - R U Sure? \n","GOING away ...", wx.YES_NO)
def SwitchPanel(self,show_pnl):
self.panel.Hide()
self.panel = show_pnl
self.panel.Layout()
self.panel.Show()
self.Layout()
def OnExit(self,e):
igot = self.doiexit.ShowModal()
if igot == wx.ID_YES:
self.Close(True)
app = None
app = wx.App()
frame = MainFrame(None, -1, "KeyWordTool")
frame.Show()
app.MainLoop()
Upvotes: 1
Views: 2857
Reputation: 858
Ok, I think I solved it with a combination of all three suggestions. It's not exactly what I wanted but very close. It works and this way I don't need to have a specific switch function for each button/panel. My solution is this:
self.wrtpnl = WritePanel(self,(h_frame,w_frame))
self.addkeywpnl = AddKeyWordsPanel(self,(h_frame,w_frame))
self.pnldic = {ID_ADDKEYWORDS:self.addkeywpnl, ID_WRITEINTERP:self.wrtpnl}
wx.EVT_MENU(self, ID_ADDKEYWORDS, self.SwitchPanel)
wx.EVT_MENU(self, ID_WRITEINTERP, self.SwitchPanel)
wx.EVT_MENU(self, ID_EXIT, self.OnExit)
def SwitchPanel(self,event):
self.panel.Hide()
self.panel = self.pnldic[event.GetId()]
self.panel.Layout()
self.panel.Show()
self.Layout()
Thanks a lot for the ideas!
Upvotes: 0
Reputation: 277
You do not require to pass both panel object while creating event for menu item.
wx.EVT_MENU(self, ID_ADDKEYWORDS, self.SwitchPanel)
wx.EVT_MENU(self, ID_WRITEINTERP, self.SwitchPanel)
Get menu item ID by using event.GetId() method to identify which panel to hide and show.
def SwitchPanel(self,event):
self.panel.Hide()
if event.GetId() == ID_ADDKEYWORDS:
self.panel = self.addkeywpnl
elif event.GetId() == ID_WRITEINTERP:
self.panel = self.wrtpnl
self.panel.Layout()
self.panel.Show()
self.Layout()
Upvotes: 1
Reputation: 33111
I actually wrote a tutorial on the topic some time ago. Here's the code:
import wx
import wx.grid as gridlib
########################################################################
class PanelOne(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
txt = wx.TextCtrl(self)
########################################################################
class PanelTwo(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
grid = gridlib.Grid(self)
grid.CreateGrid(25,12)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(grid, 0, wx.EXPAND)
self.SetSizer(sizer)
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
"Panel Switcher Tutorial")
self.panel_one = PanelOne(self)
self.panel_two = PanelTwo(self)
self.panel_two.Hide()
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.panel_one, 1, wx.EXPAND)
self.sizer.Add(self.panel_two, 1, wx.EXPAND)
self.SetSizer(self.sizer)
menubar = wx.MenuBar()
fileMenu = wx.Menu()
switch_panels_menu_item = fileMenu.Append(wx.ID_ANY,
"Switch Panels",
"Some text")
self.Bind(wx.EVT_MENU, self.onSwitchPanels,
switch_panels_menu_item)
menubar.Append(fileMenu, '&File')
self.SetMenuBar(menubar)
#----------------------------------------------------------------------
def onSwitchPanels(self, event):
""""""
if self.panel_one.IsShown():
self.SetTitle("Panel Two Showing")
self.panel_one.Hide()
self.panel_two.Show()
else:
self.SetTitle("Panel One Showing")
self.panel_one.Show()
self.panel_two.Hide()
self.Layout()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
You might also want to take a look at using one of wxPython's "Book" controls, such as the wx.Notebook
.
Upvotes: 3
Reputation: 2433
The trouble is that on the lines:
wx.EVT_MENU(self, ID_ADDKEYWORDS, self.SwitchPanel(self.addkeywpnl))
wx.EVT_MENU(self, ID_WRITEINTERP, self.SwitchPanel(self.wrtpnl))
you are calling the function SwitchPanel already. The result of the call is None (SwitchPanel does not return anything), so it is the same thing as if you did:
wx.EVT_MENU(self, ID_ADDKEYWORDS, None)
wx.EVT_MENU(self, ID_WRITEINTERP, None)
Probably the most understandable solution is:
wx.EVT_MENU(self, ID_ADDKEYWORDS, self.SwitchPanel1)
wx.EVT_MENU(self, ID_WRITEINTERP, self.SwitchPanel2)
# [...]
def SwitchPanel1(self, evt):
evt.Skip()
self.SwitchPanel(self.addkeywpnl)
def SwitchPanel2(self, evt):
evt.Skip()
self.SwitchPanel(self.wrtpnl)
Upvotes: 1