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
.pyfile 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
pythonfollowed 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
Calculatorclass 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_clickroutes button actions;
_handle_key_eventmaps 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.
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.