Tkinter is Python's standard library for creating graphical user interfaces (GUIs). Present since the earliest versions of the language, Tkinter transforms console scripts into full visual applications with windows, buttons, text fields, menus and much more. If you want to build programs that real people can use without opening a terminal, Tkinter is the most direct and accessible path.
In this complete guide, you will learn everything from creating your first window to advanced layout techniques, event handling and full desktop application development. If you are still learning the fundamentals of the language, check out our complete guide for Python beginners before proceeding.
What is Tkinter?
Tkinter is a Python binding for the Tcl/Tk graphical toolkit, originally developed by John Ousterhout in the late 1980s. The name "Tkinter" comes from "Tk interface". As part of Python's standard library, Tkinter is available in any official Python installation without needing to install additional packages — making it the most practical choice for getting started with GUI development.
Tkinter offers a wide variety of widgets (visual components) such as buttons, labels, text boxes, lists, progress bars, canvas for custom drawing and much more. The library also includes support for native dialogs (file open, color chooser, messages), menus, keyboard shortcuts and mouse events.
According to the official Python documentation, Tkinter is the simplest and fastest way to create GUI applications in the language, being widely used in internal tools, prototypes and even small to medium-sized production applications.
Installation and Setup
The best news about Tkinter is that it already comes bundled with Python. To check if Tkinter is available in your environment, run the following command in your terminal:
python -m tkinter
If everything is correct, a small window with Tkinter information will appear. If you get an error saying the module was not found, you may need to install it separately. On Ubuntu and Debian, for example, use:
sudo apt-get install python3-tk
On Windows and macOS, Tkinter is already included in the official Python installer available at python.org. Once you confirm the module is working, you are ready to create your first graphical interface.
Your First Tkinter Window
Let's create the classic "Hello, World!" in graphical form. The code below creates a window with a title and a centered label:
import tkinter as tk
window = tk.Tk()
window.title("My First Window")
window.geometry("400x300")
label = tk.Label(window, text="Hello, World!")
label.pack()
window.mainloop()
Let's break down each part of the code:
- import tkinter as tk: Imports the module with the
tkalias, a recommended practice to avoid name conflicts. - tk.Tk(): Creates the main application window. Every Tkinter application needs a
Tkinstance. - window.title(): Sets the title displayed in the window's title bar.
- window.geometry(): Sets the initial window size in "width x height" format.
- tk.Label(): Creates a label widget (static text). The first argument is the parent (the window that will contain the widget).
- .pack(): Manages widget positioning using the
packlayout manager. - window.mainloop(): Starts the application's main event loop. Without this line, the window would appear and close instantly.
When you run the code, you will see a 400x300 pixel window with the text "Hello, World!" centered. Congratulations — you have just created your first Python GUI!
Essential Tkinter Widgets
Tkinter offers dozens of ready-to-use widgets. Knowing the main ones is essential for building any graphical application. Below are the most commonly used widgets:
Label
The Label widget displays static text or images. It is one of the simplest and most versatile widgets:
label = tk.Label(window, text="Some text", font=("Arial", 14))
label.pack()
The font parameter accepts a tuple with the font name and size. You can also use fg (foreground) for text color and bg (background) for background color.
Button
The Button widget executes a function when clicked. The command parameter receives a callback function:
def on_click():
print("Button clicked!")
button = tk.Button(window, text="Click Here", command=on_click)
button.pack()
Tkinter also allows configuring the button's appearance with width, height, bg, fg and relief (border style).
Entry
The Entry widget allows users to input a single line of text. To retrieve the entered value, use the .get() method:
entry = tk.Entry(window, width=40)
entry.pack()
def show_text():
print(entry.get())
tk.Button(window, text="Show", command=show_text).pack()
The Entry widget accepts parameters like show="*" for password fields and state="disabled" to disable editing.
Text
Unlike Entry, the Text widget supports multiple lines and rich formatting:
text = tk.Text(window, height=10, width=50)
text.pack()
text.insert("1.0", "Type your text here...")
The .insert() method takes an index in "line.column" format. "1.0" means line 1, column 0 (the beginning). To retrieve all content, use text.get("1.0", tk.END).
Frame
The Frame widget is an invisible container used to group other widgets. It is essential for organizing complex layouts:
frame = tk.Frame(window, relief="solid", borderwidth=2)
frame.pack(padx=10, pady=10)
button1 = tk.Button(frame, text="Button 1")
button1.pack(side="left")
button2 = tk.Button(frame, text="Button 2")
button2.pack(side="left")
The side parameter in pack() sets the stacking direction: "left", "right", "top" (default) or "bottom".
Layout Managers
Widget positioning is controlled by geometry managers. Tkinter offers three main managers:
pack
The pack manager organizes widgets in blocks, stacking them sequentially. It is the simplest and recommended for linear layouts:
tk.Label(window, text="Top").pack(side="top", fill="x")
tk.Label(window, text="Left").pack(side="left")
tk.Label(window, text="Right").pack(side="right")
tk.Label(window, text="Bottom").pack(side="bottom", fill="x")
Useful pack parameters: fill (expand in x/y axis), expand (occupy extra space), padx/pady (external padding), ipadx/ipady (internal padding).
grid
The grid manager organizes widgets in rows and columns, similar to a spreadsheet. It is ideal for forms and grid-organized panels:
tk.Label(window, text="Name:").grid(row=0, column=0, sticky="e")
tk.Entry(window).grid(row=0, column=1, padx=5, pady=5)
tk.Label(window, text="Email:").grid(row=1, column=0, sticky="e")
tk.Entry(window).grid(row=1, column=1, padx=5, pady=5)
tk.Button(window, text="Submit").grid(row=2, column=0, columnspan=2)
The sticky parameter aligns the widget inside the cell using cardinal directions (n, s, e, w). columnspan and rowspan allow a widget to span multiple cells.
place
The place manager positions widgets at absolute or relative coordinates. Use sparingly, as it does not adapt well to resizing:
tk.Label(window, text="Absolute").place(x=50, y=100)
tk.Label(window, text="Relative").place(relx=0.5, rely=0.5, anchor="center")
According to the official TkDocs tutorial, grid is the most versatile manager for most applications, while pack excels at simple, sequential layouts.
Events and Callbacks
Tkinter is event-driven. Every user interaction — clicks, key presses, mouse movements — generates an event that can be handled by a callback function.
Mouse Events
def click(event):
print(f"Clicked at ({event.x}, {event.y})")
window.bind("", click) # Left button
window.bind("", click) # Right button
window.bind("", click) # Double click
window.bind("", click) # Mouse movement
Keyboard Events
def key_pressed(event):
print(f"Key: {event.keysym} (code: {event.keycode})")
window.bind("", key_pressed)
window.bind("", lambda e: print("Enter pressed"))
window.bind("", lambda e: window.destroy())
The event parameter is an object containing information about the event: mouse position (x, y), pressed key (keysym, keycode), source widget (widget), among others.
To associate events with specific widgets, use the .bind() method directly on the widget. For global events, use bind_all() or bind_class(). The official Tkinter events documentation lists all available event sequences.
Windows and Dialogs
Real applications often need multiple windows and native dialogs. Tkinter provides full support for these features.
Creating New Windows (Toplevel)
def open_window():
new = tk.Toplevel(window)
new.title("Secondary Window")
new.geometry("300x200")
tk.Label(new, text="This is a new window").pack()
tk.Button(window, text="Open Window", command=open_window).pack()
The Toplevel widget creates a new independent window. Unlike the main Tk window, you can create as many Toplevel instances as you need.
Native Dialogs
The tkinter.messagebox module provides ready-made dialogs for messages, alerts and confirmations:
from tkinter import messagebox
def confirm_exit():
if messagebox.askyesno("Confirmation", "Do you really want to exit?"):
window.destroy()
messagebox.showinfo("Info", "Operation completed!")
messagebox.showwarning("Warning", "File not found.")
messagebox.showerror("Error", "Connection failed.")
The tkinter.filedialog module offers dialogs for file and directory selection:
from tkinter import filedialog
file = filedialog.askopenfilename(title="Select a file")
folder = filedialog.askdirectory(title="Select a folder")
path = filedialog.asksaveasfilename(title="Save as")
These dialogs are native to the operating system, ensuring visual integration with the user's environment. Check the messagebox documentation and the filedialog documentation for more options.
Complete Application: Task Manager
Let's consolidate our knowledge by building a functional application: a graphical to-do list manager.
import tkinter as tk
from tkinter import messagebox
def add_task():
task = entry.get().strip()
if task:
listbox.insert(tk.END, task)
entry.delete(0, tk.END)
else:
messagebox.showwarning("Warning", "Enter a task!")
def remove_task():
try:
index = listbox.curselection()[0]
listbox.delete(index)
except IndexError:
messagebox.showwarning("Warning", "Select a task!")
def clear_all():
if messagebox.askyesno("Confirm", "Clear all tasks?"):
listbox.delete(0, tk.END)
window = tk.Tk()
window.title("Task Manager")
window.geometry("400x450")
frame_input = tk.Frame(window)
frame_input.pack(pady=10)
entry = tk.Entry(frame_input, width=35)
entry.pack(side="left", padx=5)
entry.bind("", lambda e: add_task())
btn_add = tk.Button(frame_input, text="Add", command=add_task)
btn_add.pack(side="left")
listbox = tk.Listbox(window, height=15, width=50)
listbox.pack(pady=10)
frame_buttons = tk.Frame(window)
frame_buttons.pack(pady=5)
tk.Button(frame_buttons, text="Remove", command=remove_task).pack(side="left", padx=5)
tk.Button(frame_buttons, text="Clear All", command=clear_all).pack(side="left", padx=5)
tk.Button(frame_buttons, text="Exit", command=window.destroy).pack(side="left", padx=5)
window.mainloop()
This application demonstrates the practical use of Entry, Listbox, Frame, Button, messagebox, layout management with pack, keyboard event binding and modular code organization. You can expand it by adding file persistence, categories or due dates.
The Canvas Widget
The Canvas widget is a powerful tool for vector drawing, custom graphics and animations. With it, you can draw lines, rectangles, circles, polygons and even display images:
canvas = tk.Canvas(window, width=300, height=300, bg="white")
canvas.pack()
canvas.create_line(50, 50, 250, 250, fill="blue", width=3)
canvas.create_rectangle(80, 80, 180, 180, outline="red", width=2, fill="yellow")
canvas.create_oval(200, 50, 280, 130, fill="green")
canvas.create_text(150, 270, text="Tkinter Canvas", font=("Arial", 12))
Each element drawn on the Canvas returns an ID that can later be used to modify or remove it using methods like itemconfig(), move() and delete(). This makes the Canvas ideal for creating simple games, custom data visualizations and drawing tools.
The Real Python Tkinter tutorial explores the Canvas capabilities and how to combine it with other widgets for interactive applications.
Styling Your Interface with ttk
The tkinter.ttk (Themed Tkinter) module offers widgets with a modern, native look and feel. While classic Tkinter widgets have a 1990s appearance, ttk widgets integrate visually with the user's operating system:
from tkinter import ttk
button_ttk = ttk.Button(window, text="Modern Button")
button_ttk.pack()
progress = ttk.Progressbar(window, length=200, mode="determinate")
progress.pack()
slider = ttk.Scale(window, from_=0, to=100, orient="horizontal")
slider.pack()
tree = ttk.Treeview(window, columns=("name", "age"), show="headings")
tree.heading("name", text="Name")
tree.heading("age", text="Age")
tree.pack()
The ttk widgets support themes that can be changed globally. You can list available themes with ttk.Style().theme_names() and switch between them with ttk.Style().theme_use("theme_name"). Common themes include "clam", "alt", "default" and "vista" (Windows).
The official ttk documentation details all available themed widgets and their configuration options.
Best Practices with Tkinter
To build professional, maintainable Tkinter applications, follow these recommendations:
- Organize with classes: Structure your application using classes, typically inheriting from
tk.Tkortk.Frame. This makes code organization and state management much easier. Learn more about this pattern in our Object-Oriented Programming in Python guide. - Use
gridfor forms: Thegridmanager is far more suitable thanpackfor organizing labels and input fields side by side. - Prefer
ttkover classic widgets: Themed widgets offer a more professional appearance and cross-platform consistency. - Avoid
placefor responsive layouts: Absolute positioning does not adapt to window resizing. - Never use
time.sleep(): Thesleepfunction freezes the interface. Usewindow.after()to schedule future executions without blocking the GUI. - Validate user input: Always verify data entered in
EntryandTextfields before processing it. - Document callbacks: Functions associated with events should have descriptive names and ideally docstrings explaining their purpose.
Regarding interface blocking, the after() method is a fundamental alternative to sleep. Here is a non-blocking clock example:
def update_clock():
from datetime import datetime
clock_label.config(text=datetime.now().strftime("%H:%M:%S"))
window.after(1000, update_clock)
clock_label = tk.Label(window, font=("Arial", 24))
clock_label.pack()
update_clock()
Conclusion
Tkinter is a powerful and accessible tool for creating graphical interfaces in Python. In this guide, you learned everything from creating your first window to advanced techniques like layout managers, events, native dialogs, ttk styling and development best practices.
Tkinter especially shines in scenarios such as internal company tools, rapid prototypes, simple editors, data entry systems, lightweight dashboards and educational applications. For projects requiring web interfaces, we recommend exploring Flask or FastAPI. And if you need mobile interfaces, frameworks like Kivy are more suitable.
The best way to master Tkinter is to practice. Start by creating small projects: a temperature converter, a simple notepad, a stopwatch or an image viewer. Each project will consolidate your learning and prepare you for more complex applications. The Python Wiki on Tkinter and the TkDocs website are excellent resources to continue your studies.