Skip to content

Commit dada64e

Browse files
authored
this is my first python pojrct
1 parent de81006 commit dada64e

1 file changed

Lines changed: 180 additions & 0 deletions

File tree

máy tính.py

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# -*- coding: utf-8 -*-
2+
import tkinter as tk
3+
from tkinter import font
4+
import math
5+
6+
# --- CÁC HÀM XỬ LÝ TOÁN HỌC AN TOÀN ---
7+
8+
# Định nghĩa các hàm wrapper để tính toán an toàn, đặc biệt là chuyển đổi độ sang radian cho các hàm lượng giác
9+
def sin_deg(x):
10+
return math.sin(math.radians(x))
11+
12+
def cos_deg(x):
13+
return math.cos(math.radians(x))
14+
15+
def tan_deg(x):
16+
# Xử lý trường hợp tan(90), tan(270),...
17+
if x % 180 == 90:
18+
return float('inf') # Trả về vô cực
19+
return math.tan(math.radians(x))
20+
21+
# Tạo một dictionary chứa các hàm và hằng số an toàn để sử dụng với eval()
22+
# Điều này ngăn chặn việc thực thi các mã độc hại.
23+
SAFE_EVAL_DICT = {
24+
"sin": sin_deg,
25+
"cos": cos_deg,
26+
"tan": tan_deg,
27+
"sqrt": math.sqrt,
28+
"log": math.log10, # log cơ số 10
29+
"ln": math.log, # log cơ số e
30+
"factorial": math.factorial,
31+
"pi": math.pi,
32+
"e": math.e,
33+
"pow": pow,
34+
}
35+
36+
# --- CÁC HÀM XỬ LÝ GIAO DIỆN ---
37+
38+
def on_button_click(char):
39+
"""
40+
Hàm này được gọi khi người dùng nhấn một nút.
41+
Nó sẽ thêm ký tự hoặc chuỗi tương ứng vào ô hiển thị.
42+
"""
43+
current_text = display.get()
44+
# Xóa nội dung "Lỗi" hoặc "0" ban đầu khi người dùng bắt đầu nhập
45+
if current_text == "Lỗi" or (current_text == "0" and char not in ".(+-×÷"):
46+
display.delete(0, tk.END)
47+
display.insert(tk.END, str(char))
48+
49+
def calculate():
50+
"""
51+
Hàm này được gọi khi người dùng nhấn nút "=".
52+
Nó sẽ lấy biểu thức từ ô hiển thị, thay thế các ký tự cho thân thiện
53+
với Python, và tính toán kết quả một cách an toàn bằng eval().
54+
"""
55+
try:
56+
expression = display.get().replace("÷", "/").replace("×", "*").replace("√", "sqrt").replace("π", "pi")
57+
58+
# Xử lý giai thừa (x!) và lũy thừa (x^y)
59+
expression = expression.replace("!", "factorial")
60+
expression = expression.replace("^", "**")
61+
62+
# Tính toán an toàn với eval
63+
result = eval(expression, {"__builtins__": None}, SAFE_EVAL_DICT)
64+
65+
display.delete(0, tk.END)
66+
# Hiển thị số nguyên nếu kết quả không có phần thập phân
67+
if result == int(result):
68+
display.insert(0, str(int(result)))
69+
else:
70+
# Làm tròn kết quả để tránh các số thập phân quá dài
71+
display.insert(0, str(round(result, 10)))
72+
except Exception as e:
73+
# Nếu có lỗi, hiển thị "Lỗi"
74+
display.delete(0, tk.END)
75+
display.insert(0, "Lỗi")
76+
print(f"Lỗi tính toán: {e}") # In lỗi ra console để debug
77+
78+
def clear_display():
79+
"""
80+
Hàm này được gọi khi người dùng nhấn nút "C".
81+
Nó sẽ xóa toàn bộ nội dung và đặt lại là "0".
82+
"""
83+
display.delete(0, tk.END)
84+
display.insert(0, "0")
85+
86+
def delete_char():
87+
"""
88+
Hàm này xóa ký tự cuối cùng trong ô hiển thị (chức năng Backspace).
89+
"""
90+
current_text = display.get()
91+
if current_text != "Lỗi" and len(current_text) > 0:
92+
new_text = current_text[:-1]
93+
display.delete(0, tk.END)
94+
if not new_text:
95+
display.insert(0, "0")
96+
else:
97+
display.insert(0, new_text)
98+
99+
# --- THIẾT LẬP GIAO DIỆN ---
100+
101+
window = tk.Tk()
102+
window.title("Máy Tính Khoa Học")
103+
window.geometry("450x650")
104+
window.minsize(450, 650)
105+
window.configure(bg="#1c1c1c")
106+
107+
window.grid_rowconfigure(0, weight=2)
108+
window.grid_rowconfigure(1, weight=5)
109+
window.grid_columnconfigure(0, weight=1)
110+
111+
display_font = font.Font(family="Helvetica", size=48)
112+
button_font = font.Font(family="Helvetica", size=16)
113+
114+
display = tk.Entry(
115+
window, font=display_font, bg="#1c1c1c", fg="white",
116+
borderwidth=0, justify="right", relief="flat"
117+
)
118+
display.grid(row=0, column=0, sticky="nsew", padx=20, pady=(20, 0))
119+
display.insert(0, "0")
120+
121+
button_frame = tk.Frame(window, bg="#1c1c1c")
122+
button_frame.grid(row=1, column=0, sticky="nsew", padx=10, pady=10)
123+
124+
for i in range(5): button_frame.grid_columnconfigure(i, weight=1)
125+
for i in range(6): button_frame.grid_rowconfigure(i, weight=1)
126+
127+
buttons_layout = [
128+
# text, command, row, col, [colspan], [bg_color], [fg_color]
129+
('sin', lambda: on_button_click('sin('), 0, 0, 1, '#2a2a2a'),
130+
('cos', lambda: on_button_click('cos('), 0, 1, 1, '#2a2a2a'),
131+
('tan', lambda: on_button_click('tan('), 0, 2, 1, '#2a2a2a'),
132+
('DEL', delete_char, 0, 3, 1, '#a6a6a6', 'black'),
133+
('C', clear_display, 0, 4, 1, '#a6a6a6', 'black'),
134+
135+
('log', lambda: on_button_click('log('), 1, 0, 1, '#2a2a2a'),
136+
('ln', lambda: on_button_click('ln('), 1, 1, 1, '#2a2a2a'),
137+
('x²', lambda: on_button_click('**2'), 1, 2, 1, '#2a2a2a'),
138+
('xʸ', lambda: on_button_click('^'), 1, 3, 1, '#2a2a2a'),
139+
('√', lambda: on_button_click('√('), 1, 4, 1, '#2a2a2a'),
140+
141+
('(', lambda: on_button_click('('), 2, 0, 1, '#2a2a2a'),
142+
(')', lambda: on_button_click(')'), 2, 1, 1, '#2a2a2a'),
143+
('x!', lambda: on_button_click('!'), 2, 2, 1, '#2a2a2a'),
144+
('π', lambda: on_button_click('π'), 2, 3, 1, '#2a2a2a'),
145+
('÷', lambda: on_button_click('÷'), 2, 4, 1, '#ff9500'),
146+
147+
('7', lambda: on_button_click('7'), 3, 0),
148+
('8', lambda: on_button_click('8'), 3, 1),
149+
('9', lambda: on_button_click('9'), 3, 2),
150+
('×', lambda: on_button_click('×'), 3, 3, 1, '#ff9500'),
151+
('-', lambda: on_button_click('-'), 3, 4, 1, '#ff9500'),
152+
153+
('4', lambda: on_button_click('4'), 4, 0),
154+
('5', lambda: on_button_click('5'), 4, 1),
155+
('6', lambda: on_button_click('6'), 4, 2),
156+
('+', lambda: on_button_click('+'), 4, 3, 1, '#ff9500'),
157+
('=', calculate, 4, 4, 1, '#ff9500', 'white', 2), # rowspan=2
158+
159+
('1', lambda: on_button_click('1'), 5, 0),
160+
('2', lambda: on_button_click('2'), 5, 1),
161+
('3', lambda: on_button_click('3'), 5, 2),
162+
('0', lambda: on_button_click('0'), 6, 0, 2),
163+
('.', lambda: on_button_click('.'), 6, 2),
164+
]
165+
166+
for config in buttons_layout:
167+
text, cmd, row, col = config[:4]
168+
colspan = config[4] if len(config) > 4 else 1
169+
bg = config[5] if len(config) > 5 else '#333333'
170+
fg = config[6] if len(config) > 6 else 'white'
171+
rowspan = config[7] if len(config) > 7 else 1
172+
173+
button = tk.Button(
174+
button_frame, text=text, font=button_font, bg=bg, fg=fg,
175+
borderwidth=0, relief="flat", activebackground="#555555",
176+
activeforeground="white", command=cmd
177+
)
178+
button.grid(row=row, column=col, rowspan=rowspan, columnspan=colspan, sticky="nsew", padx=5, pady=5)
179+
180+
window.mainloop()

0 commit comments

Comments
 (0)