Skip to content

Commit 5b5790f

Browse files
authored
Create Calculator-with-history.py
1 parent 52587ac commit 5b5790f

1 file changed

Lines changed: 269 additions & 0 deletions

File tree

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
import tkinter as tk
2+
from tkinter import messagebox
3+
4+
# =========================
5+
# THEME
6+
# =========================
7+
APP_BG = "#121212"
8+
PANEL_BG = "#1F1F1F"
9+
BTN_BG = "#2C2C2C"
10+
BTN_HOVER = "#3A3A3A"
11+
BTN_ACTIVE = "#FF6F61"
12+
ACCENT = "#FF6F61"
13+
TEXT_CLR = "#E0E0E0"
14+
SUBTEXT_CLR = "#AAAAAA"
15+
INPUT_BG = "#333333"
16+
INPUT_FG = "#FFFFFF"
17+
18+
# =========================
19+
# APP
20+
# =========================
21+
class CalculatorApp:
22+
def __init__(self, root):
23+
self.root = root
24+
root.title("MateTools – Pro Calculator")
25+
root.geometry("1000x500")
26+
root.configure(bg=APP_BG)
27+
root.resizable(False, False)
28+
29+
# =========================
30+
# LEFT PANEL (Actions)
31+
# =========================
32+
left = tk.Frame(root, bg=PANEL_BG, width=420)
33+
left.pack(side="left", fill="y")
34+
35+
header = tk.Frame(left, bg=PANEL_BG)
36+
header.pack(fill="x", padx=16, pady=(18, 10))
37+
38+
tk.Label(
39+
header,
40+
text="MateTools",
41+
bg=PANEL_BG,
42+
fg=ACCENT,
43+
font=("Segoe UI", 20, "bold")
44+
).pack(side="left")
45+
46+
tk.Frame(left, bg=ACCENT, height=2).pack(fill="x", padx=16, pady=(0, 14))
47+
48+
tk.Label(
49+
left,
50+
text="Pro Calculator",
51+
bg=PANEL_BG,
52+
fg=TEXT_CLR,
53+
font=("Segoe UI", 14, "bold")
54+
).pack(anchor="w", padx=16, pady=(0, 2))
55+
56+
tk.Label(
57+
left,
58+
text="Perform calculations with history",
59+
bg=PANEL_BG,
60+
fg=SUBTEXT_CLR,
61+
font=("Segoe UI", 10)
62+
).pack(anchor="w", padx=16, pady=(0, 16))
63+
64+
tk.Frame(left, bg=BTN_BG, height=1).pack(fill="x", padx=16, pady=(0, 16))
65+
66+
btn_frame = tk.Frame(left, bg=PANEL_BG)
67+
btn_frame.pack(fill="x", padx=16, pady=16)
68+
69+
def make_btn(text, cmd, color=BTN_BG):
70+
btn = tk.Button(
71+
btn_frame,
72+
text=text,
73+
command=cmd,
74+
bg=color,
75+
fg="white",
76+
font=("Segoe UI", 11, "bold"),
77+
relief="flat",
78+
height=2,
79+
width=20
80+
)
81+
# Hover effect
82+
btn.bind("<Enter>", lambda e, b=btn: b.config(bg=BTN_HOVER))
83+
btn.bind("<Leave>", lambda e, b=btn, c=color: b.config(bg=c))
84+
btn.bind("<ButtonPress-1>", lambda e, b=btn: b.config(bg=BTN_ACTIVE))
85+
btn.bind("<ButtonRelease-1>", lambda e, b=btn, c=color: b.config(bg=BTN_HOVER))
86+
return btn
87+
88+
make_btn("Clear Input", self.clear_input, ACCENT).pack(side="top", pady=8)
89+
make_btn("Clear History", self.clear_history, BTN_BG).pack(side="top", pady=8)
90+
make_btn("About", self.show_about, BTN_BG).pack(side="top", pady=20)
91+
92+
# =========================
93+
# RIGHT PANEL (Calculator UI)
94+
# =========================
95+
right = tk.Frame(root, bg=APP_BG)
96+
right.pack(side="right", fill="both", expand=True)
97+
98+
self.result_card = tk.Frame(right, bg=PANEL_BG, bd=2, relief="ridge")
99+
self.result_card.pack(padx=30, pady=20, fill="both", expand=True)
100+
101+
# ---------- TOP: Calculator Label ----------
102+
tk.Label(
103+
self.result_card,
104+
text="Calculator",
105+
bg=PANEL_BG,
106+
fg=TEXT_CLR,
107+
font=("Segoe UI", 18, "bold")
108+
).pack(pady=(20, 10))
109+
110+
# ---------- MAIN FRAME: split left/right ----------
111+
main_frame = tk.Frame(self.result_card, bg=PANEL_BG)
112+
main_frame.pack(fill="both", expand=True, padx=20, pady=10)
113+
114+
# ===== LEFT COLUMN: Input + Buttons =====
115+
left_frame = tk.Frame(main_frame, bg=PANEL_BG)
116+
left_frame.pack(side="left", fill="y", padx=(0, 15))
117+
118+
# Input Entry
119+
self.input_var = tk.StringVar()
120+
self.input_entry = tk.Entry(
121+
left_frame,
122+
textvariable=self.input_var,
123+
bg=INPUT_BG,
124+
fg=INPUT_FG,
125+
font=("Segoe UI", 18),
126+
relief="flat",
127+
justify="right"
128+
)
129+
self.input_entry.pack(fill="x", pady=(0, 10))
130+
self.input_entry.bind("<Return>", lambda event: self.calculate())
131+
132+
# Button Grid
133+
btn_frame = tk.Frame(left_frame, bg=PANEL_BG)
134+
btn_frame.pack()
135+
136+
buttons = [
137+
('7', '8', '9', '/'),
138+
('4', '5', '6', '*'),
139+
('1', '2', '3', '-'),
140+
('0', '.', '=', '+'),
141+
]
142+
143+
for r, row in enumerate(buttons):
144+
for c, char in enumerate(row):
145+
if char == '=':
146+
btn = tk.Button(
147+
btn_frame, text=char, bg=ACCENT, fg="white",
148+
font=("Segoe UI", 14, "bold"), relief="flat",
149+
width=5, height=2,
150+
command=self.calculate
151+
)
152+
btn.bind("<Enter>", lambda e, b=btn: b.config(bg="#FF8679"))
153+
btn.bind("<Leave>", lambda e, b=btn: b.config(bg=ACCENT))
154+
btn.bind("<ButtonPress-1>", lambda e, b=btn: b.config(bg="#FF4F3F"))
155+
btn.bind("<ButtonRelease-1>", lambda e, b=btn: b.config(bg="#FF8679"))
156+
else:
157+
btn = tk.Button(
158+
btn_frame, text=char, bg=BTN_BG, fg="white",
159+
font=("Segoe UI", 14, "bold"), relief="flat",
160+
width=5, height=2,
161+
command=lambda ch=char: self.add_to_input(ch)
162+
)
163+
btn.bind("<Enter>", lambda e, b=btn: b.config(bg=BTN_HOVER))
164+
btn.bind("<Leave>", lambda e, b=btn: b.config(bg=BTN_BG))
165+
btn.bind("<ButtonPress-1>", lambda e, b=btn: b.config(bg=BTN_ACTIVE))
166+
btn.bind("<ButtonRelease-1>", lambda e, b=btn: b.config(bg=BTN_HOVER))
167+
btn.grid(row=r, column=c, padx=5, pady=5)
168+
169+
# ===== RIGHT COLUMN: Result + History =====
170+
right_frame = tk.Frame(main_frame, bg=PANEL_BG)
171+
right_frame.pack(side="right", fill="both", expand=True)
172+
173+
# Result display in card-like style
174+
result_card = tk.Frame(right_frame, bg="#1C1C1C", bd=1, relief="ridge")
175+
result_card.pack(fill="x", pady=(0, 10))
176+
177+
tk.Label(
178+
result_card,
179+
text="Result",
180+
bg="#1C1C1C",
181+
fg=SUBTEXT_CLR,
182+
font=("Segoe UI", 12, "bold")
183+
).pack(anchor="w", padx=10, pady=(5, 0))
184+
185+
self.result_label = tk.Label(
186+
result_card,
187+
text="--",
188+
bg="#1C1C1C",
189+
fg=ACCENT,
190+
font=("Segoe UI", 18, "bold")
191+
)
192+
self.result_label.pack(anchor="e", padx=10, pady=(0, 5))
193+
194+
# History display in scrollable frame
195+
history_card = tk.Frame(right_frame, bg="#1C1C1C", bd=1, relief="ridge")
196+
history_card.pack(fill="both", expand=True)
197+
198+
tk.Label(
199+
history_card,
200+
text="History",
201+
bg="#1C1C1C",
202+
fg=SUBTEXT_CLR,
203+
font=("Segoe UI", 12, "bold")
204+
).pack(anchor="w", padx=10, pady=(5, 0))
205+
206+
self.history_box = tk.Listbox(
207+
history_card,
208+
bg=INPUT_BG,
209+
fg=INPUT_FG,
210+
font=("Segoe UI", 12),
211+
height=10,
212+
selectbackground=ACCENT,
213+
relief="flat"
214+
)
215+
self.history_box.pack(fill="both", expand=True, padx=10, pady=(0, 10))
216+
217+
self.history = []
218+
219+
# =========================
220+
# METHODS
221+
# =========================
222+
def add_to_input(self, char):
223+
self.input_var.set(self.input_var.get() + char)
224+
225+
def calculate(self):
226+
expr = self.input_var.get()
227+
if not expr.strip():
228+
return
229+
try:
230+
result = round(eval(expr), 6) # Round to 6 decimal places
231+
self.result_label.config(text=f"{result}")
232+
# Append to history and keep only last 10 items
233+
self.history.append(f"{expr} = {result}")
234+
self.history = self.history[-10:]
235+
self.update_history()
236+
self.input_var.set(str(result))
237+
except Exception as e:
238+
messagebox.showerror("Error", f"Invalid expression: {e}")
239+
240+
def update_history(self):
241+
self.history_box.delete(0, tk.END)
242+
for item in self.history:
243+
self.history_box.insert(tk.END, item)
244+
245+
def clear_input(self):
246+
self.input_var.set("")
247+
248+
def clear_history(self):
249+
self.history = []
250+
self.update_history()
251+
252+
def show_about(self):
253+
messagebox.showinfo(
254+
"About",
255+
"MateTools – Pro Calculator\n\n"
256+
"• Perform calculations instantly\n"
257+
"• Click buttons or type expressions\n"
258+
"• Keep track of history (last 10 calculations)\n"
259+
"• Results are rounded to 6 decimal places\n\n"
260+
"Built by MateTools"
261+
)
262+
263+
# =========================
264+
# RUN
265+
# =========================
266+
if __name__ == "__main__":
267+
root = tk.Tk()
268+
CalculatorApp(root)
269+
root.mainloop()

0 commit comments

Comments
 (0)