Previous | Tutorial index | Next

Tutorial 4: Tkinter Widgets – A Comprehensive Overview

Learning Objectives

1. Introduction – What Are Tkinter Widgets?

In Tkinter, everything is a widget. A widget is a graphical element on the screen—a button, a label, a text box, a frame, or even a menu. Think of widgets as the building blocks of your GUI, just as Lego bricks are the building blocks of a model.

Every widget in Tkinter follows a strict parent–child hierarchy:

Tkinter provides over 20 different widget classes. In this tutorial, we will explore the most essential ones in depth, understand their unique methods and options, and learn how to combine them to build functional interfaces.

2. Widget Categories – Grouping by Purpose

To make it easier to remember, we can group widgets into four broad categories:

Category Purpose Widgets
Display & Simple Input Show static content or get basic text input. Label, Button, Entry, Text
Selection Let the user choose from predefined options. Checkbutton, Radiobutton, Listbox, Scale
Containers & Structure Organise and group other widgets. Frame, LabelFrame, PanedWindow
Advanced & Specialised Provide drawing, menus, and scrolling. Canvas, Menu, Scrollbar, Toplevel

We will now examine each widget from the original table, plus a few extra useful ones.

3. Display & Simple Input Widgets – Deep Dive

3.1 Label – Displaying Text or Images

photo = tk.PhotoImage(file="icon.png") label = tk.Label(root, text="Welcome!", image=photo, compound=tk.TOP) label.pack()

3.2 Button – Clickable Action Trigger

def greet(): print("Hello!") btn = tk.Button(root, text="Greet", command=greet, bg="lightblue") btn.pack()

3.3 Entry – Single‑Line Text Input

entry = tk.Entry(root, width=20, bg="white", fg="black") entry.insert(0, "Enter your name") entry.pack() name = entry.get() # Retrieve later

3.4 Text – Multi‑Line Rich Text Area

text_area = tk.Text(root, height=10, width=40, wrap=tk.WORD) text_area.insert(tk.END, "This is a multi-line text widget.\nYou can type here.") text_area.pack() content = text_area.get(1.0, tk.END)

4. Selection Widgets – Deep Dive

4.1 Checkbutton – On/Off Toggles

agree_var = tk.IntVar() chk = tk.Checkbutton(root, text="I agree to terms", variable=agree_var) chk.pack() if agree_var.get() == 1: print("User agreed")

4.2 Radiobutton – Mutually Exclusive Selection

choice = tk.IntVar() rb1 = tk.Radiobutton(root, text="Small", variable=choice, value=1) rb2 = tk.Radiobutton(root, text="Medium", variable=choice, value=2) rb3 = tk.Radiobutton(root, text="Large", variable=choice, value=3) rb1.pack(); rb2.pack(); rb3.pack() # choice.get() returns 1, 2, or 3.

4.3 Listbox – Scrollable List of Items

listbox = tk.Listbox(root, height=4) for fruit in ["Apple", "Banana", "Cherry", "Date"]: listbox.insert(tk.END, fruit) listbox.pack() selected = listbox.curselection() # e.g., (2,)

4.4 Scale – Slider for Numeric Input

def show_volume(val): print(f"Volume: {val}") scale = tk.Scale(root, from_=0, to=100, orient=tk.HORIZONTAL, command=show_volume, length=200) scale.pack()

5. Container & Structure Widgets – Deep Dive

5.1 Frame – The Ultimate Organiser

main_frame = tk.Frame(root, bg="white", relief=tk.GROOVE, bd=2) main_frame.pack(padx=10, pady=10) label = tk.Label(main_frame, text="I am inside a frame") label.pack()

5.2 LabelFrame – A Framed Group with a Title

group = tk.LabelFrame(root, text="Contact Info", padx=10, pady=10) group.pack(padx=10, pady=10) tk.Entry(group).pack() # entry inside this group

6. Advanced & Specialised Widgets – Deep Dive

6.1 Canvas – The Drawing Board

c = tk.Canvas(root, width=200, height=100, bg="lightyellow") rect = c.create_rectangle(50, 25, 150, 75, fill="red") c.pack()

6.2 Menu – The Top‑Level Menu Bar

menubar = tk.Menu(root) root.config(menu=menubar) file_menu = tk.Menu(menubar, tearoff=0) menubar.add_cascade(label="File", menu=file_menu) file_menu.add_command(label="Exit", command=root.destroy)

6.3 Scrollbar – The Navigation Helper

listbox = tk.Listbox(root, height=4) scroll = tk.Scrollbar(root, orient=tk.VERTICAL, command=listbox.yview) listbox.config(yscrollcommand=scroll.set) listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scroll.pack(side=tk.RIGHT, fill=tk.Y)

7. Configuration – Setting and Changing Widget Options

7.1 Setting Options at Creation

You pass options as keyword arguments:

btn = tk.Button(root, text="Click", font=("Arial", 10), bg="yellow")

7.2 Changing Options After Creation – .config() (or .configure())

btn.config(text="New Label", bg="blue")

You can change almost any option at any time.

7.3 Retrieving Options – .cget()

current_text = btn.cget("text") print(current_text) # Prints "New Label"

7.4 Getting All Options – .keys()

print(btn.keys()) # Lists all configurable option names

7.5 The Importance of textvariable vs. text

var = tk.StringVar() label = tk.Label(root, textvariable=var) var.set("Initial") # Label updates instantly!

8. Common Methods Shared by All Widgets

Every widget inherits from the BaseWidget class and shares these methods:

9. Check Your Understanding (Quizzes)

Quiz 1: Multiple Choice

  1. Which widget would you use to let the user select exactly one option from a group of five?
AnswerB – `Radiobutton` enforces mutual exclusivity.
  1. Which method retrieves the current text from an Entry widget?
AnswerA – `.get()` retrieves the entry's content.
  1. You want to create a password input field. Which option should you set?
AnswerB – `show="*"` masks the typed characters.
  1. Which widget is best suited to display a multi‑line text area that the user can edit?
AnswerC – `Text` is the multi‑line editor.
  1. What is the first argument you pass when creating any widget?
AnswerB – The parent container is always the first argument.

Quiz 2: True or False

  1. True / False: A Frame widget must always have a background colour set, otherwise it is invisible.
AnswerFalse – A frame is visible as an empty rectangle (though it may be hard to see without a border or colour).
  1. True / False: Radiobutton widgets that share the same variable automatically belong to the same group.
AnswerTrue – That is how grouping works.
  1. True / False: The Listbox widget allows the user to type directly into the list.
AnswerFalse – It is a selection list, not an input field.
  1. True / False: You can draw shapes (like circles and rectangles) on a Canvas widget.
AnswerTrue – `Canvas` supports numerous drawing primitives.
  1. True / False: Calling .config() on a widget can only be done once—after creation, the options are locked.
AnswerFalse – `.config()` can be called any number of times.

Quiz 3: Fill in the Blanks

  1. To append an item to the end of a Listbox, you use listbox.insert(tk.____, "New Item").
AnswerEND
  1. A Scale widget uses the parameter from_ because ____ is a reserved Python keyword.
Answerfrom
  1. The method used to delete all text from an Entry widget is entry.delete(0, tk.____).
AnswerEND
  1. To link a vertical Scrollbar to a Text widget, you set the yscrollcommand option of the Text widget to scrollbar.____.
Answer.set
  1. The Canvas method to draw a rectangle is .create_____(x1, y1, x2, y2, ...).
Answerrectangle

Quiz 4: Matching

Match the widget to its primary method:

Widget Method
A. Entry .curselection()
B. Text .add_cascade()
C. Listbox .create_line()
D. Canvas .get(1.0, tk.END)
E. Menu .insert(0, "text")
AnswerA‑5, B‑4, C‑1, D‑3, E‑2.

10. Hands‑On Lab (In‑Class Exercises)

Exercise 1: Widget Identification

Write a Tkinter application that contains the following widgets:

Sample solution outline Create root, define frames, pack them. Use `grid` inside frames for labels/entries. Use `StringVar` for username, `IntVar` for checkbox, `IntVar` for radiobuttons. Define a `on_register` function that prints all values.

Exercise 2: Scrollable Text Editor

Create a window with a large Text widget and a vertical Scrollbar that is properly linked. Also add a Button at the bottom that, when clicked, prints all the text in the console.

Sample solution ```python import tkinter as tk root = tk.Tk() text = tk.Text(root, height=10, width=40) scroll = tk.Scrollbar(root, orient=tk.VERTICAL, command=text.yview) text.config(yscrollcommand=scroll.set) text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scroll.pack(side=tk.RIGHT, fill=tk.Y) def print_text(): print(text.get(1.0, tk.END)) btn = tk.Button(root, text="Print", command=print_text) btn.pack() root.mainloop() ```

Exercise 3: Canvas Shapes

Write a script that draws a yellow sun (a circle) in the top‑left corner and a green rectangle (representing grass) at the bottom of a Canvas that is 400x300 pixels. Add a Button that, when clicked, moves the sun 10 pixels to the right (use .move()).

Sample solution ```python canvas = tk.Canvas(root, width=400, height=300, bg="skyblue") canvas.pack() sun = canvas.create_oval(20, 20, 70, 70, fill="yellow") grass = canvas.create_rectangle(0, 250, 400, 300, fill="green") def move_sun(): canvas.move(sun, 10, 0) btn = tk.Button(root, text="Move Sun", command=move_sun) btn.pack() ```

Exercise 4: Dynamic Configuration

Create a window with a Label that says "Click to change". Add a Button below it. Every time the button is clicked, change the Label's text to the current time (strftime) and change its background colour to a random colour (use random.choice from a list). Use .config() to achieve this.

Sample solution ```python import tkinter as tk import random, time root = tk.Tk() label = tk.Label(root, text="Click to change", font=("Arial", 16)) label.pack() colors = ["red", "green", "blue", "yellow", "purple", "orange"] def change(): label.config(text=time.strftime("%H:%M:%S"), bg=random.choice(colors)) btn = tk.Button(root, text="Change", command=change) btn.pack() root.mainloop() ```

11. Homework Assignment

Objective

Demonstrate your mastery of Tkinter widgets by building a functional registration form, analysing code, and researching deeper capabilities.

Part A: Build a Complete Registration Form (20 points)

Write a Python script that creates a window with the following specifications:

Sample solution outline - Root window with title, geometry, resizable(False). - Outer frame packed. - Top label packed. - Personal details frame with grid: labels in col0, entries col1. - Gender frame with Radiobuttons sharing a StringVar. - Interests frame with Checkbuttons each with IntVar. - Age frame with Scale from 18 to 100, tickinterval=10. - Buttons frame with Submit and Clear. - Submit function: collect data and print. - Clear function: delete entries, set gender var to "", set check vars to 0, scale.set(18).

Part B: Code Analysis and Correction (10 points)

Examine the following code snippet. It is supposed to create a simple ordering system with a listbox, but it contains four logical or syntactical errors. Identify each error, explain why it is a problem, and provide the corrected code.

import tkinter as tk root = tk.Tk() root.title("Order") items = ["Pizza", "Burger", "Pasta", "Salad"] listbox = tk.Listbox(root, height=4, selectmode=tk.MULTIPLE) for item in items: listbox.insert(0, item) # Error 1 listbox.pack() def show_order(): selected = listbox.get(tk.ACTIVE) # Error 2 print("You selected:", selected) btn = tk.Button(root, text="Show Order", command=show_order) btn.pack() # Error 3: Scrollbar is created but never linked or packed properly scroll = tk.Scrollbar(root, orient=tk.HORIZONTAL) scroll.pack(side=tk.RIGHT, fill=tk.Y) # Error 4: Missing the mainloop call
Answers 1. `listbox.insert(0, item)` inserts each item at index 0, causing reverse order. Should be `listbox.insert(tk.END, item)`. 2. `listbox.get(tk.ACTIVE)` returns the text of the active item, not the selection. For multiple selection, use `listbox.curselection()` and then `listbox.get(index)`. 3. The scrollbar is horizontal (`orient=tk.HORIZONTAL`) but packed on the right with `fill=tk.Y` – it should be vertical and linked to the listbox via `yscrollcommand` and `command`. 4. Missing `root.mainloop()`.

Corrected code:

import tkinter as tk root = tk.Tk() root.title("Order") items = ["Pizza", "Burger", "Pasta", "Salad"] listbox = tk.Listbox(root, height=4, selectmode=tk.MULTIPLE) for item in items: listbox.insert(tk.END, item) listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scroll = tk.Scrollbar(root, orient=tk.VERTICAL, command=listbox.yview) listbox.config(yscrollcommand=scroll.set) scroll.pack(side=tk.RIGHT, fill=tk.Y) def show_order(): selected_indices = listbox.curselection() selected_items = [listbox.get(i) for i in selected_indices] print("You selected:", selected_items) btn = tk.Button(root, text="Show Order", command=show_order) btn.pack() root.mainloop()

Part C: Widget Research – The PanedWindow (5 points)

Research the PanedWindow widget (not covered in detail above). Write a short paragraph (4‑6 sentences) explaining:

Sample Answer A `PanedWindow` is a container that holds multiple panes separated by a draggable sash, allowing the user to resize the panes. Unlike a normal `Frame`, which has a fixed size unless configured with weights, a `PanedWindow` provides interactive resizing via the sash. It is ideal for applications like file explorers or IDEs where the user needs to adjust the relative sizes of side panels and main content. Example: ```python p = tk.PanedWindow(root, orient=tk.HORIZONTAL) p.add(tk.Label(p, text="Left")) p.add(tk.Label(p, text="Right")) p.pack(fill=tk.BOTH, expand=True) ```

Part D: Event Binding with Widgets (5 points)

Write a small script that creates an Entry widget and a Label. Bind the <KeyRelease> event to the Entry so that every time the user types a character, the label automatically updates to show the current text of the entry (character count or the text itself). Hint: Use .get() on the entry inside the callback.

Sample solution ```python import tkinter as tk root = tk.Tk() entry = tk.Entry(root) entry.pack() label = tk.Label(root, text="Text length: 0") label.pack() def update(event): label.config(text=f"Text length: {len(entry.get())}") entry.bind("", update) root.mainloop() ```

Part E: Reflection (5 points)

Write a short paragraph (5‑7 sentences) answering: "Why is the Frame widget considered one of the most important widgets in Tkinter, even though it does not directly display any useful information to the user?" Use examples from this tutorial and your own reasoning.

Sample Answer The `Frame` widget is essential because it provides structure and organisation to complex GUIs. Without frames, you would have to place all widgets directly in the root window, which quickly becomes chaotic and unmanageable. Frames act as containers that allow you to group related widgets, apply different geometry managers to different sections, and control the layout hierarchically. For instance, in a registration form, you can have a frame for personal details, another for gender selection, and a third for interests – each using `grid` internally while the outer frames are packed. This nesting makes the code cleaner, more modular, and easier to maintain. Frames also help with responsive design, as you can expand them and let their children fill them. In short, frames are the skeleton upon which every well‑designed Tkinter application is built.

12. Summary of Key Terms (Glossary)

Term Definition
Widget A graphical UI element such as a button, label, or text field.
Parent Container The widget that "owns" another widget. Destroying the parent destroys all children.
Geometry Manager pack, grid, or place – decides the size and position of widgets.
Callback A function passed to the command option that runs when a widget is activated.
Variable Class StringVar, IntVar, DoubleVar, BooleanVar – special Tkinter variables that synchronise with widgets automatically.
Index A way to refer to a position in a Text or Listbox (e.g., 1.0 for line 1, column 0).
Binding Connecting an event (e.g., key press) to a function using .bind().

13. Further Resources for Self‑Study

This tutorial is designed to take approximately 3 hours of study, lab work, and homework. By the end, you should be comfortable creating any basic GUI using the most common Tkinter widgets and understand how to configure and manipulate them dynamically.

Previous | Tutorial index | Next