I an trying to get a minimal wxPython GUI working, but I failed so far in achieving the desired result. What I want is to expand the text input widget in the first line so that it fills up the width of the dialog/frame. I want the input box become as wide so that its right border aligns with the right border of the button in the (wider) second line.
I thought that's what the wx.EXPAND flag is for when adding to the sizer, but apparently I am doing something wrong. Here is my code in a working example:
import wx
class MyApp(wx.Frame):
def __init__(self):
super(MyApp, self).__init__(None, title="wxPython Sizers", style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
self.panel = wx.Panel(self)
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
# First line, should expand it's width to fit the second line
panel_sizer = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
text = wx.StaticText(self.panel, label="Short label:")
hbox.Add(text, flag=wx.ALIGN_CENTER_VERTICAL)
numtext = wx.TextCtrl(self.panel)
hbox.Add(numtext, flag=wx.LEFT | wx.EXPAND, border=10)
panel_sizer.Add(hbox)
# The second, wider line
hbox = wx.BoxSizer(wx.HORIZONTAL)
text = wx.StaticText(self.panel, label="This is a long label:")
hbox.Add(text, flag=wx.ALIGN_CENTER_VERTICAL)
img_folder_button = wx.Button(self.panel, label="Button")
hbox.Add(img_folder_button, flag=wx.LEFT, border=10)
panel_sizer.Add(hbox, flag=wx.TOP, border=15)
# We need only this one sizer for the panel
self.panel.SetSizer(panel_sizer)
# Set final dialog layout
self.main_sizer.Add(self.panel, proportion=1, flag=wx.ALL | wx.EXPAND, border=15)
self.SetSizer(self.main_sizer)
self.Layout()
self.Fit()
self.Center()
self.Show()
if __name__ == "__main__":
wxapp = wx.App()
myApp = MyApp()
wxapp.MainLoop()
Be consistent with the use of proportion and border.
Rather than re-use hbox declare them separately and expand the button as well in case the user the expands the frame.
import wx
class MyApp(wx.Frame):
def __init__(self):
super(MyApp, self).__init__(None, title="wxPython Sizers", style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
self.panel = wx.Panel(self)
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
# First line, should expand it's width to fit the second line
panel_sizer = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
text = wx.StaticText(self.panel, label="Short label:")
hbox1.Add(text, flag=wx.ALIGN_CENTER_VERTICAL)
numtext = wx.TextCtrl(self.panel)
hbox1.Add(numtext, proportion=1, flag=wx.LEFT | wx.EXPAND, border=15)
# The second, wider line
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
text = wx.StaticText(self.panel, label="This is a long label:")
hbox2.Add(text, flag=wx.ALIGN_CENTER_VERTICAL)
img_folder_button = wx.Button(self.panel, label="Button")
hbox2.Add(img_folder_button, proportion=1, flag=wx.LEFT | wx.EXPAND, border=15)
panel_sizer.Add(hbox1, flag=wx.TOP | wx.EXPAND, border=15)
panel_sizer.Add(hbox2, flag=wx.TOP | wx.EXPAND, border=15)
# We need only this one sizer for the panel
self.panel.SetSizer(panel_sizer)
# Set final dialog layout
self.main_sizer.Add(self.panel, proportion=1, flag=wx.ALL | wx.EXPAND, border=15)
self.SetSizerAndFit(self.main_sizer)
self.Layout()
self.Center()
self.Show()
if __name__ == "__main__":
wxapp = wx.App()
myApp = MyApp()
wxapp.MainLoop()
You are expanding your numtext inside the horizontal box sizer. That's correct. But you must also expand your horizontal box sizer inside the vertical box sizer.
Related
I've been trying to learn wxPython and just can't get my head around sizers. As an exercise, I'm trying to lay out three panels so they appear inside of each other. Firstly, I've used an image editing program to show an approximation window I'm trying to achieve:
This is the code I'm using to attempt this:
import wx
class MyApp(wx.Frame):
def __init__(self):
super().__init__(None, title="Test")
outer_sizer = wx.BoxSizer()
outer_panel = wx.Panel(self)
outer_panel.SetBackgroundColour(wx.Colour("#94f7e7"))
inner_panel = wx.Panel(outer_panel)
inner_panel.SetBackgroundColour(wx.Colour("#b8e8a9"))
inner_sizer = wx.BoxSizer()
inner_inner_panel = wx.Panel(inner_panel)
inner_inner_panel.SetBackgroundColour(wx.Colour("#cbebf5"))
inner_inner_sizer = wx.BoxSizer()
inner_inner_sizer.Add(inner_inner_panel, 1, wx.ALL | wx.EXPAND, 20)
inner_sizer.Add(inner_inner_panel, 1, wx.ALL | wx.EXPAND, 20)
outer_sizer.Add(inner_sizer, 1, wx.EXPAND)
outer_panel.SetSizer(outer_sizer)
if __name__ == '__main__':
app = wx.App()
ma = MyApp()
ma.Show()
app.MainLoop()
And this is what it actually results with:
The reason I had hoped the above code would work is because I had some success with the following code:
import wx
class MyApp(wx.Frame):
def __init__(self):
super().__init__(None, title="Test")
outer_sizer = wx.BoxSizer()
outer_panel = wx.Panel(self)
outer_panel.SetBackgroundColour(wx.Colour("#94f7e7"))
inner_panel = wx.Panel(outer_panel)
inner_panel.SetBackgroundColour(wx.Colour("#b8e8a9"))
inner_sizer = wx.BoxSizer()
inner_sizer.Add(inner_panel, 1, wx.ALL | wx.EXPAND, 20)
outer_sizer.Add(inner_sizer, 1, wx.EXPAND)
outer_panel.SetSizer(outer_sizer)
if __name__ == '__main__':
app = wx.App()
ma = MyApp()
ma.Show()
app.MainLoop()
Which produced this:
Now obviously I'm not getting something. I'm hoping the above will enable some kind soul to identify what I'm not understanding.
None of the related posts here seem to help much as they don't ever nest panels more than one layer.
Ok, the first step will be putting in just one panel and make a hierarchy of 3 sizers. This works exactly as you expect, only you cannot change the background color of a sizer:
def __init__(self):
super().__init__(None, title="Test")
sz1 = wx.BoxSizer()
sz2 = wx.BoxSizer()
sz3 = wx.BoxSizer()
p1 = wx.Panel(self)
p1.SetBackgroundColour(wx.RED)
sz3.Add(p1, 1, wx.ALL | wx.EXPAND, 20)
sz2.Add(sz3, 1, wx.ALL | wx.EXPAND, 20)
sz1.Add(sz2, 1, wx.ALL | wx.EXPAND, 20)
self.SetSizer(sz1)
Now, to really use the panels you have to put the panel into sizer (sizer.Add) and than the sizer into the panel (panel.SetSizer) and than into a sizer and so on... Just be careful about setting the right parent.
def __init__(self):
super().__init__(None, title="Test")
sz1 = wx.BoxSizer()
sz2 = wx.BoxSizer()
sz3 = wx.BoxSizer()
p1 = wx.Panel(self)
p2 = wx.Panel(p1)
p3 = wx.Panel(p2)
p1.SetBackgroundColour(wx.RED)
p2.SetBackgroundColour(wx.GREEN)
p3.SetBackgroundColour(wx.BLUE)
sz3.Add(p3, 1, wx.ALL | wx.EXPAND, 20) # innermost
p2.SetSizer(sz3)
sz2.Add(p2, 1, wx.ALL | wx.EXPAND, 20)
p1.SetSizer(sz2)
sz1.Add(p1, 1, wx.ALL | wx.EXPAND, 0)
self.SetSizer(sz1)
I am using Hide() and Show() from wx to do the "next page" effect by hiding a panel and showing the next one but in the same frame (not very sure if I am doing it correctly though). At certain pages, the panel is just a small cropped version at the top left corner while some other panels can work normally (display the full thing). How do I solve this problem?
I saw something on stackoverflow about child/parent of the panel or frame and tried changing my code but it does not work, not very sure about how to do it correctly.
class MyPanel(wx.Panel):
def __init__(self, parent):
#Constructor
wx.Panel.__init__(self, parent=parent)
#self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
#This is for older versions of wx
self.frame = parent
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
self.Layout()
def OnEraseBackground(self, evt):
#Add background pic
#From ColourDB.py
dc = evt.GetDC()
if not dc:
dc = wx.ClientDC(self)
rect = self.GetUpdateRegion().GetBox()
dc.SetClippingRect(rect)
dc.Clear()
bmp = wx.Bitmap("RszHive.jpg")
dc.DrawBitmap(bmp, 0, 0)
class StartPage(wx.Frame):
def __init__(self, current_dt):
#Settings for frame
super().__init__(parent=None, title='Test', size=(850,790))
#setting up main panel (home page)
self.panel = MyPanel(self)
self.current_dt = current_dt
#so that frame will be in the center of the screen
self.Center()
self.vert_sizer = wx.BoxSizer(wx.VERTICAL)
from Database import DataBase, OperatingHours, GetDayTime, GetMenuByDayTime
dDataBase = DataBase("Full_Menu_Database.txt")
dOperatingHours = OperatingHours("Operating Hours.txt")
# Convert to a tuple needed for the functions
tDayTime = GetDayTime(self.get_dt())
# Function to get menu dictionary by date and time
# Will return an empty dictionary if no food/stores are available
self.stores_open = GetMenuByDayTime(dDataBase, dOperatingHours, tDayTime)
if self.stores_open == {}:
self.ophours = wx.StaticText(self.panel, -1, style=wx.ALIGN_CENTER)
self.ophours.SetLabel("Test")
self.ophours_font = wx.Font(19, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
self.ophours.SetFont(self.ophours_font)
self.vert_sizer.Add(self.ophours, 0, wx.ALL | wx.CENTER, 10)
else:
self.store_names, self.stores_ = [], []
for onestorename in self.stores_open.keys():
self.store_names.append(onestorename)
self.stores_.append(self.stores_open[onestorename])
#btn for store1
store_btn1 = wx.Button(self.panel, label= self.store_names[0])
store_btn1.Bind(wx.EVT_BUTTON, self.click_store1)
self.vert_sizer.Add(store_btn1, 0, wx.ALL | wx.CENTER, 5)
#btn for store2 if have
if len(self.store_names) > 1:
store_btn2 = wx.Button(self.panel, label=self.store_names[1])
store_btn2.Bind(wx.EVT_BUTTON, self.click_store2)
self.vert_sizer.Add(store_btn2, 0, wx.ALL | wx.CENTER, 5)
# btn for store3 if have
if len(self.store_names) > 2:
store_btn3 = wx.Button(self.panel, label=self.store_names[2])
store_btn3.Bind(wx.EVT_BUTTON, self.click_store3)
self.vert_sizer.Add(store_btn3, 0, wx.ALL | wx.CENTER, 5)
# btn for store4 if have
if len(self.store_names) > 3:
store_btn4 = wx.Button(self.panel, label=self.store_names[3])
store_btn4.Bind(wx.EVT_BUTTON, self.click_store4)
self.vert_sizer.Add(store_btn4, 0, wx.ALL | wx.CENTER, 5)
# btn for store5 if have
if len(self.store_names) > 4:
store_btn5 = wx.Button(self.panel, label=self.store_names[4])
store_btn5.Bind(wx.EVT_BUTTON, self.click_store5)
self.vert_sizer.Add(store_btn5, 0, wx.ALL | wx.CENTER, 5)
self.SetSizer(self.vert_sizer)
self.Layout()
self.Show()
Picture of what the panel looks like when i run the code
#igor is correct a call to Layout will get the job done.
Here is an example:
Click on the displayed panel to swap to the other one.
import wx
class MyPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.panel = wx.Panel(self)
self.btn = wx.Button(self.panel, label="Panel 1", size=(250,75))
self.btn.Bind(wx.EVT_BUTTON, self.switch)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox1.Add(self.btn)
self.panel.SetSizer(vbox1)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.panel)
self.SetSizer(vbox)
self.Show()
def switch(self, event):
self.parent.Swap()
class MyOtherPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.panel = wx.Panel(self)
self.btn = wx.Button(self.panel, label="Panel 2", size=(175,250))
self.btn.Bind(wx.EVT_BUTTON, self.switch)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox1.Add(self.btn)
self.panel.SetSizer(vbox1)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.panel)
self.SetSizer(vbox)
self.Show()
self.panel.Hide()
def switch(self, event):
self.parent.Swap()
class PanelSwitcher(wx.Frame):
def __init__(self):
super().__init__(None)
vbox = wx.BoxSizer(wx.VERTICAL)
self.panel1 = MyPanel(self)
self.panel2 = MyOtherPanel(self)
vbox.Add(self.panel1)
vbox.Add(self.panel2)
self.SetSizer(vbox)
self.Show()
def Swap(self):
if self.panel1.panel.IsShown():
self.panel1.panel.Hide()
self.panel2.panel.Show()
else:
self.panel2.panel.Hide()
self.panel1.panel.Show()
self.Layout()
if __name__ == "__main__":
app = wx.App()
PanelSwitcher()
app.MainLoop()
I also had the problem a very long time and did not know the solution. The sizers did not work (as I expected)
For me, the problem was, that the panel had no (or the incorrect size). The solution was eiter:
panel.Fit()
or
panel.SetSize(x,y)
Another possibility was, to first add the panel into a sizer. And then set them to the frame.
Afterwards put the buttons into the sizer - and add them to the panel.
This also solves the incorrect size of the panel.
I have a simple application with wx.Notebook, it looks like this:
To lay out its child elements, I used wx.GridBagSizer - and it works perfectly. However, I encountered a small but annoying issue. When I expand the window of wx.Notebook, it does not expand all the elements and results in window like this one below:
Which is not what I want actually. How should my modify my code to be able to expand all the child elements when I resize the window? Cheers :)
My code is quite simple:
import wx
import wx.richtext
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title='wx.Notebook')
book = wx.Notebook(self)
page = MyPage(parent=book)
book.AddPage(page, 'Page 1')
book.AddPage(MyPage(book),'Page 2')
book.AddPage(MyPage(book),'Page 3')
self.SetSize(wx.Size(320,250))
self.Centre()
class MyPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, size=(0,0))
# create sizer to add a border
bagSizer = wx.GridBagSizer(15, 10)
mainSizer = wx.BoxSizer(wx.VERTICAL)
label = wx.StaticText(self, label="Text:")
self.content1 = wx.TextCtrl(self, size=(300, 20))
self.content2 = wx.richtext.RichTextCtrl(self, size=(300, 100), style=wx.TE_MULTILINE)
bagSizer.Add(self.content1, pos=(0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)
bagSizer.Add(label, pos=(1, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)
bagSizer.Add(self.content2, pos=(2, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM | wx.EXPAND, border=5)
self.SetSizer(bagSizer)
app = wx.App(False)
MyFrame().Show()
app.MainLoop()
You must tell your GridBagSizer which rows and columns are growable. Try:
bagSizer.AddGrowableRow(2)
bagSizer.AddGrowableCol(0)
self.SetSizer(bagSizer)
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.
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.