When I started to work with pyGTK, I had the impression that documentation is not as abundant and detailed as for learning the standard Python language in general. Among the most popular tutorials are an introduction to pyGTK by tutorialspoint.com and (so far my favourite) an intro by readthedocs.io. While these tutorials will explain the technical basics, I would have sometimes preferred a few more graphical illustrations to understand the effects of different commands to arrange graphical elements (‘widgets’) in a window.
A method frequently needed to arrange widgets in so called
Box containers that pops up in early introductory examples is
pack_start. I had a particular hard time of imagining what effects each of its parameters would have. So here’s a graphical illustration.
The function parameters
Taking the examples from the pyGTK tutorials and the official GTK documentation (which is not Python specific, but C++), the template for the
pack_start function is as follows:
box.pack_start(childWidget, expand, fill, padding)
boxis the destination
Boxobject into which the
childWidgetcan be almost any widget – a Label, a CheckButton, a ComboBox, an image etc.
expandis of type boolean. If set to
True, Gtk will distribute all child objects with equal spaces in between. The name is a quite misleading, because the effect is not to alter the size of the object. Rather, the parameter influences the positioning of the object (with respect to the height of the
VBoxor the width of an
HBox).Those who do PowerPoint will know the horizontally and vertically arrange buttons which have the same effect:
- In case we have a
VBox, the objects each object will be horizontally stretched to the full width of the VBox, and they will vertically be arranged so that the space before and after each object is identical.
- In case we have an
HBox, each widget will be vertically stretched to the full height of the box. Horizontally, the objects will be arranged so that the space before and after each object has the same width.
- In case we have a
- Similar ill-labelled is the
fillparameter. First of all, the parameter is without any effect if
expandis set to
False. This parameter actually stretches each widget arranged along the Box object so that any blank space is filled (evidently, this does only make sense when the objects are aligned with equal spaces along the Box by
paddingparameter has an equally strange defintion. According to the GTK+3 reference (which again isn’t Python specific) padding is basically the amount of Pixels that a widget is shifted along the orientation of the Box (i.e. horizontally to the right in case of an HBox, vertically to the bottom in case of a VBox) “over and above the global amount specified by the spacing property”. The spacing property is by default set to 0 and determines the distance of a widget from its neighbours.
A less confusing way to name the function parameters would be something like:
box.pack_start(widget, arrange, stretch, padding)
The Basic Code
The code I am using produces 4 objects (a Button, a CheckButton, a Label and a ComboBox) and puts them all in a VBox that fills the whole main window. As a consequence, the pack_start function is called 4 times – once each for placing the 4 objects.
from gi.repository import Gtk
win = Gtk.Window(title='Demo')
vbox = Gtk.VBox(spacing=10)
btn = Gtk.Button("Do not click here")
chk = Gtk.CheckButton("Mit alles...")
lbl = Gtk.Label("Alles für den Dackel")
cmb = Gtk.ComboBox()
vbox.pack_start(chk, False, True, 0)
vbox.pack_start(btn, False, True, 0)
vbox.pack_start(lbl, False, True, 0)
vbox.pack_start(cmb, False, True, 0)
arrange = False
We start with calling
arrange=False as in the above base example:
vbox.pack_start(chk, True, False, 0)
vbox.pack_start(btn, True, False, 0)
vbox.pack_start(lbl, True, False, 0)
vbox.pack_start(cmb, True, False, 0)
Note without any arranging along the orientation of the Box object, the
stretch parameter is completely without any effect whether it’s set to
False. The left Window in the image below is with
padding=0, the right image is with
padding=20 for the second
pack_start command that packs the Button.
As expected, each widget is packed along the vertical orientation of the VBox. Note that
pack_start by enforces stretching each widget in its width to match the full width of the VBox. In case an HBox,
pack_start would stuff any widget without any horizontal space from left to right but would stretch any widget vertically to meet the height of the HBox.
We also see, that setting padding to a non-zero value enforces the space to the neighboring items before and after the widget that was packed with that padding value. The (vertical) distance between the preceding CheckBox and the Button has increased as well as the (vertical) distance between the Button and the following Label.
arrange = True, stretch = False
stretch=False, Gtk spreads the widgets evenly on the vertical axis (in case of a VBox), with equal vertical white space being put before and after each widget.
Again to test for the effect of a non-zero
padding parameter, we have set
padding=20 (this time for the first element packed which is the CheckBox). This increases the vertical space above and below the CheckBox by 20px while the remaining 3 widgets are equally spaced apart along the remaining vertical space.
arrange = True, stretch = True
True will first distribute all widgets evenly spaced along the orientation of the box (i.e. vertically in case of a VBox and horizontally in case of an Hbox) and then stretch any widgets to fill the gaps left arranging the widgets with equal spacing.
Again, in order to observe the effect of the
padding was set to
20 for one single widget (this time the Label widget, i.e. the 3rd element to be placed in the containing VBox) while all the others were set to
As expected setting
padding=20 for the Label widget with
arrange=True will first align all widgets with equal vertical free space among them, then
stretch=True will stretch each widget equally in height (for VBox, width for Hbox) until all empty space between the widgets is consumed. Finally the Label will be extended 20px up and 20px down at the expanse of shrinking all remaining Labels proportionally.