DEV Community

Mate Technologies
Mate Technologies

Posted on

🧮 Building a Modern Statistics Calculator in Python with Tkinter

Python is often praised for its data science ecosystem, but you don’t always need Pandas or NumPy to build something useful.

In this post, we’ll build StatMate — a clean, modern desktop statistics calculator using:

🪟 Tkinter (Python’s standard GUI library)

🎨 sv-ttk for modern theming

📊 Python’s built-in statistics module

By the end, you’ll have a polished GUI app that calculates:

Mean

Median

Mode

Variance

Standard Deviation

Min / Max
with real-time input validation and configurable decimal precision.

✨ Features

Modern light theme using sv-ttk

Real-time input validation

Placeholder text UX

Adjustable decimal precision

Clean status bar feedback

Graceful error handling

📦 Requirements

Install the only external dependency:

pip install sv-ttk

Everything else comes from Python’s standard library.

🧠 Design Overview

The app is structured into logical sections:

Helpers

Formatting

Status updates

Validation

Regex-based numeric input filtering

Statistics Logic

Uses Python’s statistics module

UI Layout

Cards, labels, buttons, and result panel

UX Enhancements

Placeholder text

Status bar

Precision control

🧮 How the Calculation Works

The user enters numbers as a comma-separated list:

1, 2, 3, 4, 5

We:

Parse and sanitize the input

Convert values to floats

Compute statistics safely

Format output based on selected precision

Edge cases (like no unique mode or a single value) are handled gracefully.

🧑‍💻 Full Source Code

import tkinter as tk
from tkinter import ttk, messagebox
import sv_ttk
import statistics
import re

# =========================
# Helpers
# =========================
def set_status(msg):
    status_var.set(msg)
    root.update_idletasks()

def fmt(value):
    try:
        p = precision_var.get()
        return f"{value:.{p}f}"
    except Exception:
        return str(value)

def calculate_stats():
    raw_input = numbers_entry.get()
    if raw_input.strip() == 'e.g., 1, 2, 3, 4':
        messagebox.showerror("Invalid Input", "Please enter a valid list of numbers.")
        return
    try:
        numbers = [float(x.strip()) for x in raw_input.split(",") if x.strip() != ""]
        if not numbers:
            raise ValueError

        mean_val = statistics.mean(numbers)
        median_val = statistics.median(numbers)
        try:
            mode_val = statistics.mode(numbers)
        except statistics.StatisticsError:
            mode_val = "No unique mode"
        variance_val = statistics.variance(numbers) if len(numbers) > 1 else 0
        stdev_val = statistics.stdev(numbers) if len(numbers) > 1 else 0

        result_var.set(
            f"📊 Mean: {fmt(mean_val)}\n"
            f"📌 Median: {fmt(median_val)}\n"
            f"🎯 Mode: {mode_val}\n"
            f"📈 Variance: {fmt(variance_val)}\n"
            f"📉 Std. Dev.: {fmt(stdev_val)}\n"
            f"🔽 Min: {fmt(min(numbers))}\n"
            f"🔼 Max: {fmt(max(numbers))}"
        )
        set_status("✅ Statistics calculated successfully")
    except ValueError:
        messagebox.showerror("Invalid Input", "Please enter a valid list of numbers.")

def validate_input(new_value):
    if new_value == '' or new_value == 'e.g., 1, 2, 3, 4':
        return True
    return re.match(r'^[0-9.,\s-]*$', new_value) is not None

# =========================
# App Setup
# =========================
root = tk.Tk()
root.title("StatMate - Full Statistics Tool")
root.geometry("950x650")
root.minsize(950, 650)
sv_ttk.set_theme("light")

precision_var = tk.IntVar(value=4)
status_var = tk.StringVar(value="Ready")

ttk.Label(root, textvariable=status_var, anchor="w",
          font=("Segoe UI", 10), padding=(10, 5)
).pack(side="bottom", fill="x")

main_frame = ttk.Frame(root, padding=20)
main_frame.pack(expand=True, fill="both")

ttk.Label(main_frame, text="StatMate",
          font=("Segoe UI", 28, "bold")
).pack(anchor="w")

ttk.Label(main_frame, text="Full Statistics Calculator",
          font=("Segoe UI", 14), foreground="#555"
).pack(anchor="w", pady=(0, 20))

input_card = ttk.LabelFrame(main_frame, text="Input Numbers & Precision", padding=20)
input_card.pack(fill="x", pady=(0, 20))

input_row = ttk.Frame(input_card)
input_row.pack(fill="x")

def on_entry_click(event):
    if numbers_entry.get() == 'e.g., 1, 2, 3, 4':
        numbers_entry.delete(0, "end")
        numbers_entry.config(fg='black')

def on_focusout(event):
    if numbers_entry.get() == '':
        numbers_entry.insert(0, 'e.g., 1, 2, 3, 4')
        numbers_entry.config(fg='grey')

ttk.Label(input_row, text="Numbers:").grid(row=0, column=0)
numbers_entry = tk.Entry(input_row, font=("Segoe UI", 14), width=40, fg='grey')
numbers_entry.insert(0, 'e.g., 1, 2, 3, 4')
numbers_entry.bind('<FocusIn>', on_entry_click)
numbers_entry.bind('<FocusOut>', on_focusout)
numbers_entry.grid(row=0, column=1, padx=(5, 20))

vcmd = (root.register(validate_input), '%P')
numbers_entry.config(validate='key', validatecommand=vcmd)

ttk.Label(input_row, text="Decimal Precision:").grid(row=0, column=2)
ttk.Spinbox(input_row, from_=0, to=10,
            textvariable=precision_var, width=5
).grid(row=0, column=3, padx=(5, 0))

ttk.Button(main_frame, text="📊 Calculate Statistics",
           command=calculate_stats,
           style="Accent.TButton"
).pack(pady=20, ipadx=10, ipady=10)

result_card = ttk.LabelFrame(main_frame, text="Results", padding=20)
result_card.pack(fill="both", expand=True)

result_var = tk.StringVar(value="—")
tk.Label(result_card, textvariable=result_var,
         font=("Segoe UI", 16, "bold"),
         justify="left", anchor="nw",
         bd=2, relief="groove", padx=10, pady=10
).pack(fill="both", expand=True)

root.mainloop()
Enter fullscreen mode Exit fullscreen mode

🚀 Possible Improvements

Export results to CSV

Add histogram visualization

Dark mode toggle

Keyboard shortcuts

Save/load datasets

🎯 Final Thoughts

Tkinter doesn’t have to look outdated. With a bit of structure, validation, and theming, you can build clean, professional desktop apps using only Python.

If you enjoyed this project, consider extending it—or turning it into a reusable statistics toolkit.

Happy building! 🧠📊

StatMate launches with a clean, modern interface built using Tkinter and sv-ttk. The layout is designed for clarity and ease of use.

Top comments (0)