Table of Contents
When creating an application, you'll want to put more than one
widget inside a window. Our first helloworld example only used one widget so
we could simply use the gtk.Container
add() method to "pack" the widget into the window. But
when you want to put more than one widget into a window, how do you control
where that widget is positioned? This is where packing comes in.
Most packing is done by creating boxes. These are invisible widget containers that we can pack our widgets into which come in two forms, a horizontal box, and a vertical box. When packing widgets into a horizontal box, the objects are inserted horizontally from left to right or right to left depending on the call used. In a vertical box, widgets are packed from top to bottom or vice versa. You may use any combination of boxes inside or beside other boxes to create the desired effect.
To create a new horizontal box, we use a call to
gtk.HBox(), and for vertical boxes,
gtk.VBox() . The pack_start() and
pack_end() methods are used to place objects inside of
these containers. The pack_start() method will start at
the top and work its way down in a vbox, and pack left to right in an hbox.
The pack_end() method will do the opposite, packing
from bottom to top in a vbox, and right to left in an hbox. Using these
methods allows us to right justify or left justify our widgets and may be
mixed in any way to achieve the desired effect. We will use
pack_start() in most of our examples. An object may be
another container or a widget. In fact, many widgets are actually containers
themselves, including the button, but we usually only use a label inside a
button.
You may find when working with containers that the size (and aspect ratio) of your widget isn't quite what you would expect. That's an intentional consequence of the GTK+ box model. The size of any given widget is determined both by by how it packs among the widgets around it and whether or not its container offers it the possibility to expand and fill space available to it.
if you have a container a single child, this child will take up all its space minus its border:
If you have a container (say a VBox or HBox) with two (or more) children, they will fight[1] to determine who takes up more space:
How much each one actually gets is determined by:
the default and requested sizes of the widgets, which normally depends on their contents (for labels, in particular).
the expand and fill arguments supplied to
add() or
pack_start/pack_end(),
all three of which we will describe in more detail later in this
chapter:
expand=True means "I will
fight for space"
expand=False means "I don't want more space"
fill=True means "If I got
more space, I will occupy it with my content"
fill=False means "If I got
more space, leave it blank"
This is important to understand when assembling your interfaces, and is the most peculiar thing about GTK+ programming to a newbie; although the packing-based widget geometry is more complex to understand initially than fixed-width layouts, it is superior because GTK+ windows actually resize properly.
To get an intuitive grasp of the box model, spend some time experimenting with the "packing" tab in Glade.
[1] A cute analogy; in reality fill, expansion, requested sizes, widget expansion semantics, container packing semantics, electron spins and lunar cycles are computed to determine how much space each widget wins.