Working with SizedControls

SizedControls is an add-on library provided by wx.lib to help simplify the creation of sizer based layouts. It does this by providing three helper base classes, SizedPanel, SizedFrame, and SizedDialog. All of which hide some of the details about using sizers by overriding some of the virtual methods of wx.Window in order to intercept when child windows are created and to then automatically add them to a sizer that the window has created. This recipe will show how to use the SizedControls to help create a dialog to retrieve an address.

How to do it

Here we will define our custom dialog class by creating a subclass of SizedDialog which will automatically create the Panel and setup all the sizers.

   1 import wx
   2 import wx.lib.sized_controls as sized_ctrls
   3 
   4 class AddressDialog(sized_ctrls.SizedDialog):
   5     def __init__(self, parent, title="Address Form"):
   6         style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER
   7         super(AddressDialog, self).__init__(parent,
   8                                             title=title,
   9                                             style=style)
  10 
  11         # Attributes
  12         self._data = dict(name="", street="", zip="",
  13                           state="", city="")
  14 
  15         # Layout
  16         self.__DoLayout()
  17         self.SetInitialSize((300, -1))
  18 
  19     def __DoLayout(self):
  20         """Setup all the controls"""
  21         # Get the SizedPanel from the SizedDialog
  22         # This must be used as the parent of the controls
  23         # we are going to create next.
  24         pane = self.GetContentsPane()
  25 
  26         # Set the Layout Type
  27         pane.SetSizerType("form")
  28 
  29         # Create the Controls
  30         # Each time through the loop creates one row in the
  31         # dialogs layout ("form" is a two column grid)
  32         for ctrl in ("name", "street", "city",
  33                      "state", "zip"):
  34             lbltext = "%s:" % ctrl.title()
  35             lbl = wx.StaticText(pane, label=lbltext)
  36             lbl.SetSizerProps(valign="center")
  37             txt = wx.TextCtrl(pane, name=ctrl)
  38             txt.SetSizerProps(expand=True)
  39 
  40         # Add the buttons
  41         btnsizer = self.CreateButtonSizer(wx.OK|wx.CANCEL)
  42         self.SetButtonSizer(btnsizer)
  43 
  44     def GetAddress(self):
  45         """Get the address data from the dialog"""
  46         # Update data from controls
  47         for name in self._data:
  48             ctrl = self.FindWindowByName(name)
  49             if ctrl:
  50                 value = ctrl.GetValue()
  51                 self._data[name] = value
  52         # Create a formatted address label
  53         template = "%(name)s\n"
  54         template += "%(street)s\n"
  55         template += "%(city)s, %(state)s %(zip)s"
  56         return template % self._data

How it works

Our AddressDialog class derives from SizedDialog which provides the framework that encapsulates the usage of sizers to help simplify the layout. Let’s start with reviewing what we did in the AddressDialog’s __DoLayout method to see how the SizedControls work.

The first thing we do as part the __DoLayout is call the SizedDialog’s GetContentsPane method. This returns the dialog’s SizedPanel object. This Panel needs to be used as the parent for all the controls we add to the dialog. Next we call the SizedDialog’s SetSizerType method. This method is used to specify the type of sizer the panel will use to perform the layout of our controls. In this case we choose ‘form’ which will create a two column grid layout. We choose this because we are going to have a number of fields, each with a label and an entry field.

The next step is to create all of our controls, the SizedPanel will automatically add them to our layout as they are created as its children. When it does this it dynamically attaches a new method to each object called SetSizerProps. This method can then be used to customize the way the sizer handles each object, such as its proportions and alignments. Since the dialog is going to lay the controls out in a two column grid each time through the loop and create two controls it will end up creating a new row in the layout.

Finally we use the Dialog’s CreateButtonSizer method to create our Ok and Cancel buttons and then add the sizer to the layout with the SizedDialog’s SetButtonSizer method.

Theres more...

Included below are some quick references to the different types of sizers types and properties that SizedControls support.

Sizer Types

The SizedPanel’s SetSizerType method accepts a string that describes the type of layout to do and optionally a dictionary of sizer options. The following table is a quick reference of the possible types.

horizontal

Use a horizontal BoxSizer layout.

vertical

Use a vertical BoxSizer layout.

form

Use a two column FlexGridSizerLayout.

table

Lays controls out in a table. Requires columns and rows specified in the options.

grid

Like ‘form’ but accepts additional options to configure the grids properties.

Sizer Type Options

The following table describes the possible options that can be set in the SetSizerType’s options parameter dictionary (i.e { rows : 3, columns : 5 }).

rows

Integer – number of rows

cols

Integer – number of columns

growable_row

Tuple – (row, proportion)

growable_col

Tuple – (col, proportion)

hgap

Integer – horizontal gap in pixels between columns.

vgap

Integer – vertical gap in pixels between rows.

Sizer Properties

The properties can be set with the SetSizerProps method for controls that are children of a SizedPanel.

proportion

Integer – proportion value

hgrow

Integer – Grow horizontally

vgrow

Integer – Grow vertically

align

Alignment flag bitmask

border

Tuple – (list_of_directions, pixels). (left, right, top, bottom, all)

minsize

Can be “fixed” or “adjust”.

expand

Bool

SizedControls (last edited 2010-12-16 15:20:52 by 74)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.