In this tutorial, we’ll build a modern GUI app in Python that:
Converts binary → decimal
Supports single and batch conversion
Detects invalid binaries
Shows live statistics
Supports dark mode
Can open/save .txt files
No advanced Tkinter knowledge required—everything is explained step by step.
🛠️ Prerequisites
Make sure you have:
Python 3.9+
Basic Python knowledge
Tkinter (comes bundled with Python)
sv-ttk for modern theming
Install sv-ttk:
pip install sv-ttk
1️⃣ Imports & Dependencies
We start by importing everything we’ll need.
import sys
import os
import threading
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import sv_ttk
Why these?
tkinter / ttk → GUI widgets
threading → delayed updates (prevents UI freezing)
filedialog & messagebox → file handling and alerts
sv_ttk → modern light/dark themes
2️⃣ Helper Functions
Resource Path Helper (for PyInstaller support)
def resource_path(file_name):
base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, file_name)
This ensures assets load correctly whether the app is:
Run normally
Packaged as an .exe
Status Bar Helper
def set_status(msg):
status_var.set(msg)
root.update_idletasks()
This updates the status bar without freezing the UI.
3️⃣ App Window Setup
root = tk.Tk()
root.title("Binary → Decimal Converter Pro")
root.geometry("1200x680")
sv_ttk.set_theme("light")
We:
Create the main window
Set a title and size
Apply a modern light theme
4️⃣ Global State Variables
Tkinter uses special variable classes to auto-update UI elements.
dark_mode_var = tk.BooleanVar(value=False)
binary_var = tk.StringVar()
decimal_var = tk.StringVar(value="0")
Statistics variables
stats_vars = {
"total_binaries": tk.StringVar(value="0"),
"valid": tk.StringVar(value="0"),
"invalid": tk.StringVar(value="0"),
"sum": tk.StringVar(value="0"),
}
5️⃣ Dark Mode Toggle
def toggle_theme():
style.theme_use("clam")
bg = "#2E2E2E" if dark_mode_var.get() else "#FFFFFF"
fg = "white" if dark_mode_var.get() else "black"
root.configure(bg=bg)
for w in ["TFrame", "TLabel", "TLabelframe", "TLabelframe.Label", "TCheckbutton"]:
style.configure(w, background=bg, foreground=fg)
What this does:
Switches background & text colors
Updates all major ttk widgets
Keeps the UI readable in both modes
6️⃣ Single Binary Conversion Logic
def convert_single_binary():
bin_str = binary_var.get().strip()
Validate input
if not bin_str:
decimal_var.set("0")
set_status("Enter a binary number")
return
Reject invalid binaries
if not all(c in "01" for c in bin_str):
decimal_var.set("Error")
set_status("Invalid binary number")
return
Convert safely
decimal_var.set(str(int(bin_str, 2)))
set_status(f"Converted {bin_str} → {decimal_var.get()}")
7️⃣ Batch Conversion Logic
def convert_batch():
content = batch_text.get("1.0", tk.END).strip().splitlines()
Track results
valid_count = 0
invalid_count = 0
total_sum = 0
results = []
Process each line
for line in content:
if all(c in "01" for c in line):
dec = int(line, 2)
results.append(f"{line} → {dec}")
valid_count += 1
total_sum += dec
else:
results.append(f"{line} → Invalid")
invalid_count += 1
Update UI & stats
batch_text.delete("1.0", tk.END)
batch_text.insert("1.0", "\n".join(results))
stats_vars["total_binaries"].set(len(content))
stats_vars["valid"].set(valid_count)
stats_vars["invalid"].set(invalid_count)
stats_vars["sum"].set(total_sum)
8️⃣ Delayed Auto-Conversion (Smooth UX)
Instead of converting on every keystroke, we add a short delay.
def delayed_single_convert(event=None):
threading.Timer(0.1, convert_single_binary).start()
def delayed_batch_convert(event=None):
threading.Timer(0.2, convert_batch).start()
This keeps the UI responsive.
9️⃣ File Open & Save
Open .txt file
def open_file():
path = filedialog.askopenfilename(filetypes=[("Text Files", "*.txt")])
with open(path, "r", encoding="utf-8") as f:
batch_text.insert("1.0", f.read())
Save results
def save_file():
path = filedialog.asksaveasfilename(defaultextension=".txt")
with open(path, "w", encoding="utf-8") as f:
f.write(batch_text.get("1.0", tk.END))
🔟 Main UI Layout
Title
ttk.Label(main, text="Binary → Decimal Converter Pro",
font=("Segoe UI", 20, "bold")).pack()
Single Conversion Section
input_entry = ttk.Entry(single_frame, textvariable=binary_var)
input_entry.bind("<KeyRelease>", delayed_single_convert)
Batch Conversion Textbox
batch_text = tk.Text(batch_frame, height=5)
batch_text.bind("<KeyRelease>", delayed_batch_convert)
Statistics Grid
for i, (label, var) in enumerate(stats_vars.items()):
ttk.Label(stats_frame, text=label.title()).grid(row=0, column=i*2)
ttk.Label(stats_frame, textvariable=var).grid(row=0, column=i*2+1)
1️⃣1️⃣ Action Buttons
ttk.Button(actions, text="📂 Open", command=open_file).pack(side="left")
ttk.Button(actions, text="💾 Save", command=save_file).pack(side="left")
ttk.Button(actions, text="🧹 Clear", command=clear_all).pack(side="left")
ttk.Button(actions, text="❓ Help", command=show_help).pack(side="left")
1️⃣2️⃣ Run the App
root.mainloop()
This starts the Tkinter event loop—and your app is live 🎉
🚀 Final Thoughts
You now have:
A polished Tkinter GUI
Live conversion logic
Batch processing
Dark mode
File support
💡 Ideas to extend it
Export CSV
Copy to clipboard
Add hex / octal support
Package with PyInstaller

Top comments (0)