Previous | Tutorial index | Next

Tutorial 3: Tkinter Basics – Creating Your First GUI Window

Learning Objectives

1. Introduction – Your First Step into GUI Programming

Writing your first GUI program is a milestone. Unlike a terminal program that simply prints text and exits, a GUI program creates a living window that stays on your screen, responds to your mouse, and updates itself dynamically.

In this tutorial, we will dissect the minimal Tkinter application line by line. By the end, you will understand not just how to create a window, but what each line does behind the scenes, and how to customise the window for your own applications.

2. Importing Tkinter – The Right Way

2.1 Standard Import

import tkinter as tk

2.2 What Is Actually Imported?

The tkinter module contains dozens of classes, constants, and utility functions. The most important ones we will use early on are:

3. The Tk Class – Your Application's Root

3.1 Creating the Root Window

root = tk.Tk()

3.2 The Root Window's Hidden Role

The root object is not just a window – it is also the application controller. It holds:

4. Configuring the Window – Title, Size, and More

4.1 Setting the Title

root.title("My First Application")

4.2 Setting the Geometry (Size and Position)

root.geometry("400x300") # width x height in pixels root.geometry("400x300+100+50") # width x height + x_offset + y_offset

4.3 Other Useful Window Methods

Method Description
root.resizable(width, height) True/False – allows or prevents the user from resizing the window.
root.minsize(width, height) Sets the minimum size the window can be shrunk to.
root.maxsize(width, height) Sets the maximum size the window can be expanded to.
root.iconbitmap("path.ico") Sets the window icon (on Windows; other platforms use iconphoto).
root.attributes("-alpha", 0.8) Sets transparency (0.0 fully transparent, 1.0 opaque). Windows only.
root.attributes("-fullscreen", True) Makes the window full‑screen.

4.4 Example: A Configured Window

import tkinter as tk root = tk.Tk() root.title("Advanced Config") root.geometry("500x300+200+100") root.resizable(False, False) # User cannot resize root.minsize(400, 250) # Minimum size (if resizable is True) root.maxsize(800, 600) root.mainloop()

5. Adding a Simple Widget – The Label

5.1 Creating the Label

label = tk.Label(root, text="Hello, World!")

5.2 The Important Distinction – Creation vs. Display

5.3 Packing the Label – The Simplest Layout

label.pack()

6. The Event Loop – mainloop()

6.1 What Does mainloop() Do?

root.mainloop()

6.2 What Happens If You Forget mainloop()?

6.3 Code After mainloop()

7. Other Essential Methods – destroy() and quit()

7.1 destroy()

root.destroy()

7.2 quit()

root.quit()

7.3 The protocol Handler – Intercepting the Close Button

When a user clicks the "X" (close) button on the window title bar, Tkinter's default behaviour is to destroy the window and exit mainloop(). You can override this to ask for confirmation before closing:

def on_closing(): if tk.messagebox.askokcancel("Quit", "Do you want to quit?"): root.destroy() root.protocol("WM_DELETE_WINDOW", on_closing)

This is an excellent way to prevent accidental data loss.

8. Complete Walkthrough – From Zero to Window

Let's annotate the complete minimal example with every concept we have covered:

import tkinter as tk # 1. Import root = tk.Tk() # 2. Create root window root.title("First Window") # 3. Set title root.geometry("300x200") # 4. Set size label = tk.Label(root, text="Hello, Tkinter!") # 5. Create label widget label.pack() # 6. Display the label (pack it) root.mainloop() # 7. Start the event loop

Execution flow:

9. Check Your Understanding (Quizzes)

Quiz 1: Multiple Choice

  1. What is the correct way to import Tkinter to avoid namespace pollution?
AnswerB – `import tkinter as tk` is the standard, clean approach.
  1. Which method is used to set the title of the main window?
AnswerB – `root.title("My App")` is correct.
  1. Which method starts the event loop and keeps the window open?
AnswerC – `mainloop()` starts the event loop.
  1. What does the geometry("400x300") method do?
AnswerB – It sets width and height in pixels.
  1. If you create a widget (e.g., tk.Label()) but do not call any geometry manager on it (like pack()), what happens?
AnswerB – The widget is not displayed because no geometry manager is called.

Quiz 2: True or False

  1. True / False: You can create multiple Tk() instances in a single program to create multiple independent windows.
AnswerFalse – You should not create multiple `Tk()` instances; use `Toplevel` for extra windows.
  1. True / False: The mainloop() function only runs for a fixed number of seconds and then stops automatically.
AnswerFalse – It runs indefinitely until the window is closed or `quit()` is called.
  1. True / False: The root.destroy() method closes the window but does not stop the event loop.
AnswerFalse – `destroy()` stops the event loop as well.
  1. True / False: On macOS, the title() method sets the window title correctly.
AnswerTrue – `title()` works on all platforms.
  1. True / False: If you resize the window using your mouse, the geometry() method automatically updates to reflect the new size.
AnswerFalse – `geometry()` sets an initial size; it does not update automatically when the user resizes.

Quiz 3: Fill in the Blanks

  1. The root = tk.Tk() line creates the ______________ window of the application.
Answerroot (or main)
  1. To prevent a window from being resized by the user, you can call root.resizable(_______, _______).
AnswerFalse, False
  1. The method that checks for system messages and dispatches events is called ______________.
Answermainloop()
  1. A widget must be placed inside a ______________ (usually the root or a frame) using a layout manager.
Answerparent container
  1. The string "300x200+50+50" passed to geometry() means width _____, height _____, and the window's top‑left corner is positioned 50 pixels from the ______________ and 50 pixels from the ______________.
Answerwidth = 300, height = 200, left, top

Quiz 4: Debugging

  1. The following code has two errors. Identify and fix them.
import tkinter as tk root = tk.Tk root.title("Hello) label = tk.Label(root, text="Hi") root.mainloop()
AnswerError 1: `tk.Tk` is missing parentheses – should be `tk.Tk()`. Error 2: The title string `"Hello)` is missing a closing quote – should be `"Hello"`. Corrected code: ```python import tkinter as tk root = tk.Tk() root.title("Hello") label = tk.Label(root, text="Hi") label.pack() # Also missing pack() in the original! root.mainloop() ```

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

Exercise 1: Window Configuration Playground

Task: Write a script that creates a window with the following properties:

Bonus: Make the label text colour blue.

Sample Solution ```python import tkinter as tk root = tk.Tk() root.title("My Playground") sw = root.winfo_screenwidth() sh = root.winfo_screenheight() x = (sw - 600) // 2 y = (sh - 400) // 2 root.geometry(f"600x400+{x}+{y}") root.resizable(False, False) root.minsize(400, 300) label = tk.Label(root, text="Welcome to the Playground", font=("Arial", 20), fg="blue") label.pack(expand=True) root.mainloop() ```

Exercise 2: Observe the Lifecycle

Task: Write a script that prints "Creating window..." before root = tk.Tk(), prints "Starting mainloop..." just before root.mainloop(), and prints "Window was closed." after root.mainloop(). Run the script and observe the order of print statements. Close the window to see the final print.

Sample output order "Creating window..." → "Starting mainloop..." (then window opens) → (user closes window) → "Window was closed."

Exercise 3: Pack Parameters Experiment

Task: Create a window with three labels: "Top", "Middle", "Bottom". Use pack() with different side values for each label (e.g., side=tk.TOP, side=tk.LEFT, side=tk.RIGHT). Also try adding padx=20 and pady=20 to see how spacing changes. Write down your observations about the layout.

Sample observations Using `side=tk.TOP` stacks them vertically; `side=tk.LEFT` places them side‑by‑side; `padx` and `pady` add spacing. The order of packing determines placement order.

Exercise 4: Custom Close Handler

Task: Modify the basic window so that when the user clicks the "X" button, a pop‑up message (use tk.messagebox.askyesno) asks "Are you sure you want to exit?" If the user answers "Yes", close the window; if "No", keep the window open. (Note: you will need to import tk.messagebox or from tkinter import messagebox.)

Sample Solution ```python import tkinter as tk from tkinter import messagebox root = tk.Tk() def on_closing(): if messagebox.askyesno("Quit", "Are you sure you want to exit?"): root.destroy() root.protocol("WM_DELETE_WINDOW", on_closing) root.mainloop() ```

11. Homework Assignment

Objective

Demonstrate your deep understanding of the Tkinter root window lifecycle, widget creation, and geometry management. You will also practice reading documentation to discover new methods.

Part A: Window Customisation (10 points)

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

Submit the full code, clearly commented.

Sample Solution ```python import tkinter as tk

root = tk.Tk() root.title("My Custom Window") sw = root.winfo_screenwidth() sh = root.winfo_screenheight()

bottom‑right corner: window top‑left at (sw - 800, sh - 500)

root.geometry(f"800x500+{sw-800}+{sh-500}") root.resizable(True, True) root.minsize(500, 400) root.maxsize(1200, 900)

To set icon, uncomment: root.iconbitmap("myicon.ico") # on Windows

label = tk.Label(root, text="Your Name - Student ID", font=("Arial", 18), bg="lightyellow") label.pack(expand=True) # centering root.mainloop()

</details> ### Part B: Code Interpretation and Explanation (10 points) Given the following code, answer the questions below: ```python import tkinter as tk root = tk.Tk() root.title("Test") root.geometry("300x300") lbl1 = tk.Label(root, text="Label 1") lbl2 = tk.Label(root, text="Label 2") lbl3 = tk.Label(root, text="Label 3") lbl1.pack(side=tk.LEFT, padx=10) lbl2.pack(side=tk.LEFT, padx=10) lbl3.pack(side=tk.LEFT, padx=10) print("All labels packed.") root.mainloop() print("Mainloop ended.")

Questions:

  1. In what order will the three labels appear (left to right)? Justify your answer.
  2. What happens to the window size if you add a fourth label lbl4 with pack(side=tk.LEFT)? Does the window resize automatically?
  3. If you change side=tk.LEFT to side=tk.TOP for all labels, how does the layout change?
  4. Why does the print("All labels packed.") appear immediately when you run the script, but print("Mainloop ended.") only appears after closing the window?
Answers 1. They appear in the order they are packed: Label 1, then Label 2, then Label 3, from left to right because `side=LEFT` places them consecutively. 2. The window does not resize automatically; the labels will extend beyond the window if there isn't enough space. You would need to set `fill` or adjust geometry. 3. With `side=tk.TOP`, they are stacked vertically from top to bottom. 4. `"All labels packed."` is executed immediately because it is outside the event loop. `"Mainloop ended."` is only printed after `root.mainloop()` finishes (when the window is closed).

Part C: Research – The winfo Methods (5 points)

Tkinter provides a family of methods prefixed with winfo_ that retrieve information about the window. Research the following methods (using Python's help() or online documentation) and explain what each does:

Then, write a small script that, after the window is created but before mainloop() is called, prints the width and height. Why do they print 1 (or another small value) instead of the actual geometry size you set? (Hint: think about when the window is actually drawn.)

Answers - `winfo_width()` – returns the current width of the window in pixels. - `winfo_height()` – returns the current height in pixels. - `winfo_pointerx()` – returns the x‑coordinate of the mouse pointer relative to the screen. - `winfo_children()` – returns a list of child widgets.

The width/height print 1 because the window has not yet been mapped (drawn) on the screen before mainloop() runs; the geometry is not finalised until the event loop starts. You can use root.update() before querying to force a draw, or check after mainloop() starts (but that would require an after callback).

Part D: Error Analysis and Correction (5 points)

A student submitted the following code, but it does not display the label. Explain why, and provide the corrected code.

import tkinter as tk root = tk.Tk() root.title("Error") label = tk.Label(text="I am invisible") root.mainloop()
Answer The label does not have a parent container specified, so it doesn't belong to any window. Also, it is not packed/gridded/placed. Corrected code: ```python import tkinter as tk root = tk.Tk() root.title("Error") label = tk.Label(root, text="I am visible") label.pack() root.mainloop() ```

Part E: Creative Extension (5 points)

Add a feature to your window from Part A: When the user clicks the "X" button, instead of closing immediately, the window should display a new message box that says "Thank you for using my app!" and then closes after the user clicks "OK". Write the necessary function and the protocol binding to achieve this.

Sample Solution ```python from tkinter import messagebox def on_closing(): messagebox.showinfo("Goodbye", "Thank you for using my app!") root.destroy() root.protocol("WM_DELETE_WINDOW", on_closing) ```
### Submission Guidelines for Homework - Submit a single `.py` file containing all your code for Parts A, C (the script), D (the correction), and E (the extension). Clearly comment each part with `# Part A`, `# Part C`, etc. - For Part B, submit a separate text/PDF document with your written answers. - For Part C, include your research answers in the same document. - Ensure all code runs without syntax errors.

12. Summary of Key Terms (Glossary)

Term Definition
Root Window The main window of a Tkinter application, created by tk.Tk(). It holds the event loop and all widgets.
Widget A GUI element like a label, button, or entry field.
Parent Container The widget (or window) that contains another widget. The parent is passed as the first argument when creating a child widget.
Geometry Manager A method (pack, grid, or place) that determines the size and position of widgets within their parent.
Event Loop The infinite loop (mainloop()) that waits for user interactions and updates the display.
destroy() A method that deletes a window and all its children, freeing memory.
protocol() A method that intercepts window manager events (e.g., the close button).

13. Further Resources for Self‑Study

This tutorial is designed to take approximately 2–3 hours of study time, including the lab exercises and homework. Mastery of this foundational material is critical for all later Tkinter topics.

Previous | Tutorial index | Next