wxPython centering a button and app crash on close - python

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

Related

Wxpython panel is cropped with only a small box shown at the top left hand corner

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.

wxpython: Hide one of splitterWindow panels

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.

Generate List of All sizerItems Nested in wxPython Sizers

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()

Multiple panels

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.

wxPython GUI BoxSizers

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.

Categories

Resources