import tkinter as tk
from tkinter import ttk
import math
import re
class CalculatorGUI:
def __init__(self, root):
self.root = root
self.root.title("科学计算器")
self.root.geometry("400x550")
self.root.resizable(False, False)
self.root.configure(bg="#f0f0f0")
# 设置中文字体
self.font = ("SimHei", 12)
# 计算器逻辑
self.memory = 0
self.history = []
self.current_expression = ""
self.last_result = None
# 创建界面
self.create_widgets()
def create_widgets(self):
"""创建计算器界面"""
# 历史记录按钮
history_frame = tk.Frame(self.root, bg="#f0f0f0")
history_frame.pack(pady=5, fill=tk.X, padx=10)
history_button = tk.Button(history_frame, text="历史记录", font=self.font,
command=self.show_history, bg="#2196F3", fg="white")
history_button.pack(side=tk.RIGHT, padx=5)
# 显示屏
display_frame = tk.Frame(self.root, bg="#f0f0f0")
display_frame.pack(pady=10, fill=tk.X, padx=10)
self.expression_var = tk.StringVar()
self.expression_var.set("")
self.result_var = tk.StringVar()
self.result_var.set("0")
expression_label = tk.Label(display_frame, textvariable=self.expression_var,
font=("SimHei", 14), bg="white", anchor=tk.E, padx=10, pady=5)
expression_label.pack(fill=tk.X)
result_label = tk.Label(display_frame, textvariable=self.result_var,
font=("SimHei", 24, "bold"), bg="white", anchor=tk.E, padx=10, pady=5)
result_label.pack(fill=tk.X)
# 按钮框架
buttons_frame = tk.Frame(self.root, bg="#f0f0f0")
buttons_frame.pack(pady=10, fill=tk.BOTH, expand=True, padx=10)
# 按钮布局
buttons = [
['7', '8', '9', '/', 'C'],
['4', '5', '6', '*', 'CE'],
['1', '2', '3', '-', '√'],
['0', '.', '=', '+', '^'],
['(', ')', 'M+', 'M-', 'MR']
]
for i, row in enumerate(buttons):
for j, text in enumerate(row):
button = tk.Button(buttons_frame, text=text, font=self.font,
width=7, height=2, bg="#e0e0e0",
command=lambda txt=text: self.button_click(txt))
button.grid(row=i, column=j, padx=2, pady=2, sticky="nsew")
# 配置网格权重,使按钮均匀分布
for i in range(len(buttons)):
buttons_frame.grid_rowconfigure(i, weight=1)
for j in range(len(buttons[0])):
buttons_frame.grid_columnconfigure(j, weight=1)
def button_click(self, text):
"""处理按钮点击事件"""
if text == '=':
self.calculate()
elif text == 'C':
self.current_expression = ""
self.update_display()
elif text == 'CE':
# 删除最后一个字符
self.current_expression = self.current_expression[:-1]
self.update_display()
elif text == '√':
self.current_expression += "sqrt("
self.update_display()
elif text == '^':
self.current_expression += "**"
self.update_display()
elif text == 'M+':
self.current_expression += f"+{self.memory}"
self.update_display()
elif text == 'M-':
self.current_expression += f"-{self.memory}"
self.update_display()
elif text == 'MR':
self.current_expression += str(self.memory)
self.update_display()
else:
self.current_expression += text
self.update_display()
def update_display(self):
"""更新显示屏"""
self.expression_var.set(self.current_expression)
# 如果表达式为空,显示0
if not self.current_expression:
self.result_var.set("0")
def calculate(self):
"""计算表达式结果"""
if not self.current_expression:
return
expression = self.current_expression
# 替换函数调用
pattern = r'sqrt\(([^)]+)\)'
while re.search(pattern, expression):
match = re.search(pattern, expression)
arg = match.group(1)
expression = expression.replace(match.group(0), f"math.sqrt({arg})")
# 替换幂运算
expression = expression.replace('^', '**')
try:
# 计算表达式
result = eval(expression)
# 更新历史记录
self.history.append(f"{self.current_expression} = {result}")
# 更新显示
self.result_var.set(str(result))
self.last_result = result
# 如果用户想继续计算,使用结果作为新表达式的开始
self.current_expression = str(result)
except ZeroDivisionError:
self.result_var.set("错误: 除数不能为零")
except Exception as e:
self.result_var.set(f"错误: {str(e)}")
def show_history(self):
"""显示历史记录"""
if not self.history:
tk.messagebox.showinfo("历史记录", "暂无计算历史")
return
# 创建历史记录窗口
history_window = tk.Toplevel(self.root)
history_window.title("计算历史")
history_window.geometry("400x300")
history_window.resizable(False, False)
history_window.configure(bg="#f0f0f0")
history_window.transient(self.root) # 使窗口成为主窗口的子窗口
# 创建历史记录列表
history_text = tk.Text(history_window, font=self.font, bg="white", wrap=tk.WORD)
history_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# 插入历史记录
for i, entry in enumerate(self.history, 1):
history_text.insert(tk.END, f"{i}. {entry}\n\n")
# 使文本框只读
history_text.config(state=tk.DISABLED)
# 关闭按钮
close_button = tk.Button(history_window, text="关闭", font=self.font,
command=history_window.destroy, bg="#f44336", fg="white")
close_button.pack(pady=10)
# 启动计算器
if __name__ == "__main__":
root = tk.Tk()
app = CalculatorGUI(root)
root.mainloop()