Wax layout mini-FAQ

This mini-FAQ answers a few questions about the layout for the most commonly containers in Wax, Frame and Panel. The answers may apply to other containers as well, if appropriate.

How do expand and stretch work?

This is a regular source of confusion. In short: expand expands in the direction of the container; stretch expands in the opposite direction. In other words, if you define a Frame with direction='vertical', then a control added with expand=1 will expand vertically, while stretch=1 will make it expand horizontally. For a horizontal panel, these values are reversed.

The following sample code illustrates this:

from wax import *

class MainFrame(Frame):
    def Body(self):
        b = Button(self, "stretch")
        self.AddComponent(b, stretch=1, border=1)

        b = Button(self, "expand")
        self.AddComponent(b, expand=1, border=1)

        b = Button(self, "stretch && expand")
        self.AddComponent(b, stretch=1, expand=1, border=1)
                        
        self.Pack()

app = Application(MainFrame, direction='v')
app.Run()

How does Pack() work? When to call it?

It's simple, actually... when you're done adding controls to a container, you pack it. It makes no difference if the control you add is a container itself... just make sure it's packed before you add it to some other container.

It's not just called on the vanilla Frame and Panel, but on other types of frames and panels as well. Forgetting to call Pack() can lead to strange layout surprises.

However, there is one situation where you don't necessarily have to pack. If a container contains just one control, and the container is not packed, then that control will automatically fill up all the available space given to it by the container. Compare:

Example 1: No packing -- window is resized to (400, 400), button fills up all the space

from wax import *

class MainFrame(Frame):
    def Body(self):
        b = Button(self, "poing")
        self.AddComponent(b)
        # make window big so you see the effect
        self.Size = 400, 400
        
app = Application(MainFrame)
app.Run()

Example 2: Packing after setting the size -- window does not have size (400, 400), but wraps around the normal-sized button, with a little extra space (at least on Windows XP).

from wax import *

class MainFrame(Frame):
    def Body(self):
        b = Button(self, "poing")
        self.AddComponent(b)
        self.Size = 400, 400
        self.Pack()
        
app = Application(MainFrame)
app.Run()

Example 3: Packing before setting size -- the window becomes (400, 400), and a normal-sized button sits in the top left corner; it does not fill up all the space.

from wax import *

class MainFrame(Frame):
    def Body(self):
        b = Button(self, "poing")
        self.AddComponent(b)
        self.Pack()
        self.Size = 400, 400
        
app = Application(MainFrame)
app.Run()

I find expand, stretch and Pack cumbersome. Isn't there a simpler way?

Maybe. The expand/stretch distinction and behavior is confusing, and could be replaced by something clearer. And maybe, in certain cases, it's possible to pack containers automatically. We're currently looking for acceptable, Pythonic solutions to these problems.

Update: Recent versions of Wax support 'h' (horizontal), 'v' (vertical) and 'b' (both) parameters for expand. (Note that this makes stretch obsolete.) So we can write

parent.AddComponent(obj, expand='v', border=1)

and the meaning is clear.