Ok I have an application I am coding and am trying to get a layout simpler to this:
Notice how the text is left justified and the input boxes are all aligned, I see this in the wxPython demo code, but they all use the flexgrid sizer and I am trying to only use BoxSizers (due to them being simpler and because I only understand a little of sizers and even struggle with using BoxSizers, in 6 months I would have an even harder time)
I have tried having the input and text in two vertical sizers and then putting those in a horizontal sizer, didn't work because the text was not aligned with the inputs. I also tried doing that and also having each text, input pairing in a sizer, even worse. Any suggestions?
Here's a simple example using just BoxSizers:
import wx
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")
# Add a panel so it looks the correct on all platforms
panel = wx.Panel(self, wx.ID_ANY)
# create the labels
lblOne = wx.StaticText(panel, label="labelOne", size=(60,-1))
lblTwo = wx.StaticText(panel, label="lblTwo", size=(60,-1))
lblThree = wx.StaticText(panel, label="lblThree", size=(60,-1))
# create the text controls
txtOne = wx.TextCtrl(panel)
txtTwo = wx.TextCtrl(panel)
txtThree = wx.TextCtrl(panel)
# create some sizers
mainSizer = wx.BoxSizer(wx.VERTICAL)
lineOneSizer = wx.BoxSizer(wx.HORIZONTAL)
lineTwoSizer = wx.BoxSizer(wx.HORIZONTAL)
lineThreeSizer = wx.BoxSizer(wx.HORIZONTAL)
# add widgets to sizers
lineOneSizer.Add(lblOne, 0, wx.ALL|wx.ALIGN_LEFT, 5)
lineOneSizer.Add(txtOne, 0, wx.ALL, 5)
lineTwoSizer.Add(lblTwo, 0, wx.ALL|wx.ALIGN_LEFT, 5)
lineTwoSizer.Add(txtTwo, 0, wx.ALL, 5)
lineThreeSizer.Add(lblThree, 0, wx.ALL|wx.ALIGN_LEFT, 5)
lineThreeSizer.Add(txtThree, 0, wx.ALL, 5)
mainSizer.Add(lineOneSizer)
mainSizer.Add(lineTwoSizer)
mainSizer.Add(lineThreeSizer)
panel.SetSizer(mainSizer)
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
But this is kind of messy, so here's a refactored version:
import wx
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")
# create the main sizer
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
# Add a panel so it looks the correct on all platforms
self.panel = wx.Panel(self, wx.ID_ANY)
lbls = ["labelOne", "lblTwo", "lblThree"]
for lbl in lbls:
self.buildLayout(lbl)
self.panel.SetSizer(self.mainSizer)
#----------------------------------------------------------------------
def buildLayout(self, text):
""""""
lblSize = (60,-1)
lbl = wx.StaticText(self.panel, label=text, size=lblSize)
txt = wx.TextCtrl(self.panel)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(lbl, 0, wx.ALL|wx.ALIGN_LEFT, 5)
sizer.Add(txt, 0, wx.ALL, 5)
self.mainSizer.Add(sizer)
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
For most layouts other than the most basic you usually can't escape using a number of different types of sizers in order to realize your design.
Here is a good tutorial on sizers.
Related
I have a frame containing wx.SplitterWindow with two panels as its children. I want to hide one of the panel with a button(show/hide button) click i.e, First panel should hide and the second panel should occupy the whole frame with the sash gone. Clicking the button again should show the hidden panel, and the sash back in place. Is this possible?
I have searched the documentation, and there seems to be no specific method to do this? How can this be achieved.
import wx
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, title="test", size=(800,600))
self.splitter = wx.SplitterWindow(self, wx.ID_ANY)
self.panelOne = wx.Panel(self.splitter,1)
self.panelTwo = wx.Panel(self.splitter,1)
self.panelOne.SetBackgroundColour('sky blue')
self.panelTwo.SetBackgroundColour('pink')
self.splitter.SplitHorizontally(self.panelOne, self.panelTwo)
self.splitter.SetMinimumPaneSize(20)
self.buttonpanel = wx.Panel(self, 1)
self.buttonpanel.SetBackgroundColour('white')
self.mybutton = wx.Button(self.buttonpanel,label = "Hide")
self.Bind(wx.EVT_BUTTON, self.show_hide, self.mybutton)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.splitter, 2, wx.EXPAND)
self.sizer.Add(self.buttonpanel, 0, wx.EXPAND)
self.SetSizer(self.sizer)
def show_hide(self, event):
label = self.mybutton.GetLabel()
if label == "Hide":
### How to Hide panelOne ??
self.mybutton.SetLabel("Show")
if label == "Show":
### How to Show panelOne ??
self.mybutton.SetLabel("Hide")
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
After reading the documentation for a few seconds, I noticed the Unsplit method. You can use that to take out panelOne. Then when you want to Show it again, you just split the SplitterWindow again:
import wx
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, title="test", size=(800,600))
self.splitter = wx.SplitterWindow(self, wx.ID_ANY)
self.panelOne = wx.Panel(self.splitter,1)
self.panelTwo = wx.Panel(self.splitter,1)
self.panelOne.SetBackgroundColour('sky blue')
self.panelTwo.SetBackgroundColour('pink')
self.splitter.SplitHorizontally(self.panelOne, self.panelTwo)
self.splitter.SetMinimumPaneSize(20)
self.buttonpanel = wx.Panel(self, 1)
self.buttonpanel.SetBackgroundColour('white')
self.mybutton = wx.Button(self.buttonpanel,label = "Hide")
self.Bind(wx.EVT_BUTTON, self.show_hide, self.mybutton)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.splitter, 2, wx.EXPAND)
self.sizer.Add(self.buttonpanel, 0, wx.EXPAND)
self.SetSizer(self.sizer)
def show_hide(self, event):
label = self.mybutton.GetLabel()
if label == "Hide":
### How to Hide panelOne ??
self.mybutton.SetLabel("Show")
self.splitter.Unsplit(self.panelOne)
if label == "Show":
### How to Show panelOne ??
self.splitter.SplitHorizontally(self.panelOne, self.panelTwo)
self.mybutton.SetLabel("Hide")
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
Note: You had left off the call to MainLoop at the end of the code. This made your example un-runnable.
I'm looking for a way to get a list of all sizerItems which correspond to widgets. To demonstrate, I created the following example:
import wx
from wx.lib.scrolledpanel import ScrolledPanel
class Tester(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Window")
self.panel = ScrolledPanel(parent=self, id=-1)
self.panel.SetupScrolling()
self.sizerItems = []
Btn1 = wx.Button(self.panel, -1, "I'm a Button!")
Btn2 = wx.Button(self.panel, -1, "Me Too!")
Btn3 = wx.Button(self.panel, -1, "Hey! Quiet up there!")
Btn4 = wx.Button(self.panel, -1, "Jeez Frank, relax")
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
hbox1.Add(Btn1, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox1.Add(Btn2, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox2.Add(Btn3, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox2.Add(Btn4, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
vbox.Add(hbox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
vbox.Add(hbox2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
self.panel.SetSizer(vbox)
self.panel.Layout()
self.GetAllChildren(self.panel.GetSizer())
print self.sizerItems
def GetAllChildren(self, item):
try:
for sizerItem in item.GetChildren():
self.GetAllChildren(sizerItem)
except:
try:
item.GetSizer()
self.GetAllChildren(item.GetSizer())
except:
self.sizerItems.append(item)
return
app = wx.PySimpleApp()
Tester().Show()
app.MainLoop()
This code makes a GUI with 4 buttons. I want GetAllChildren() to return a list (self.sizerItems) of all the sizerItems which are not sizers. For this example, there should be 4 elements in the list corresponding to the four buttons. GetAllChildren() should recursively run down the tree of sizers, so vbox first, then hbox1 and all its children, then hbox2 and all its children.
Currently though, I get [None,None,None,None] as the result. I realize the try...except is where it is breaking, but I don't know how else to decide whether a particular item is what I want. Any suggestions on how to fix this or alternative methods? Thanks in advance
I played around with the code a bit and changed it so that it actually returned the widget instances instead of the sizerItem instances:
import wx
from wx.lib.scrolledpanel import ScrolledPanel
class Tester(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Window")
self.panel = ScrolledPanel(parent=self, id=-1)
self.panel.SetupScrolling()
self.sizerItems = []
Btn1 = wx.Button(self.panel, -1, "I'm a Button!")
Btn2 = wx.Button(self.panel, -1, "Me Too!")
Btn3 = wx.Button(self.panel, -1, "Hey! Quiet up there!")
Btn4 = wx.Button(self.panel, -1, "Jeez Frank, relax")
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
hbox1.Add(Btn1, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox1.Add(Btn2, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox2.Add(Btn3, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox2.Add(Btn4, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
vbox.Add(hbox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
vbox.Add(hbox2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
self.panel.SetSizer(vbox)
self.panel.Layout()
self.GetAllChildren(self.panel.GetSizer())
print self.sizerItems
def GetAllChildren(self, item):
for sizerItem in item.GetChildren():
widget = sizerItem.GetWindow()
if not widget:
# then it's probably a sizer
sizer = sizerItem.GetSizer()
if isinstance(sizer, wx.Sizer):
self.GetAllChildren(sizer)
else:
self.sizerItems.append(widget)
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
Tester().Show()
app.MainLoop()
You can read more about this method in one of my old tutorials:
http://www.blog.pythonlibrary.org/2012/08/24/wxpython-how-to-get-children-widgets-from-a-sizer/
Which, oddly enough, is based on another StackOverflow question:
wxPython: How to get sizer from wx.StaticText?
Anyway, when I ran that code above, I got back a list of four buttons. To check and make sure they aren't the same button added 4 times, I did this:
for item in self.sizerItems:
print item.GetLabel()
You might also want to take a look at the Widget Inspection Tool which can visually show you which widgets are in which sizers.
the path you are going down leads to the darkside! turn back!
you should just do something like
def __init__(self):
...
self.widgets = {
'text_input':textBox,
'btn1':btn1,
....
}
then just access them later through
my_instance.widgets['text_input'].GetValue()
or
def validate(self):
self.widgets['text_input'].GetValue()
Could someone help me kill two birds with one stone? I've been trying to center a button in my wxPanel for a little while and can't seem to figure it out. I've tried different attributes such as wx.CENTER and wx.ALIGN_CENTER and wx.ALIGN_CENTER_HORIZONTAL, but just can't seem to get the button to move to the center of the panel. The button I'm trying to center is set_button in the add_unit_pane method.
Also, when I click the X button to close the program, the program crashes. Am I not handling the close event correctly?
Could someone point out where I'm wrong?
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.init_ui()
def init_ui(self):
self.Bind(wx.EVT_CLOSE, self.on_close_window)
panel = wx.Panel(self)
panel_sizer = wx.BoxSizer(wx.VERTICAL)
panel_sizer.Add(self.add_unit_pane(panel, panel_sizer), 0, wx.EXPAND, border=5)
panel.SetSizerAndFit(panel_sizer)
self.Show()
def on_close_window(self, event):
self.Destroy()
def add_unit_pane(self, panel, panel_sizer):
""" Creates the Unit Measurement panel """
unit_panel = wx.StaticBox(panel, -1, 'Unit of Measurement')
unit_panel_sizer = wx.StaticBoxSizer(unit_panel, wx.VERTICAL)
# Create horizontal row of widgets 1
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
st1 = wx.StaticText(panel, label='UNIT:')
unit_choices = ['in (INCHES)',
'cm (CENTIMETERS)',
'mm (MILLIMETERS)'
]
unit_cb = wx.ComboBox(panel, -1, '100%',
choices=unit_choices,
style=wx.CB_DROPDOWN|wx.CB_READONLY)
unit_cb.SetValue('mm (MILLIMETERS)')
hbox1.Add(st1)
hbox1.AddSpacer(5)
hbox1.Add(unit_cb)
# Create horizontal row of widgets 2
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
st2 = wx.StaticText(panel, label='Pixels per selected unit:')
tc1 = wx.TextCtrl(panel)
hbox2.Add(st2)
hbox2.AddSpacer(5)
hbox2.Add(tc1)
# Create horizontal row of widgets 3
hbox3 = wx.BoxSizer(wx.HORIZONTAL)
set_button = wx.Button(panel, -1, 'Set')
hbox3.Add(set_button, 0, wx.CENTER)
# Add all other sizers to the main unit_panel_sizer
unit_panel_sizer.Add(hbox1)
unit_panel_sizer.AddSpacer(5)
unit_panel_sizer.Add(hbox2)
unit_panel_sizer.AddSpacer(5)
unit_panel_sizer.Add(hbox3)
# Fit all widgets to the sizer
unit_panel.SetSizerAndFit(unit_panel_sizer)
# Return the unit_panel_sizer
return unit_panel_sizer
if __name__ == '__main__':
ex = wx.App()
Example(None, -1, "Centering Button", size=(250,150))
ex.MainLoop()
Thank you,
Adam
change the line where you add hbox3 to be
unit_panel_sizer.Add(hbox3,0,wx.CENTER)
also comment out
unit_panel.SetSizerAndFit(unit_panel_sizer)
that should fix your crashing
I am trying to nest an sizer with horizontal layout inside the vertical layout sizer of a notebookPage panel.
I took some inspiration from wxPython: Resizing a notebook within a notebook but cannot make it work properly.
Instead of getting this layout
Tonnage limit (in tons): [3000]
[x] Enable filter on matchings categories
Everything is mangled on a single line in the panel
I am running this on Win7, python 2.6.6, wx 2.8.12.1
Here is the relevant code:
import sys
import os
import wx
class MainWindow(wx.Frame):
def __init__(self,parent,title):
self.ID_LOAD=101
self.ID_SAVE=102
# based on a frame, so set up the frame
wx.Frame.__init__(self,parent,wx.ID_ANY, title, size=(640,480))
self.CreateStatusBar()
self.tab = wx.Notebook(self, -1, style=(wx.NB_TOP))
self.globPanel = wx.NotebookPage(self.tab, -1)
self.orderPanel = wx.NotebookPage(self.tab, -1)
self.slabsPanel = wx.NotebookPage(self.tab, -1)
self.tab.AddPage(self.globPanel, "Global filter")
self.tab.AddPage(self.orderPanel, "Orders filter")
self.tab.AddPage(self.slabsPanel, "Slabs filter")
self.toolbar = wx.ToolBar(self, wx.ID_ANY, style=wx.TB_HORIZONTAL)
self.toolbar.SetToolBitmapSize((20,20))
load_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, (20,20))
self.toolbar.AddLabelTool(self.ID_LOAD, "Load", load_ico, bmpDisabled=wx.NullBitmap, shortHelp='Load', longHelp="Loads a text file to the filter editor")
save_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, (20,20))
self.toolbar.AddLabelTool(self.ID_SAVE, "Save", save_ico, bmpDisabled=wx.NullBitmap, shortHelp='Save', longHelp="Saves the contents of the filter editor")
self.toolbar.AddSeparator()
self.tonnageStatic = wx.StaticText(self.globPanel, wx.ID_ANY, "Tonnage limit (in tons): ")
self.tonnageEdit = wx.TextCtrl(self.globPanel, wx.ID_ANY, '30000')
self.tonnageSizer = wx.BoxSizer(wx.HORIZONTAL)
self.tonnageSizer.Add(self.tonnageStatic, flag=wx.EXPAND | wx.RIGHT | wx.LEFT | wx.TOP | wx.BOTTOM, border=10)
self.tonnageSizer.Add(self.tonnageEdit, flag=wx.EXPAND | wx.RIGHT | wx.LEFT | wx.TOP | wx.BOTTOM, border=10)
self.filterCheck = wx.CheckBox(self.globPanel, wx.ID_ANY, "Enable filter on matchings categories")
self.globSizer = wx.BoxSizer(wx.VERTICAL)
self.globSizer.Add(self.tonnageSizer)
self.globSizer.Add(wx.StaticLine(self), 0, wx.EXPAND)
self.globSizer.Add(self.filterCheck, 0, wx.EXPAND)
self.globPanel.SetSizer(self.globSizer)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.toolbar,0,wx.EXPAND)
self.sizer.Add(wx.StaticLine(self), 0, wx.EXPAND)
self.sizer.Add(self.tab, 1, wx.EXPAND)
self.SetSizer(self.sizer)
self.Layout()
self.toolbar.Realize()
# Show it !!!
self.Show(1)
def main():
app = wx.PySimpleApp()
view = MainWindow(None, "Input filter")
app.MainLoop()
if __name__ == "__main__":
main()
It is slighlty better like this, but I don't get the static line and only the first character of the checkox label is displayed
self.tonnageStatic = wx.StaticText(self.globPanel, wx.ID_ANY, "Tonnage limit (in tons): ")
self.tonnageEdit = wx.TextCtrl(self.globPanel, wx.ID_ANY, '30000')
self.tonnageSizer = wx.BoxSizer(wx.HORIZONTAL)
self.tonnageSizer.Add(self.tonnageStatic, 0, flag=wx.EXPAND|wx.ALL)
self.tonnageSizer.Add(self.tonnageEdit, 0, flag=wx.EXPAND|wx.ALL)
self.filterCheck = wx.CheckBox(self.globPanel, wx.ID_ANY, "Enable filter on matchings categories")
self.globSizer = wx.BoxSizer(wx.VERTICAL)
self.globSizer.Add(self.tonnageSizer)
self.globSizer.Add(wx.StaticLine(self.globPanel), 0, wx.EXPAND)
self.globSizer.Add(self.filterCheck, 0, wx.EXPAND)
self.globPanel.SetSizer(self.globSizer)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.toolbar,0,wx.EXPAND)
self.sizer.Add(wx.StaticLine(self), 0, wx.EXPAND)
self.sizer.Add(self.tab, 1, wx.EXPAND)
self.SetSizer(self.sizer)
self.globPanel.Layout()
self.Layout()
self.toolbar.Realize()
# Show it !!!
self.Show(1)
I just ran it on windows and if you call .Layout() on the globPanel after the self.Layout() line it should kick the sizers into shape :)
Also you can use wx.ALL which is the same as right, left, top and bottom
EDIT: I was curious why the weird behaviour and looked into a bit more. I looked at places I've used notebooks and I always use panels for the pages. If you change the NotebookPages to Panels you can do away with the Layout calls and it works as expected.
I'm having two problems with my program. The code below generates two panels when it should generate 3. It generates panel1 and panel2 no problem but panel3 should be to the right of panel2 is no where to be seen. Panel1 and panel2 are split vertically I'm trying to do the same with panel2 and panel3
My second problem is how do I generate another panel below panel1 without disrupting the splitter between panel1 and panel2 and then create a splitter between panel1 and new created panel below it?
import wx
class Panels(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title)
hbox = wx.BoxSizer(wx.HORIZONTAL)
splitter = wx.SplitterWindow(self, -1)
vbox1 = wx.BoxSizer(wx.VERTICAL)
panel1 = wx.Panel(splitter, -1)
panel12 = wx.Panel(panel1, -1, style=wx.BORDER_SUNKEN)
st1 = wx.StaticText(panel12, -1, 'Panel 1', (5, 5))
vbox1.Add(panel12, 1, wx.EXPAND)
panel1.SetSizer(vbox1)
vbox2 = wx.BoxSizer(wx.VERTICAL)
panel2 = wx.Panel(splitter, -1)
panel22 = wx.Panel(panel2, -1, style=wx.BORDER_RAISED)
st2 = wx.StaticText(panel22, -1, 'Panel 2', (5, 5))
vbox2.Add(panel22, 1, wx.EXPAND)
panel2.SetSizer(vbox2)
vbox3 = wx.BoxSizer(wx.VERTICAL)
panel3 = wx.Panel(splitter, -1)
panel32 = wx.Panel(panel3, -1, style=wx.BORDER_RAISED)
st3 = wx.StaticText(panel32, -1, 'Panel 3', (5, 5))
vbox3.Add(panel32, 1, wx.EXPAND)
panel3.SetSizer(vbox3)
hbox.Add(splitter, 1, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.SetSizer(hbox)
self.CreateStatusBar()
splitter.SplitVertically(panel1, panel3)
splitter.SplitVertically(panel2, panel3)
self.Centre()
self.Show(True)
def ExitApp(self, event):
self.Close()
app = wx.App()
Panels(None, -1, 'Panels')
app.MainLoop()
You have a couple options. You could nest your SplitterWindows, which is kind of confusing, but effective. Or you could use the MultiSplitterWindow widget.
For the first one, I'd do something like this:
Create a main splitter and a sub-splitter
In the sub-splitter, but the first two panels
Put the sub-splitter and the 3rd panel in the main splitter
Or some variation thereof.
EDIT: Here's one example:
import wx
########################################################################
class RandomPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent, color):
"""Constructor"""
wx.Panel.__init__(self, parent)
self.SetBackgroundColour(color)
########################################################################
class MainPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
topSplitter = wx.SplitterWindow(self)
hSplitter = wx.SplitterWindow(topSplitter)
panelOne = RandomPanel(hSplitter, "blue")
panelTwo = RandomPanel(hSplitter, "red")
hSplitter.SplitVertically(panelOne, panelTwo)
hSplitter.SetSashGravity(0.5)
panelThree = RandomPanel(topSplitter, "green")
topSplitter.SplitHorizontally(hSplitter, panelThree)
topSplitter.SetSashGravity(0.5)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(topSplitter, 1, wx.EXPAND)
self.SetSizer(sizer)
########################################################################
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Nested Splitters",
size=(800,600))
panel = MainPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
app.MainLoop()
See also might want to look at wx.SashLayoutWindow: http://www.wxpython.org/docs/api/wx.SashLayoutWindow-class.html
Problem 1:
Create a horzontal vbox sizer. Add the sizers for panel2 and panel3 to that. This will put the panel2 and panel3 next to each other. Then add the horizontal sizer to the splitter as the second item.
Problem 2:
Create another splitter and add to a sizer (I assume splitter is a widget like panel). Then create your other panel and add it to that splitter. So you end up nesting the splitter inside a sizer. (May not need sizer for that though.) Then that sizer is inside the main splitter. You may be able to add the second splitter inside the first.