How to work with wxPython BoxSizer

Introduction

In wxPython, sizers are responsible for the layout of controls such as buttons, text boxes, combo boxes, panels, and other sizers. There are different sizers. Among them, BoxSizer is very handy to quickly create an app.

A sizer gets its allocated space (area) from its parent. It can be a window, a panel, or another sizer. Then it divides the space among its children based on some rules. There are two types of BoxSizers: horizontal and vertical.

Prerequisites

You need wxPython installed.

python -m pip install wxpython

For the sake of brevity and being focused, I removed the repeated code from examples. To try each example, paste them first in the below code:

import wx
 
class Window(wx.Frame):
    def __init__(self, title):
        super().__init__(parent = None, title = title, size=(500,500))
        self.panel = wx.Panel(self)
  
        ''' 
        
        PASTE EXAMPLES HERE 
        
        '''
        self.panel.SetSizer(sizer)
         
        self.Centre()
        self.Show()
 
         
app = wx.App()
window = Window("WxPython")
app.MainLoop()

Horizontal sizer

A horizontal sizer places controls one after the other in a horizontal line.

(.Get 1)

Proportion

Proportion specifies how much a control takes horizontal space. proportion=0 means the sizer doesn’t change the control size i.e. the control holds its original size. An example for the above picture is

sizer = wx.BoxSizer(wx.HORIZONTAL)

text = wx.StaticText(self.panel, label = "Some random text")
text.SetBackgroundColour((0,255,0))
sizer.Add(text, proportion=0)
    
button1 = wx.Button(self.panel, label="Button 1")
sizer.Add(button1, proportion=0)

button2 = wx.Button(self.panel, label="Button 2")
sizer.Add(button2, proportion=0)

input = wx.TextCtrl(self.panel)
sizer.Add(input, proportion=0)

In the example above, if you drop proportion=0, you will still see the same results because 0 is the default value.

A control with proportion>1 takes all the remaining space.

(.Get 1)

A control with proportion=2 takes twice horizontal space as a control with proportion=1.

(.Get 1)

Alignment

In a horizontal BoxSizer, controls can be aligned vertically:

(.Get 1)

An example for the above picture is:

sizer = wx.BoxSizer(wx.HORIZONTAL)

text = wx.StaticText(self.panel, label = "Some random text")
text.SetBackgroundColour((0,255,0))
sizer.Add(text, proportion=0, flag=wx.ALIGN_TOP)
        
button1 = wx.Button(self.panel, label="Button 1")
sizer.Add(button1, proportion=0, flag=wx.ALIGN_CENTER)

button2 = wx.Button(self.panel, label="Button 2")
sizer.Add(button2, proportion=0, flag=wx.ALIGN_BOTTOM)

input = wx.TextCtrl(self.panel)
sizer.Add(input, proportion=0, flag=wx.EXPAND)

Exapnd and Shaped

Flag EXPAND stretches the control vertically and flag SHAPED enlarges the control and keeps its aspect ratio.

(.Get 1)

See the below example:

sizer = wx.BoxSizer(wx.HORIZONTAL)

text = wx.StaticText(self.panel, label = "Some random text")
text.SetBackgroundColour((0,255,0))
sizer.Add(text, proportion=0)
    
button1 = wx.Button(self.panel, label="Button 1")
sizer.Add(button1, proportion = 0, flag=wx.EXPAND)

button2 = wx.Button(self.panel, label="Button 2")
sizer.Add(button2, proportion = 1, flag=wx.SHAPED)

Border

Within a sizer, we can set borders for each control

(.Get 1)

The code for the above picture is

sizer = wx.BoxSizer(wx.HORIZONTAL)

text = wx.StaticText(self.panel, label = "Some random text")
text.SetBackgroundColour((0,255,0))
sizer.Add(text, proportion=0, flag=wx.RIGHT, border=5)
    
button1 = wx.Button(self.panel, label="Button 1")
sizer.Add(button1, proportion = 0)

button2 = wx.Button(self.panel, label="Button 2")
sizer.Add(button2, proportion = 0, flag=wx.ALL, border=10)

input = wx.TextCtrl(self.panel)
sizer.Add(input, proportion = 0, flag=wx.TOP | wx.LEFT, border=10)

Vertical sizer

Vertical sizer places controls in vertical direction from top to bottom.

(.Get 1)

The code for the above picture is

sizer = wx.BoxSizer(wx.VERTICAL)

text = wx.StaticText(self.panel, label = "Some random text")
text.SetBackgroundColour((0,255,0))
sizer.Add(text, proportion=0)
    
button1 = wx.Button(self.panel, label="Button 1")
sizer.Add(button1, proportion = 0)

button2 = wx.Button(self.panel, label="Button 2")
sizer.Add(button2, proportion = 0)

input = wx.TextCtrl(self.panel)
sizer.Add(input, proportion = 0)

Proportion

The proportion parameter can be used to allocate more space to controls:

(.Get 1)

Alignment

The controls are aligned horizontally with ALIGN flags:

(.Get 1)

The picture above can be reproduced with:

sizer = wx.BoxSizer(wx.VERTICAL)

text = wx.StaticText(self.panel, label = "Some random text")
text.SetBackgroundColour((0,255,0))
sizer.Add(text, proportion=0, flag=wx.ALIGN_LEFT)
    
button1 = wx.Button(self.panel, label="Button 1")
sizer.Add(button1, proportion = 0, flag=wx.ALIGN_CENTER)

button2 = wx.Button(self.panel, label="Button 2")
sizer.Add(button2, proportion = 0, flag=wx.ALIGN_RIGHT)

input = wx.TextCtrl(self.panel)
sizer.Add(input, proportion = 0, flag = wx.EXPAND)

Expand and Shaped

The EXPAND flag stretches a control horizontally, and the SHAPED flag scales the contorl and keeps its aspect ratio:

(.Get 1)

Try this code to see above picture:

sizer = wx.BoxSizer(wx.VERTICAL)

text = wx.StaticText(self.panel, label = "Some random text")
text.SetBackgroundColour((0,255,0))
sizer.Add(text, proportion=0)
    
button1 = wx.Button(self.panel, label="Button 1")
sizer.Add(button1, proportion = 0, flag=wx.EXPAND)

button2 = wx.Button(self.panel, label="Button 2")
sizer.Add(button2, proportion = 1, flag=wx.SHAPED)
Tags ➡ Python

Subscribe

I notify you of my new posts

Latest Posts

Comments

1 comment
Edward Shave 11-Jan-2023
Just writing to thank so much. I was really struggling with sizers until I read your excellent article. Thanks again, Ed