Build a Feature‑Rich Python Calculator with Tkinter – Full Code & Walkthrough
Learn how to create a fully functional Python calculator using Tkinter, covering complete requirements, UI design, button layout, advanced math operations, dynamic font scaling, keyboard handling, and extensibility suggestions, with the entire source code and detailed explanations for each component.
Functional Requirements
The calculator should support basic arithmetic (addition, subtraction, multiplication, division), advanced operations (square root, percentage, exponentiation), trigonometric functions (sin, cos, tan), logarithmic functions (natural log and common log), the constant π, a clear display area with history, responsive button colors, keyboard input, and user instructions.
Complete Code and Execution
Copy the following code into a .py file and run it with python filename.py. No external libraries are required.
import tkinter as tk
from tkinter import font
import math
import re
class Calculator:
def __init__(self, root):
self.root = root
self.root.title("高级计算器")
self.root.geometry("400x600")
self.root.resizable(False, False)
self.root.configure(bg="#f0f0f0")
self.display_font = font.Font(family="SimHei", size=24)
self.button_font = font.Font(family="SimHei", size=14)
self.current_expression = ""
self.last_result = ""
self.is_new_calculation = True
self._create_display()
self._create_buttons()
self.root.bind("<Key>", self._handle_key_event)
def _create_display(self):
self.history_frame = tk.Frame(self.root, bg="#f0f0f0", height=50)
self.history_frame.pack(fill=tk.X, padx=10, pady=(10, 0))
self.history_frame.pack_propagate(0)
self.history_label = tk.Label(self.history_frame, text="", bg="#f0f0f0", fg="#888", font=self.display_font, anchor=tk.E)
self.history_label.pack(fill=tk.BOTH, padx=5)
self.display_frame = tk.Frame(self.root, bg="#f0f0f0", height=80)
self.display_frame.pack(fill=tk.X, padx=10, pady=5)
self.display_frame.pack_propagate(0)
self.display = tk.Entry(self.display_frame, font=self.display_font, bg="white", fg="black", justify=tk.RIGHT, bd=5, relief=tk.SUNKEN, state="readonly")
self.display.pack(fill=tk.BOTH, padx=5, pady=5)
self.display.insert(0, "0")
self.display.configure(state="readonly")
def _create_buttons(self):
button_frame = tk.Frame(self.root, bg="#f0f0f0")
button_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
buttons = [
("7",1,0), ("8",1,1), ("9",1,2), ("/",1,3), ("C",1,4),
("4",2,0), ("5",2,1), ("6",2,2), ("*",2,3), ("⌫",2,4),
("1",3,0), ("2",3,1), ("3",3,2), ("-",3,3), ("(",3,4),
("0",4,0), (".",4,1), ("=",4,2), ("+",4,3), (")",4,4),
("%",5,0), ("√",5,1), ("^",5,2), ("π",5,3), ("sin",5,4),
("cos",6,0), ("tan",6,1), ("ln",6,2), ("log",6,3), ("1/x",6,4)
]
for text, row, col in buttons:
if text == "=":
bg_color, fg_color = "#4CAF50", "white"
elif text in ("C", "⌫"):
bg_color, fg_color = "#f44336", "white"
elif col in (3,4):
bg_color, fg_color = "#2196F3", "white"
else:
bg_color, fg_color = "#e0e0e0", "black"
button = tk.Button(button_frame, text=text, font=self.button_font, bg=bg_color, fg=fg_color,
relief=tk.RAISED, bd=3, padx=10, pady=10,
command=lambda txt=text: self._button_click(txt))
button.grid(row=row, column=col, padx=5, pady=5, sticky="nsew")
for i in range(7):
button_frame.grid_rowconfigure(i, weight=1)
for i in range(5):
button_frame.grid_columnconfigure(i, weight=1)
def _button_click(self, text):
if text == "C":
self._clear_all()
elif text == "⌫":
self._backspace()
elif text == "=":
self._calculate()
elif text == "π":
self._append_value(str(math.pi))
elif text == "√":
self._calculate_sqrt()
elif text == "^":
self._append_value("**")
elif text in ("sin", "cos", "tan"):
self._calculate_trig(text)
elif text == "ln":
self._calculate_ln()
elif text == "log":
self._calculate_log()
elif text == "1/x":
self._calculate_reciprocal()
elif text == "%":
self._calculate_percentage()
else:
self._append_value(text)
def _handle_key_event(self, event):
key = event.char
if key.isdigit() or key in "+-*/().":
self._append_value(key)
elif key in ("\r", "="):
self._calculate()
elif key == "\x08":
self._backspace()
elif key.lower() == "c":
self._clear_all()
# ... Additional methods for _append_value, _clear_all, _backspace, _update_display,
# _calculate, _calculate_sqrt, _calculate_trig, _calculate_ln, _calculate_log,
# _calculate_reciprocal, _calculate_percentage are defined similarly, handling
# expression parsing, error catching, history updates, and display refresh.
if __name__ == "__main__":
root = tk.Tk()
app = Calculator(root)
root.mainloop()Running the Application
Open a command prompt, type python followed by a space, drag the saved file into the window, and press Enter. The calculator window will appear.
Code Walkthrough
The application is built with an object‑oriented structure. The Calculator class creates and manages the GUI, processes user input (both button clicks and keyboard events), performs calculations, and updates the display.
Overall Architecture: The class initializes the root window, sets title, size, and background, and defines fonts.
Display Area: Two sections – a history label showing the previous expression and result, and a read‑only entry showing the current expression.
Button Layout: Buttons are defined in a list and placed on a 6×5 grid. Colors differentiate functions: green for “=”, red for clear/backspace, blue for operators, gray for digits.
Core Calculation: eval() evaluates the expression after replacing π and e. Results are formatted to avoid long floating‑point strings.
Advanced Functions: Separate methods handle square root, trigonometric functions (with degree‑to‑radian conversion), natural and common logarithms, reciprocal, and percentage calculations, each with error handling.
User Input: _button_click routes button actions; _handle_key_event maps keyboard keys to the same logic, supporting digits, operators, Enter, Backspace, and clear.
Dynamic Font Adjustment: If the expression exceeds 15 characters, the font size shrinks from 24 pt to 18 pt to keep the whole expression visible.
Program Entry: The standard if __name__ == "__main__" block creates the Tkinter root and starts the main event loop.
Extension Ideas
Add memory buttons (M+, M-, MR, MC) for storing values.
Implement scientific notation for very large or small results.
Provide base conversion (binary, octal, decimal, hexadecimal).
Show matching parentheses with color cues.
Store multiple history entries and allow reusing them.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
