GUI Python with Tkinter – Part 3 – The pack() geometry manager

Now we have a bunch of widgets within out main window (in the test.py file). It looks hideous now. Let’s see how we can arrange them to look better using geometry managers.

There are three Tkinter geometry managers. They are:

  • pack() – Simple to use for simple layouts.
  • grid() – Commonly used geometry manager, table-like layout of management features.
  • place() – Least popular, provides the best control for the absolute positioning of widgets.

The pack() geometry manager

The pack() manager places each widget along the top edge by default. It then repeats the process until all the widgets are accommodated. The geometry manager calculates the bounding box for all the widgets and makes the parent widget large enough to accommodate all the child widgets. When packing the child widgets, the pack() manager distinguishes between the following three kinds of space:

  • The unclaimed space
  • The claimed but unused space
  • The claimed and used space

The commonly used options in the pack() manager are:

  • side – alignment of the widget – LEFT, TOP, RIGHT, and BOTTOM
  • fill – widget can grow in size or not – X, Y, BOTH, and NONE
  • expand – have Boolean values – tkinter.YES, tkinter.NO, 1, 0, True, False
  • anchorNW, N, NE, E, SE, S, SW, W, and CENTER
  • Internal padding – ipadx and ipady for the padding inside widgets and padx and pady for external padding (0 is the default value for all of them)

The most commonly used pack() options are side, fill, and expand. I have created a second file named test02.py where I tried to generate a GUI that looks decent and it shows how side, fill, and expand work.

from tkinter import *
root = Tk()

frame = Frame(root)

Label(frame, text="side and fill options of pack").pack()

Button(frame, text = "B1").pack(side = LEFT, fill = Y)
Button(frame, text = "B2").pack(side = TOP, fill = X)
Button(frame, text = "B3").pack(side = RIGHT, fill = NONE)
Button(frame, text = "B4").pack(side = TOP, fill = BOTH)

frame.pack()

Label (root, text = "expand option of pack").pack()
Button(root, text = "No expand").pack()
Button(root, text = "No fill x - expand").pack(expand = 1)
Button(root, text = "fill x - expand").pack(fill = X, expand = 1)

root.mainloop()

Run the file in the terminal and you will get a decent looking GUI as shown below.

The pack() geometry manager

Resize the root window to see the effect on the buttons.

The B1 button in the root frame, captures the left side area of the frame, expands, and fills the Y dimension. The fill = Y claims all the area that it wants and fills the Y dimension.

The frame is packed with a plain pack() method, with no pack() options. It takes the minimum space required to accommodate all of its child widgets. If you increase the size of the root window the buttons (B1, B2, B3, and B4) within frame do not fill or expand with the root window.

The position of the B2, B3, and B4 buttons is based on the side and fill options.

The next three buttons (that are not part of the frame but part of the root) show the expand option in action. The expand = 1 means that the button moves its place on resizing the window.

The pack() manager places the widget at the center of the available space or the packing box. If you want to change that you might want to use the anchor attribute which positions a widget relative to a reference point.

Note:
The value for most of the Tkinter geometry manager attributes can either be specified in capital letters without quotes (side = TOP) or in small letters within quotes (side = “top”). Single or double quotes are allowed.

Note:
Usually, when you want to place widgets in a top-down manner or side by side, the pack() geometry manager is a very good option to use.

Below is an example that I place in a file named test03.py.

from tkinter import *
root = Tk()

frame = Frame(root)

# placing widgets top-down
Button(frame, text = 'Motorcycles').pack(fill = X)
Button(frame, text = 'Power of the road').pack(fill = X)
Button(frame, text = 'CATCH ME IF U CAN').pack(fill = X)

# placing widgets side by side
Button(frame, text = 'Honda').pack(side = LEFT)
Button(frame, text = 'Yamaha').pack(side = LEFT)
Button(frame, text = 'Suzuki').pack(side = LEFT)

frame.pack()
root.mainloop()

Run the file in the terminal to see the result.

The pack() geometry manager

Leave a Reply