The box sizer is the simplest and most flexible of the sizers provided by wxPy-thon. A box sizer is a single vertical column or horizontal row, with the widgets being laid out in a line from left to right or top to bottom. Although this may sound too simplistic to be of any use, the real power of the box sizer comes from the ability to nest sizers inside each other, giving you the advantage of being able to easily place a different number of items in each row or column. And since each sizer is a separate entity, you have more flexibility in terms of layout. Despite the seeming simplicity, for most applications a vertical sizer with horizontal sizers nested inside will allow you to create your needed layout.
Figures 11.11-11.14 show several examples of simple box sizers. Each of these frames has been slightly resized by the user before the screen shot, to show how each sizer responds to the growth. Figure 11.11 shows a horizontal box sizer and figure 11.12 shows the same widgets in a vertical box sizer.
Figure 11.12 A vertical box sizer
Figure 11.13 shows a vertical sizer with one widget that is set to expand and fill the available vertical space. Figure 11.14 shows a vertical sizer with two widgets set to grab the available vertical space in different proportions.
The code to generate all four sizer frames is given in listing 11.9.
Listing 11.9 Generating a number of box sizers import wx from blockwindow import BlockWindow labels = "one two three four".split()
class TestFrame(wx.Frame): title = "none"
sizer = self.CreateSizerAndWindows()
class VBoxSizerFrame(TestFrame): title = "Vertical BoxSizer"
def CreateSizerAndWindows(self): <1—1 The vertical sizer sizer = wx.BoxSizer(wx.VERTICAL) for label in labels:
bw = BlockWindow(self, label=label, size=(2 00,3 0)) sizer.Add(bw, flag=wx.EXPAND) return sizer class HBoxSizerFrame(TestFrame): title = "Horizontal BoxSizer"
The horizontal sizer def CreateSizerAndWindows(self):
sizer = wx.BoxSizer(wx.HORIZONTAL)
for label in labels:
bw = BlockWindow(self, label=label, size=(75,30)) sizer.Add(bw, flag=wx.EXPAND) return sizer class VBoxSizerStretchableFrame(TestFrame): title = "Stretchable BoxSizer"
sizer = wx.BoxSizer(wx.VERTICAL) for label in labels:
bw = BlockWindow(self, label=label, sizer.Add(bw, flag=wx.EXPAND)
Horizontal with free space size=(200,30))
# Add an item that takes all the free space bw = BlockWindow(self, label="gets all free space", size=(2 00,3 0)) sizer.Add(bw, 1, flag=wx.EXPAND) return sizer class VBoxSizerMultiProportionalFrame(TestFrame): <— Proportional sizing title = "Proportional BoxSizer"
sizer = wx.BoxSizer(wx.VERTICAL) for label in labels:
bw = BlockWindow(self, label=label, size=(2 00,3 0)) sizer.Add(bw, flag=wx.EXPAND)
# Add an item that takes one share of the free space bw = BlockWindow(self, label="gets 1/3 of the free space", size=(200,30)) sizer.Add(bw, 1, flag=wx.EXPAND)
# Add an item that takes 2 shares of the free space bw = BlockWindow(self, label="gets 2/3 of the free space", size=(200,30)) sizer.Add(bw, 2, flag=wx.EXPAND) return sizer app = wx.PySimpleApp()
frameList = [VBoxSizerFrame, HBoxSizerFrame, VBoxSizerStretchableFrame, VBoxSizerMultiProportionalFrame] for klass in frameList: frame = klass() frame.Show() app.MainLoop()
After seeing the previous sizer examples, most of this code should make sense. Box sizers are instances of the class wx.BoxSizer, which is a direct subclass of wx.Sizer, adding almost no new methods. The constructor for wx.BoxSizer takes one argument:
The orient parameter represents the direction of the sizer, and can take either the value wx.vertical or wx.horizontal. The only new method defined for box sizers is GetOrientation() which returns the integer constant value as it was set in the constructor. You cannot change the orientation of a box sizer once it has been created. All other functions of a box sizer use the common sizer methods discussed earlier in this chapter
The layout algorithm for a box sizer treats the sizer's primary direction (defined by its orientation when constructed) differently from its secondary direction. In particular, the proportion parameter only applies when the sizer is grown or shrunk along its primary direction, while the wx.EXPAND flag only applies when the sizer changes size in its secondary direction. In other words, when a vertical box sizer is stretched vertically, the proportion parameter passed to each of the Add() method calls determines how each item will grow or shrink vertically. The proportion parameter affects a horizontal box sizer the same way, except for affecting horizontal growth of the sizer and its items. On the other hand, growth in the secondary direction is controlled by using the wx.EXPAND flag for items, so items in a vertical box sizer will only grow horizontally if they have the wx.EXPAND flag set, otherwise the items remain at their minimum or best size. Figure 6.7 in chapter 6 illustrates this process graphically.
In box sizers proportional item growth works similarly to the way it works with flex grid sizers, with some exceptions. First, the box sizer proportional behavior is determined using the proportion parameter when the widget is added to the sizer—you do not need to separately specify it as growable the way that you would with a flex grid sizer. Second, the behavior of the sizer for proportions of 0 is different. In a box sizer, a proportion of 0 means that the widget will not be resized from its minimum or best size in the primary dimension, but it can still grow in the secondary dimension if the wx.EXPAND flag is used. When the box sizer calculates the layout of its items for the primary dimension it first adds up the space needed by the fixed size items, which are those with a proportion of 0. The remaining space is divided between the proportional items, with those with a larger proportion value getting the larger amount of the free space.
Was this article helpful?