DEV Community

Mate Technologies
Mate Technologies

Posted on

Building a Modern Calculator with Tkinter (Light & Dark Mode)

Simple Calculator Light Theme

Simple Calculator Dark Theme

Python’s tkinter often gets dismissed as “old-school”, but with the right styling and structure, you can build clean, modern desktop apps surprisingly fast.

In this post, we’ll build a simple calculator using:

tkinter & ttk

sv-ttk for modern light/dark themes

A clean, grid-based layout

Minimal but extensible logic

By the end, you’ll have a fully working calculator with Dark Mode support.

🧰 Requirements

Make sure you have Python 3 installed, then install sv-ttk:

pip install sv-ttk

🖥️ App Features

Basic arithmetic (+ - * /)

Responsive button grid

Error handling for invalid expressions

Light / Dark mode toggle

Clean, modern UI styling

📁 Project Structure

This app is contained in a single Python file, making it perfect for beginners or quick desktop utilities.

🧠 Key Concepts Used

  1. StringVar for Reactive UI

We use tk.StringVar() to automatically update the display whenever the expression changes.

  1. eval() for Fast Prototyping

For simplicity, the calculator evaluates expressions using eval().
⚠️ This is fine for learning or personal tools, but not recommended for untrusted input.

  1. sv-ttk Themes

sv-ttk instantly upgrades the look of ttk widgets and provides seamless dark mode support.

🧮 Full Calculator Code

import sys
import os
import tkinter as tk
from tkinter import ttk, messagebox
import sv_ttk


def resource_path(file_name):
    """Get the absolute path to a resource, works for PyInstaller."""
    base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, file_name)


# =========================
# App Setup
# =========================
root = tk.Tk()
root.title("Simple Calculator")
root.geometry("360x520")
root.resizable(False, False)

sv_ttk.set_theme("light")

# =========================
# Globals
# =========================
expression = tk.StringVar(value="")
dark_mode_var = tk.BooleanVar(value=False)

# =========================
# Helpers
# =========================
def append_value(val):
    expression.set(expression.get() + str(val))


def clear_all():
    expression.set("")


def calculate():
    try:
        result = eval(expression.get())
        expression.set(str(result))
    except Exception:
        messagebox.showerror("Error", "Invalid Expression")
        expression.set("")


def toggle_theme():
    sv_ttk.set_theme("dark" if dark_mode_var.get() else "light")


# =========================
# Styles
# =========================
style = ttk.Style()
style.theme_use("clam")

style.configure(
    "Calc.TButton",
    font=("Segoe UI", 14, "bold"),
    padding=10
)

style.configure(
    "Equals.TButton",
    font=("Segoe UI", 14, "bold"),
    padding=10
)

# =========================
# Display
# =========================
display_frame = ttk.Frame(root, padding=10)
display_frame.pack(fill="x")

display = ttk.Entry(
    display_frame,
    textvariable=expression,
    font=("Consolas", 20),
    justify="right"
)
display.pack(fill="x", ipady=10)

# =========================
# Buttons
# =========================
btn_frame = ttk.Frame(root, padding=10)
btn_frame.pack(expand=True, fill="both")

buttons = [
    ("7", 1, 0), ("8", 1, 1), ("9", 1, 2), ("/", 1, 3),
    ("4", 2, 0), ("5", 2, 1), ("6", 2, 2), ("*", 2, 3),
    ("1", 3, 0), ("2", 3, 1), ("3", 3, 2), ("-", 3, 3),
    ("0", 4, 0), (".", 4, 1), ("C", 4, 2), ("+", 4, 3),
]

for (text, r, c) in buttons:
    action = clear_all if text == "C" else lambda t=text: append_value(t)
    ttk.Button(
        btn_frame,
        text=text,
        command=action,
        style="Calc.TButton"
    ).grid(row=r, column=c, sticky="nsew", padx=5, pady=5)

# Equals button
ttk.Button(
    btn_frame,
    text="=",
    command=calculate,
    style="Equals.TButton"
).grid(row=5, column=0, columnspan=4, sticky="nsew", padx=5, pady=10)

# =========================
# Options
# =========================
options_frame = ttk.Frame(root, padding=10)
options_frame.pack(fill="x")

ttk.Checkbutton(
    options_frame,
    text="Dark Mode",
    variable=dark_mode_var,
    command=toggle_theme
).pack(anchor="w")

# =========================
# Grid Configuration
# =========================
for i in range(4):
    btn_frame.columnconfigure(i, weight=1)
for i in range(6):
    btn_frame.rowconfigure(i, weight=1)

# =========================
# Run App
# =========================
root.mainloop()
Enter fullscreen mode Exit fullscreen mode

🚀 Possible Improvements

If you want to extend this project:

Replace eval() with a safer expression parser

Add keyboard input support

Implement scientific functions (√, %, sin, cos)

Package it as an .exe with PyInstaller

Add history tracking

🎯 Final Thoughts

Tkinter doesn’t have to look outdated. With ttk, modern themes, and clean layout logic, you can build polished desktop tools quickly — especially for internal utilities, learning projects, or lightweight apps.

If you found this useful, feel free to remix it or build something bigger on top of it.

Happy hacking 🧠🐍

Top comments (0)