Tkinter Pack

Summary: in this tutorial, you’ll learn about the Tkinter pack geometry manager and how to use it to arrange widgets on a window.

Introduction to the Tkinter pack geometry manager

Tkinter uses the geometry manager to organize widgets on a window. Tkinter supports three geometry managers:

The pack geometry manager organizes widgets in blocks before placing them on the container widget, which can be the main window or a frame.

The pack geometry manager has many options that arrange the widgets:

  • Side
  • Expand
  • Fill
  • ipadx, ipady
  • padx, pady
  • Anchor

Before diving into each option, you need to understand the x and y coordinates of the window:

The top left corner of the window is the origin with the coordinate (0,0). The x-coordinate increments from left to right and the y-coordinate increments from top to bottom.

Tkinter pack parameters

We’ll create a simple program to illustrate how the pack geometry manager works:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')

label1.pack()
label2.pack()
label3.pack()

root.mainloop()Code language: JavaScript (javascript)

The program has a main window with three labels with red, green, and blue background colors.

To use the pack geometry manager, you call the pack() of the widget. By default, the pack geometry manager places widgets in one direction vertically from top to bottom.

Side

The side parameter determines the direction of the widgets in the pack layout.

The side parameter has four options:

  • 'top': arrange widgets from top to bottom vertically.
  • 'bottom': arrange widgets from bottom to top vertically.
  • 'left': arrange widgets from left to right horizontally.
  • 'right': arrange widgets from right to left horizontally.

The side defaults to 'top', arranging the widget vertically from top to bottom.

In addition to the string constants, you can use the predefined constants provided by the Tkinter module:

  • tk.TOP
  • tk.BOTTOM
  • tk.LEFT
  • tk.RIGHT

Note that we imported the Tkinter module as tk.

The following program explicitly sets the side to 'top' that arranges the labels vertically from top to bottom:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')

label1.pack(side=tk.TOP)
label2.pack(side=tk.TOP)
label3.pack(side=tk.TOP)

root.mainloop()Code language: JavaScript (javascript)

When you change the side to tk.BOTTOM, the pack arranges the labels from bottom to top vertically:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')

label1.pack(side=tk.BOTTOM)
label2.pack(side=tk.BOTTOM)
label3.pack(side=tk.BOTTOM)

root.mainloop()Code language: JavaScript (javascript)

Output:

The side tk.LEFT arranges the labels from left to right:

The side tk.RIGHT arranges the labels from right to left:

Widget spaces

In Tkinter, there are two kinds of spaces:

  • The space a widget can occupy
  • The space a widget will occupy.

By default, a widget will take only the necessary space to display its content. However, a widget can occupy more space.

For example, a Label widget will be only as big as the text. The background color shows that each label has a different width because the length of its text is different.

Expand

The expand determines whether the widget should expand to occupy any extra spaces allocated to the container.

If the expand is set to True, the widget will expand, and if set to False, it will not. The expand parameter defaults to False.

The expand parameter is highly dependent on the side parameter.

The following table illustrates the dependencies between the side and the expand parameters when it comes to the space of the widget.

SideExpand
Top (or Bottom)The widget can be as wide as the container, the expand will determine the height of the widget.
Left (or Right)The widget can be as high as the container, the expand will determine the width of the widget.

The following program places the Label widgets vertically from top to bottom and sets the expand parameter of the first Label widget to True and the other two Label widgets to False:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')

label1.pack(side=tk.TOP, expand=True)
label2.pack(side=tk.TOP, expand=False)
label3.pack(side=tk.TOP, expand=False)

root.mainloop()
Code language: PHP (php)

Because we set the expand parameter of the first Label to true, it occupies the entirely vertical space and pushes the other two Label widgets down to the bottom:

The following program places the Label widgets horizontally from left to right and sets the expand parameter of the first Label widget to True and the other two Label widgets to False:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')

label1.pack(side=tk.LEFT, expand=True)
label2.pack(side=tk.LEFT, expand=False)
label3.pack(side=tk.LEFT, expand=False)

root.mainloop()Code language: PHP (php)

Because we set the expand parameter of the first Label to true, it occupies the entirely horizontal space and pushes the other two Label widgets to the right:

tkinter pack layout side left, expand true

If you set the expand parameter of the three Label widgets to True, they will take up even horizontal spaces:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')

label1.pack(side=tk.LEFT, expand=True)
label2.pack(side=tk.LEFT, expand=True)
label3.pack(side=tk.LEFT, expand=True)

root.mainloop()
Code language: PHP (php)

Output:

Fill

The fill determines if a widget will occupy the available space. It accepts the following values: ‘x’, ‘y’, ‘both’, and ‘none’. By default, the fill is ‘none’.

fillEffect
‘none’The widget will not expand to fill any extra space. It only takes up space that fits the content.
‘x’The widget will expand horizontally to fill any extra space along the x-axis.
‘y’The widget will expand vertically to fill any extra space along the y-axis.
‘both’The widget will expand both horizontally and vertically to fill any extra space in both directions.

The following program illustrates how the fill parameter works:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Fill',bg='blue', fg='white')
label4 = tk.Label(master=root, text='Demo',bg='purple', fg='white')

label1.pack(side=tk.TOP, expand=True, fill=tk.X)
label2.pack(side=tk.TOP, expand=True, fill=tk.Y)
label3.pack(side=tk.TOP, expand=True, fill=tk.NONE)
label4.pack(side=tk.TOP, expand=True, fill=tk.BOTH)


root.mainloop()
Code language: PHP (php)

Output:

tkinter pack fill demo

In this example, we arrange the Label widgets vertically from top to bottom. The expands of all the Label widgets are set to True.

  • The first Label widget has the fill value of tk.X, allowing it to fill extra spaces along the x-axis.
  • The second Label widget has the fill value of tk.Y, allowing it to fill extra spaces along the y-axis.
  • The third Label widget has the fill value of tk.NONE, indicating that it does not expand to fill any extra space.
  • The fourth Label widget has the fill value of tk.BOTH, enabling it to occupy any additional space in both horizontal and vertical directions.

Internal paddings: ipadx & ipady

The ipadx and ipady parameters create internal paddings for widgets:

  • ipadx creates padding left and right, or padding along the x-axis.
  • ipady creates padding top and bottom, or padding along the y-axis.

For example, the following program uses ipadx and ipady parameters to set the internal paddings of each Label widget:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Pack',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack',bg='green', fg='white')
label3 = tk.Label(master=root, text='Pack',bg='blue', fg='white')
label4 = tk.Label(master=root, text='Pack',bg='purple', fg='white')

label1.pack(side=tk.LEFT)
label2.pack(side=tk.LEFT, ipadx=40)
label3.pack(side=tk.LEFT, ipady=40)
label4.pack(side=tk.LEFT, ipadx=80, ipady=80)

root.mainloop()Code language: Python (python)

Output:

tkinter pack ipadx ipady

External paddings: padx and pady

The padx and pady parameters allow you to specify padding to be added horizontally and vertically respectively:

  • padx – represents the horizontal padding that adds space to the left and right of the widget.
  • pady – represents the vertical padding that adds space above or below the widget.

The following example illustrates how to use the pady:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Pack',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack',bg='green', fg='white')
label3 = tk.Label(master=root, text='Pack',bg='blue', fg='white')
label4 = tk.Label(master=root, text='Pack',bg='purple', fg='white')

label1.pack(side=tk.TOP, fill=tk.X, pady=10)
label2.pack(side=tk.TOP, fill=tk.X, pady=20)
label3.pack(side=tk.TOP, fill=tk.X ,pady=40)
label4.pack(side=tk.TOP, fill=tk.X, pady=60)

root.mainloop()Code language: JavaScript (javascript)

Output:

The following program illustrates how to use the padx:

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')

label1 = tk.Label(master=root, text='Pack',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack',bg='green', fg='white')
label3 = tk.Label(master=root, text='Pack',bg='blue', fg='white')
label4 = tk.Label(master=root, text='Pack',bg='purple', fg='white')

label1.pack(side=tk.LEFT, fill=tk.X, padx=10)
label2.pack(side=tk.LEFT, fill=tk.X, padx=20)
label3.pack(side=tk.LEFT, fill=tk.X ,padx=40)
label4.pack(side=tk.LEFT, fill=tk.X, padx=60)

root.mainloop()Code language: JavaScript (javascript)

Output:

tkinter pack padx

Anchor

The anchor parameter allows you to anchor the widget to the edge of the allocated space. It accepts one of the following values:

StickyDescription
‘n’North or Top Center
‘s’South or Bottom Center
‘e’East or Right Center
‘w’West or Left Center
‘nw’North West or Top Left
‘ne’North East or Top Right
‘se’South East or Bottom Right
‘sw’South West or Bottom Left
‘center’Center

The following picture illustrates the anchor options:

tkinter pack anchor illustration

For example, the following program shows widgets that use E and W anchors:

import tkinter as tk

root = tk.Tk()
root.title('Pack Demo')
root.geometry("350x200")

# box 1
box1 = tk.Label(root, text="Box 1", bg="green", fg="white")
box1.pack(ipadx=20, ipady=20, anchor=tk.E,  expand=True)

# box 2
box2 = tk.Label(root, text="Box 2", bg="red", fg="white")
box2.pack(ipadx=20, ipady=20, anchor=tk.W, expand=True)


root.mainloop()Code language: PHP (php)

Output:

Using Tkinter pack to create a login form

The following example uses the pack() method to create a login form:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.title('Login')
root.geometry("350x220")


fields = {}

fields['username_label'] = ttk.Label(text='Username:')
fields['username'] = ttk.Entry()

fields['password_label'] = ttk.Label(text='Password:')
fields['password'] = ttk.Entry(show="*")


for field in fields.values():
    field.pack(anchor=tk.W, padx=10, pady=5, fill=tk.X)

ttk.Button(text='Login').pack(anchor=tk.W, padx=10, pady=5)

root.mainloop()
Code language: JavaScript (javascript)

Output:

How it works.

First, initialize a dictionary to store the widgets:

fields = {}

Second, create Label and Entry widgets:

fields['username_label'] = ttk.Label(text='Username:')
fields['username'] = ttk.Entry()

fields['password_label'] = ttk.Label(text='Password:')
fields['password'] = ttk.Entry(show="*")Code language: JavaScript (javascript)

Third, iterate through the widgets and pack them:

for field in fields.values():
    field.pack(anchor=tk.W, padx=10, pady=5, fill=tk.X)

Finally, add the login button:

ttk.Button(text='Login').pack(anchor=tk.W, padx=10, pady=5)Code language: JavaScript (javascript)

Summary

  • Use the Tkinter pack geometry manager to arrange widgets in a top-down or side-by-side layout.
  • Use the side, expand, and fill options of the pack geometry manager to control how widgets are arranged.
Did you find this tutorial helpful ?