Learn How to Build a Desktop Program in Python: Absolute Beginners Tutorial

Python is not only a scripting language — it can produce real desktop programs with windows, buttons, and input fields that run on any platform. The standard library includes tkinter, a toolkit that gives you everything needed to build a functioning GUI application without installing anything extra.

This tutorial walks through building a working desktop application from scratch. By the end you will have a functional tip calculator — a small but complete program with a window, labeled inputs, a button, and a live result display. Every concept introduced here is transferable to any tkinter project you build after this one.

What is tkinter and Why Use It

tkinter is Python's standard GUI library. It wraps a toolkit called Tk, which has been maintained since the late 1980s and runs on Windows, macOS, and Linux without modification. Because tkinter ships with CPython, you do not need to run pip install for anything in this tutorial. On most Linux distributions you may need to install the separate package — on Debian and Ubuntu that command is sudo apt install python3-tk.

The Python documentation describes tkinter as providing "a thin object-oriented layer on top of Tcl/Tk." In practice that means every visual element — a button, a label, a text field — is a Python object with methods and attributes. You configure them in Python, and tkinter handles the platform-level drawing.

Note

IDLE — the code editor bundled with Python — is itself written in tkinter. That means every Python installation that includes IDLE already has a complete tkinter example running on it.

For absolute beginners, tkinter is a practical starting point because it introduces GUI concepts (windows, events, widgets) without requiring you to learn a framework with its own file structure, build pipeline, or package manager. The tradeoff is that the default widget appearance is plain. Libraries such as CustomTkinter and ttkthemes extend tkinter with styled widgets while keeping the same programming model covered here.

Comes with Python
Yes — no pip install required
Best for
Learning GUI concepts, small utilities, tools you want to run anywhere Python runs
Comes with Python
No — install via pip
Best for
Large, professional desktop applications; richer widget set and designer tools
Comes with Python
No — install via pip
Best for
Cross-platform apps that need native OS look and feel on each platform

Your First Window in Five Lines

The minimal tkinter program creates a window, gives it a title, and starts the event loop. Run the code below and a blank window will open on your screen.

python
import tkinter as tk

root = tk.Tk()
root.title("My First Window")
root.geometry("400x300")
root.mainloop()

Walking through each line: import tkinter as tk loads the library and gives it the short alias tk, which is the convention you will see everywhere. tk.Tk() creates the root window — there is exactly one root window in a tkinter application. .title() sets the text that appears in the window's title bar. .geometry("400x300") sets the initial width and height in pixels. root.mainloop() starts the event loop and must be the last line in your script.

Pro Tip

If the window appears but closes immediately without an error, the likely cause is that mainloop() is missing or placed before the window setup. Move it to the final line of your script.

code builder click a token to place it

Build the correct line to import tkinter and assign it the standard alias:

your code will appear here...
as tkinter from import tk *
Why: The correct form is import tkinter as tk. The keyword import comes first, then the module name tkinter, then as, then the alias tk. Using from tkinter import * would also work but pollutes the namespace and is discouraged in production code.

Widgets: Labels, Buttons, and Entry Fields

A window with nothing in it is just a container. Widgets are the elements that make a program usable — text, buttons, input boxes, checkboxes, menus. Every widget is a Python class in tkinter. You create an instance, configure it, and then call a geometry manager to make it appear.

Label

A Label displays static text or an image. It does not respond to user input — it is purely for showing information.

python
label = tk.Label(root, text="Enter the bill amount:")
label.pack(pady=8)

Entry

An Entry widget accepts a single line of text from the user. To read what the user typed, use a StringVar bound to the widget via the textvariable parameter, then call .get() on the variable.

python
bill_var = tk.StringVar()
entry = tk.Entry(root, textvariable=bill_var, width=20)
entry.pack(pady=4)

# Later, inside a function:
value = bill_var.get()   # returns the current text as a string

Button

A Button runs a function when clicked. Pass the function using the command keyword — without parentheses, otherwise the function runs immediately when the window opens rather than when the button is clicked.

python
def calculate():
    print("Button clicked")

btn = tk.Button(root, text="Calculate Tip", command=calculate)
btn.pack(pady=10)
spot the bug click the line that contains the bug

The Button below has a bug that causes the function to run immediately when the window opens instead of when the button is clicked. Click the line you think is wrong.

1 import tkinter as tk
2 root = tk.Tk()
3 def greet():
4 btn = tk.Button(root, text="Hello", command=greet())
5 btn.pack()
6 root.mainloop()
The fix: Change command=greet() to command=greet. Writing greet() calls the function immediately when Python evaluates that line. Passing greet without parentheses hands the function object to tkinter so it can call it later, when the button is clicked.

Geometry Managers: pack, grid, and place

Creating a widget does not make it visible. You must call one of the three geometry managers to position it inside the window. Mixing geometry managers within the same container causes conflicts — pick one and use it consistently.

pack is the simplest manager. It stacks widgets in a line, top to bottom by default. Use the side parameter (tk.LEFT, tk.RIGHT, tk.TOP, tk.BOTTOM) and the pady / padx parameters for spacing.

grid places widgets in an invisible table of rows and columns. It is well suited for forms where labels and inputs need to line up. Use row= and column= keyword arguments.

place positions widgets at exact x/y pixel coordinates. This gives full control but makes layouts fragile when the window is resized. It is rarely the right choice for beginners.

python
# grid example — label in column 0, entry in column 1
tk.Label(root, text="Bill amount ($):").grid(row=0, column=0, sticky="e", padx=8, pady=6)
bill_entry.grid(row=0, column=1, padx=8, pady=6)

tk.Label(root, text="Tip percentage:").grid(row=1, column=0, sticky="e", padx=8, pady=6)
tip_entry.grid(row=1, column=1, padx=8, pady=6)
Warning

Never call both .pack() and .grid() on widgets that share the same parent frame or window. tkinter will enter an infinite loop trying to resolve the conflicting layout instructions, and the window will freeze.

How to Build a Desktop Program in Python

The following five steps assemble everything covered above into a complete, working tip calculator. Each step builds on the last. After step five you will have a program you can run, enter numbers into, click a button, and see a computed result — all inside a real desktop window.

  1. Import tkinter and create the main window

    At the top of a new Python file, write import tkinter as tk. Then create the root window: root = tk.Tk(). Set a title with root.title("Tip Calculator") and an initial size with root.geometry("320x220"). Do not call mainloop() yet — that comes last.

  2. Add widgets to the window

    Create two StringVar objects to hold the bill amount and tip percentage. Create Label widgets to describe each field, Entry widgets bound to those variables, a Button to trigger the calculation, and a result Label whose text you will update dynamically. Set the result label's textvariable to a third StringVar so you can update it without re-creating the widget.

  3. Position widgets with a geometry manager

    Call .grid() on each widget, assigning each a row and column. Put the labels in column 0 with sticky="e" so they right-align. Put the entries in column 1. Span the button and result label across both columns using columnspan=2 and center them with sticky="". Add padx=10 and pady=6 for breathing room.

  4. Write event handler functions

    Define a calculate_tip() function above the widget definitions. Inside it, call .get() on both StringVars and convert the results to floats. Compute the tip and total, format them as a string, and call .set() on the result StringVar to update the label. Wrap the conversion in a try/except ValueError so invalid input shows a friendly message instead of crashing. Pass the function to the Button via command=calculate_tip.

  5. Start the event loop

    As the final line of the file, call root.mainloop(). Run the script with python tip_calculator.py. A window opens, you can enter a bill amount and tip percentage, click the button, and the calculated tip and total appear in the result label — no terminal interaction required.

The complete tip calculator source code puts everything together:

python
import tkinter as tk

def calculate_tip():
    try:
        bill   = float(bill_var.get())
        pct    = float(tip_var.get())
        tip    = bill * (pct / 100)
        total  = bill + tip
        result_var.set(f"Tip: ${tip:.2f}   Total: ${total:.2f}")
    except ValueError:
        result_var.set("Please enter valid numbers.")

root = tk.Tk()
root.title("Tip Calculator")
root.geometry("320x220")
root.resizable(False, False)

bill_var   = tk.StringVar()
tip_var    = tk.StringVar(value="15")
result_var = tk.StringVar()

tk.Label(root, text="Bill amount ($):").grid(row=0, column=0, sticky="e", padx=10, pady=6)
tk.Entry(root, textvariable=bill_var, width=14).grid(row=0, column=1, padx=10, pady=6)

tk.Label(root, text="Tip percentage:").grid(row=1, column=0, sticky="e", padx=10, pady=6)
tk.Entry(root, textvariable=tip_var, width=14).grid(row=1, column=1, padx=10, pady=6)

tk.Button(root, text="Calculate", command=calculate_tip).grid(
    row=2, column=0, columnspan=2, pady=12)

tk.Label(root, textvariable=result_var, fg="#2ecc71").grid(
    row=3, column=0, columnspan=2)

root.mainloop()
"Simple is better than complex." — The Zen of Python, Tim Peters

Python Learning Summary Points

  1. tkinter is Python's built-in GUI toolkit. It ships with CPython on Windows and macOS and requires a single package install on most Linux distributions. No third-party dependencies are needed to get started.
  2. Every visible element in a tkinter program is a widget — an instance of a class like Label, Entry, or Button. Widgets must be attached to a parent window or frame and positioned with a geometry manager before they become visible.
  3. The three geometry managers are pack (linear stacking), grid (row/column table), and place (exact coordinates). Never mix pack and grid within the same parent container.
  4. Event-driven programming means the program waits for user actions rather than running top to bottom. Functions tied to widgets through the command parameter are called event handlers. Pass function names without parentheses so tkinter can call them later.
  5. StringVar and the other tkinter variable types (IntVar, DoubleVar, BooleanVar) keep Python variables and widget displays synchronized. Use .get() to read values and .set() to update them without rebuilding the widget.

Building a GUI program reinforces core Python skills — functions, exception handling, string formatting, and object instantiation — while producing something immediately tangible. Once you are comfortable with the tip calculator structure, applying the same pattern to other tools is straightforward: swap in different widgets, add more fields, or wrap the layout in frames to organize complex interfaces.

check your understanding question 1 of 5

Frequently Asked Questions

The standard library for building desktop programs in Python is tkinter. It ships with Python on Windows and macOS, so no separate installation is needed. On Linux you may need to install it through your package manager — for example with sudo apt install python3-tk on Debian-based systems.

On Windows and macOS, tkinter is included with the standard Python installer from python.org. On Debian or Ubuntu Linux you can install it by running sudo apt install python3-tk. No third-party packages or pip commands are required.

A widget is a visual element in a tkinter window. Labels, buttons, text entry fields, checkboxes, and dropdown menus are all widgets. Each widget is a Python object created from a tkinter class and must be placed in the window using a geometry manager before it becomes visible.

pack, grid, and place are tkinter geometry managers that control how widgets are positioned in a window. pack stacks widgets in a line and is the simplest option. grid arranges widgets in rows and columns, which makes it better for form-style layouts. place lets you position widgets at exact pixel coordinates, which gives full control but is harder to maintain. Never mix pack and grid within the same parent container.

mainloop() is the event loop that keeps your tkinter window open and responsive. When Python reaches this line, it hands control to tkinter, which watches for user actions such as mouse clicks and key presses and routes them to the appropriate handler functions. Without mainloop(), the window opens and closes immediately before you can interact with it.

Set the command parameter when you create the Button widget, passing the function name without parentheses. For example: btn = tk.Button(root, text="Click me", command=my_function). When the user clicks the button, tkinter calls my_function automatically.

StringVar is a tkinter variable type that keeps a text entry field and a Python variable synchronized. When you link a StringVar to an Entry widget via the textvariable parameter, calling .get() on the StringVar always returns the current contents of the input field, and calling .set() updates what the field displays.

Yes. tkinter is used in production tools and is the GUI toolkit built into CPython itself. IDLE, the Python editor that ships with Python, is written in tkinter. For projects that need a more modern look, libraries such as CustomTkinter extend tkinter with styled widgets while keeping the same programming model covered in this tutorial.