Python实现Windows系统计算器程序(含高级功能)
下面我将介绍如何使用Python创建一个功能完整的Windows风格计算器程序,包含基本运算和高级数学功能。
1. 使用Tkinter实现基础计算器
import tkinter as tk
from tkinter import ttk
import math
class Calculator:
def __init__(self, root):
self.root = root
self.root.title("高级计算器")
self.root.geometry("400x550")
self.root.resizable(False, False)
# 当前输入和结果
self.current_input = ""
self.previous_input = ""
self.operation = None
self.reset_input = False
# 创建界面
self.create_widgets()
def create_widgets(self):
# 显示框
self.display_frame = ttk.Frame(self.root)
self.display_frame.pack(fill=tk.BOTH, padx=10, pady=10)
self.expression_var = tk.StringVar()
self.expression_label = ttk.Label(
self.display_frame,
textvariable=self.expression_var,
font=("Arial", 18),
anchor=tk.E
)
self.expression_label.pack(fill=tk.BOTH, expand=True)
self.result_var = tk.StringVar()
self.result_label = ttk.Label(
self.display_frame,
textvariable=self.result_var,
font=("Arial", 28, "bold"),
anchor=tk.E,
foreground="blue"
)
self.result_label.pack(fill=tk.BOTH, expand=True)
# 按钮框架
self.buttons_frame = ttk.Frame(self.root)
self.buttons_frame.pack(fill=tk.BOTH, expand=True)
# 按钮布局
buttons = [
("C", 0, 0, "#FF9500", self.clear_all),
("⌫", 0, 1, "#FF9500", self.delete_last),
("÷", 0, 2, "#FF9500", lambda: self.add_operation("/")),
("×", 0, 3, "#FF9500", lambda: self.add_operation("*")),
("7", 1, 0, "#333333", lambda: self.add_number("7")),
("8", 1, 1, "#333333", lambda: self.add_number("8")),
("9", 1, 2, "#333333", lambda: self.add_number("9")),
("-", 1, 3, "#FF9500", lambda: self.add_operation("-")),
("4", 2, 0, "#333333", lambda: self.add_number("4")),
("5", 2, 1, "#333333", lambda: self.add_number("5")),
("6", 2, 2, "#333333", lambda: self.add_number("6")),
("+", 2, 3, "#FF9500", lambda: self.add_operation("+")),
("1", 3, 0, "#333333", lambda: self.add_number("1")),
("2", 3, 1, "#333333", lambda: self.add_number("2")),
("3", 3, 2, "#333333", lambda: self.add_number("3")),
("=", 3, 3, "#4CD964", self.calculate),
("0", 4, 0, "#333333", lambda: self.add_number("0")),
(".", 4, 1, "#333333", lambda: self.add_number(".")),
("(", 4, 2, "#333333", lambda: self.add_number("(")),
(")", 4, 3, "#333333", lambda: self.add_number(")")),
# 高级功能按钮
("sin", 5, 0, "#5856D6", lambda: self.add_function("math.sin(")),
("cos", 5, 1, "#5856D6", lambda: self.add_function("math.cos(")),
("tan", 5, 2, "#5856D6", lambda: self.add_function("math.tan(")),
("log", 5, 3, "#5856D6", lambda: self.add_function("math.log10(")),
("√", 6, 0, "#5856D6", lambda: self.add_function("math.sqrt(")),
("x²", 6, 1, "#5856D6", lambda: self.add_operation("**2")),
("x³", 6, 2, "#5856D6", lambda: self.add_operation("**3")),
("π", 6, 3, "#5856D6", lambda: self.add_number(str(math.pi))),
("e", 7, 0, "#5856D6", lambda: self.add_number(str(math.e))),
("x^y", 7, 1, "#5856D6", lambda: self.add_operation("**")),
("(", 7, 2, "#333333", lambda: self.add_number("(")),
(")", 7, 3, "#333333", lambda: self.add_number(")")),
("Ans", 8, 0, "#5856D6", lambda: self.add_number(str(self.previous_result))),
("1/x", 8, 1, "#5856D6", lambda: self.add_function("1/(" + self.current_input + ")")),
("n!", 8, 2, "#5856D6", lambda: self.add_function("math.factorial(int(" + self.current_input + "))" if self.current_input.isdigit() else "")),
("(", 8, 3, "#333333", lambda: self.add_number("(")),
]
# 创建按钮
for (text, row, col, color, command) in buttons:
button = ttk.Button(
self.buttons_frame,
text=text,
command=command
)
if text.isdigit() or text in [".", "+", "-", "*", "/", "(", ")", "^"]:
button.configure(style="Number.TButton")
elif text in ["sin", "cos", "tan", "log", "√", "x²", "x³", "Ans", "1/x", "n!"]:
button.configure(style="Function.TButton")
else:
button.configure(style="Operator.TButton")
button.grid(row=row, column=col, sticky="nsew", padx=5, pady=5)
# 配置网格权重
self.buttons_frame.grid_rowconfigure(row, weight=1)
self.buttons_frame.grid_columnconfigure(col, weight=1)
# 设置按钮样式
style = ttk.Style()
style.configure("TButton", font=("Arial", 14))
style.map("TButton",
foreground=[('pressed', 'white'), ('active', '#007AFF')],
background=[('pressed', '#007AFF'), ('active', '#007AFF')],
relief=[('pressed', 'flat'), ('active', 'flat')])
style.configure("Number.TButton", background="#F2F2F7")
style.configure("Operator.TButton", background="#FF9500", foreground="white")
style.configure("Function.TButton", background="#5856D6", foreground="white")
# 计算结果变量
self.previous_result = 0
def add_number(self, number):
if self.reset_input:
self.current_input = ""
self.reset_input = False
if number == "." and "." in self.current_input:
return
self.current_input += number
self.expression_var.set(self.current_input)
def add_operation(self, operation):
if self.current_input == "" and self.previous_input == "":
return
if self.previous_input:
self.calculate()
self.operation = operation
else:
self.operation = operation
self.previous_input = self.current_input
self.current_input = ""
self.expression_var.set(self.previous_input + " " + operation)
def add_function(self, function):
if self.reset_input:
self.current_input = ""
self.reset_input = False
# 检查是否需要添加括号
if not (self.current_input.endswith(")") or self.current_input == ""):
self.current_input += ")"
self.current_input += function
if not self.current_input.endswith(")"):
self.current_input += "("
self.expression_var.set(self.current_input)
def clear_all(self):
self.current_input = ""
self.previous_input = ""
self.operation = None
self.reset_input = False
self.expression_var.set("")
self.result_var.set("")
def delete_last(self):
if self.current_input:
self.current_input = self.current_input[:-1]
self.expression_var.set(self.current_input if self.current_input else "")
elif self.previous_input:
self.previous_input = self.previous_input[:-1]
self.expression_var.set(self.previous_input if self.previous_input else "")
def calculate(self):
try:
# 替换x为*用于计算
expression = self.current_input.replace("^", "**")
# 处理特殊函数
if "sin(" in expression:
expression = expression.replace("sin(", "math.sin(")
if "cos(" in expression:
expression = expression.replace("cos(", "math.cos(")
if "tan(" in expression:
expression = expression.replace("tan(", "math.tan(")
if "log(" in expression:
expression = expression.replace("log(", "math.log10(")
if "√(" in expression:
expression = expression.replace("√(", "math.sqrt(")
result = eval(expression, {"math": math})
self.previous_input = str(result)
self.current_input = str(result)
self.expression_var.set(str(result))
self.result_var.set("=" + str(result))
self.previous_result = result
self.reset_input = True
except Exception as e:
self.expression_var.set("错误")
self.result_var.set("")
self.current_input = ""
self.previous_input = ""
self.reset_input = False
@property
def current_input(self):
return self._current_input
@current_input.setter
def current_input(self, value):
self._current_input = value
# 创建主窗口并运行计算器
if __name__ == "__main__":
import math
root = tk.Tk()
calculator = Calculator(root)
# 添加自定义样式
style = ttk.Style()
style.theme_use('clam')
root.mainloop()
2. 高级功能实现
2.1 科学计算功能
上述代码已经实现了以下高级功能:
- 三角函数:sin, cos, tan
- 对数函数:log10
- 平方根:√
- 幂运算:x², x³, x^y
- 常数:π, e
- 阶乘:n!
- 反函数:1/x
2.2 历史记录功能(扩展)
要添加历史记录功能,可以修改代码如下:
class Calculator:
def __init__(self, root):
# ... 其他初始化代码 ...
self.history = [] # 存储计算历史
def calculate(self):
try:
# ... 计算代码 ...
# 添加到历史记录
if self.previous_input and self.operation and self.current_input:
expression = f"{self.previous_input} {self.operation} {self.current_input}"
self.history.append((expression, str(result)))
if len(self.history) > 10: # 限制历史记录数量
self.history.pop(0)
# ... 其他代码 ...
except Exception as e:
# ... 错误处理代码 ...
def show_history(self):
# 创建新窗口显示历史记录
history_window = tk.Toplevel(self.root)
history_window.title("计算历史")
history_window.geometry("350x400")
history_text = tk.Text(history_window, font=("Arial", 12))
history_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
for expr, res in self.history:
history_text.insert(tk.END, f"{expr} = {res}\n")
history_text.config(state=tk.DISABLED)
2.3 图形绘制功能(扩展)
要添加函数图形绘制功能,可以使用matplotlib:
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class Calculator:
# ... 其他代码 ...
def plot_function(self):
function_window = tk.Toplevel(self.root)
function_window.title("函数绘图")
function_window.geometry("600x500")
# 创建输入框
input_frame = ttk.Frame(function_window)
input_frame.pack(fill=tk.X, padx=10, pady=10)
ttk.Label(input_frame, text="输入函数 (使用x作为变量):").pack(side=tk.LEFT)
function_entry = ttk.Entry(input_frame, width=30)
function_entry.pack(side=tk.LEFT, padx=5)
function_entry.insert(0, "math.sin(x)") # 默认函数
# 创建绘图区域
fig_frame = ttk.Frame(function_window)
fig_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
fig, ax = plt.subplots(figsize=(6, 5))
canvas = FigureCanvasTkAgg(fig, master=fig_frame)
canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
# 绘制按钮
def draw_plot():
try:
func_str = function_entry.get()
x = np.linspace(-10, 10, 400)
y = eval(func_str, {"math": math, "x": x, "np": np})
ax.clear()
ax.plot(x, y)
ax.set_title(f"y = {func_str}")
ax.grid(True)
canvas.draw()
except Exception as e:
messagebox.showerror("错误", f"无法绘制函数: {str(e)}")
ttk.Button(function_window, text="绘制", command=draw_plot).pack(pady=5)
3. 完整功能整合
将上述功能整合到一个完整的计算器程序中:
import tkinter as tk
from tkinter import ttk, messagebox
import math
import numpy as np
class AdvancedCalculator:
def __init__(self, root):
self.root = root
self.root.title("高级科学计算器")
self.root.geometry("500x650")
self.root.resizable(False, False)
self.current_input = ""
self.previous_input = ""
self.operation = None
self.reset_input = False
self.history = []
self.create_widgets()
def create_widgets(self):
# 显示框
self.display_frame = ttk.Frame(self.root)
self.display_frame.pack(fill=tk.BOTH, padx=10, pady=10)
self.expression_var = tk.StringVar()
self.expression_label = ttk.Label(
self.display_frame,
textvariable=self.expression_var,
font=("Arial", 14),
anchor=tk.E
)
self.expression_label.pack(fill=tk.BOTH, expand=True)
self.result_var = tk.StringVar()
self.result_label = ttk.Label(
self.display_frame,
textvariable=self.result_var,
font=("Arial", 24, "bold"),
anchor=tk.E,
foreground="blue"
)
self.result_label.pack(fill=tk.BOTH, expand=True)
# 按钮框架
self.buttons_frame = ttk.Frame(self.root)
self.buttons_frame.pack(fill=tk.BOTH, expand=True)
# 按钮布局
buttons = [
# 第一行
("C", 0, 0, "#FF9500", self.clear_all),
("⌫", 0, 1, "#FF9500", self.delete_last),
("÷", 0, 2, "#FF9500", lambda: self.add_operation("/")),
("×", 0, 3, "#FF9500", lambda: self.add_operation("*")),
# 第二行
("7", 1, 0, "#333333", lambda: self.add_number("7")),
("8", 1, 1, "#333333", lambda: self.add_number("8")),
("9", 1, 2, "#333333", lambda: self.add_number("9")),
("-", 1, 3, "#FF9500", lambda: self.add_operation("-")),
# 第三行
("4", 2, 0, "#333333", lambda: self.add_number("4")),
("5", 2, 1, "#333333", lambda: self.add_number("5")),
("6", 2, 2, "#333333", lambda: self.add_number("6")),
("+", 2, 3, "#FF9500", lambda: self.add_operation("+")),
# 第四行
("1", 3, 0, "#333333", lambda: self.add_number("1")),
("2", 3, 1, "#333333", lambda: self.add_number("2")),
("3", 3, 2, "#333333", lambda: self.add_number("3")),
("=", 3, 3, "#4CD964", self.calculate),
# 第五行
("0", 4, 0, "#333333", lambda: self.add_number("0")),
(".", 4, 1, "#333333", lambda: self.add_number(".")),
("(", 4, 2, "#333333", lambda: self.add_number("(")),
(")", 4, 3, "#333333", lambda: self.add_number(")")),
# 第六行 - 高级功能
("sin", 5, 0, "#5856D6", lambda: self.add_function("math.sin(")),
("cos", 5, 1, "#5856D6", lambda: self.add_function("math.cos(")),
("tan", 5, 2, "#5856D6", lambda: self.add_function("math.tan(")),
("log", 5, 3, "#5856D6", lambda: self.add_function("math.log10(")),
# 第七行
("√", 6, 0, "#5856D6", lambda: self.add_function("math.sqrt(")),
("x²", 6, 1, "#5856D6", lambda: self.add_operation("**2")),
("x³", 6, 2, "#5856D6", lambda: self.add_operation("**3")),
("π", 6, 3, "#5856D6", lambda: self.add_number(str(math.pi))),
# 第八行
("e", 7, 0, "#5856D6", lambda: self.add_number(str(math.e))),
("x^y", 7, 1, "#5856D6", lambda: self.add_operation("**")),
("(", 7, 2, "#333333", lambda: self.add_number("(")),
(")", 7, 3, "#333333", lambda: self.add_number(")")),
# 第九行
("Ans", 8, 0, "#5856D6", lambda: self.add_number(str(self.previous_result))),
("1/x", 8, 1, "#5856D6", lambda: self.add_function("1/(" + self.current_input + ")")),
("n!", 8, 2, "#5856D6", lambda: self.add_function("math.factorial(int(" + self.current_input + "))" if self.current_input.isdigit() else "")),
("Hist", 8, 3, "#5856D6", self.show_history),
]
# 创建按钮
for (text, row, col, color, command) in buttons:
button = ttk.Button(
self.buttons_frame,
text=text,
command=command
)
if text.isdigit() or text in [".", "+", "-", "*", "/", "(", ")", "^"]:
button.configure(style="Number.TButton")
elif text in ["sin", "cos", "tan", "log", "√", "x²", "x³", "Ans", "1/x", "n!"]:
button.configure(style="Function.TButton")
elif text in ["Hist"]:
button.configure(style="History.TButton")
else:
button.configure(style="Operator.TButton")
button.grid(row=row, column=col, sticky="nsew", padx=5, pady=5)
# 配置网格权重
self.buttons_frame.grid_rowconfigure(row, weight=1)
self.buttons_frame.grid_columnconfigure(col, weight=1)
# 设置按钮样式
style = ttk.Style()
style.configure("TButton", font=("Arial", 14))
style.map("TButton",
foreground=[('pressed', 'white'), ('active', '#007AFF')],
background=[('pressed', '#007AFF'), ('active', '#007AFF')],
relief=[('pressed', 'flat'), ('active', 'flat')])
style.configure("Number.TButton", background="#F2F2F7")
style.configure("Operator.TButton", background="#FF9500", foreground="white")
style.configure("Function.TButton", background="#5856D6", foreground="white")
style.configure("History.TButton", background="#8E8E93", foreground="white")
# 计算结果变量
self.previous_result = 0
def add_number(self, number):
if self.reset_input:
self.current_input = ""
self.reset_input = False
if number == "." and "." in self.current_input:
return
self.current_input += number
self.expression_var.set(self.current_input)
def add_operation(self, operation):
if self.current_input == "" and self.previous_input == "":
return
if self.previous_input:
self.calculate()
self.operation = operation
else:
self.operation = operation
self.previous_input = self.current_input
self.current_input = ""
self.expression_var.set(self.previous_input + " " + operation)
def add_function(self, function):
if self.reset_input:
self.current_input = ""
self.reset_input = False
# 检查是否需要添加括号
if not (self.current_input.endswith(")") or self.current_input == ""):
self.current_input += ")"
self.current_input += function
if not self.current_input.endswith(")"):
self.current_input += "("
self.expression_var.set(self.current_input)
def clear_all(self):
self.current_input = ""
self.previous_input = ""
self.operation = None
self.reset_input = False
self.expression_var.set("")
self.result_var.set("")
def delete_last(self):
if self.current_input:
self.current_input = self.current_input[:-1]
self.expression_var.set(self.current_input if self.current_input else "")
elif self.previous_input:
self.previous_input = self.previous_input[:-1]
self.expression_var.set(self.previous_input if self.previous_input else "")
def calculate(self):
try:
# 替换x为*用于计算
expression = self.current_input.replace("^", "**")
# 处理特殊函数
if "sin(" in expression:
expression = expression.replace("sin(", "math.sin(")
if "cos(" in expression:
expression = expression.replace("cos(", "math.cos(")
if "tan(" in expression:
expression = expression.replace("tan(", "math.tan(")
if "log(" in expression:
expression = expression.replace("log(", "math.log10(")
if "√(" in expression:
expression = expression.replace("√(", "math.sqrt(")
result = eval(expression, {"math": math})
self.previous_input = str(result)
self.current_input = str(result)
self.expression_var.set(str(result))
self.result_var.set("=" + str(result))
self.previous_result = result
self.reset_input = True
# 添加到历史记录
if self.previous_input and self.operation and self.current_input:
expr = f"{self.previous_input} {self.operation} {self.current_input}"
self.history.append((expr, str(result)))
if len(self.history) > 10: # 限制历史记录数量
self.history.pop(0)
except Exception as e:
self.expression_var.set("错误")
self.result_var.set("")
self.current_input = ""
self.previous_input = ""
self.reset_input = False
@property
def current_input(self):
return self._current_input
@current_input.setter
def current_input(self, value):
self._current_input = value
def show_history(self):
history_window = tk.Toplevel(self.root)
history_window.title("计算历史")
history_window.geometry("400x400")
history_text = tk.Text(history_window, font=("Arial", 12))
history_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
for expr, res in self.history:
history_text.insert(tk.END, f"{expr} = {res}\n")
history_text.config(state=tk.DISABLED)
# 创建主窗口并运行计算器
if __name__ == "__main__":
import math
root = tk.Tk()
# 添加自定义样式
style = ttk.Style()
style.theme_use('clam')
calculator = AdvancedCalculator(root)
root.mainloop()
4. 功能说明
4.1 基本功能
- 支持加、减、乘、除基本运算
- 支持括号和小数点
- 清除(C)和删除(⌫)功能
4.2 高级科学计算功能
- 三角函数:sin, cos, tan
- 对数函数:log10
- 平方根:√
- 幂运算:x², x³, x^y
- 常数:π, e
- 阶乘:n!
- 反函数:1/x
4.3 额外功能
- 历史记录:记录最近10次计算
- Ans功能:使用上一次的计算结果
5. 扩展建议
- 图形绘制功能:添加函数绘图功能,可以使用matplotlib集成
- 单位转换:添加长度、重量、温度等单位转换功能
- 方程求解:添加一元二次方程等求解功能
- 统计计算:添加平均值、标准差等统计功能
- 编程模式:添加自定义函数定义功能
这个计算器程序提供了完整的科学计算功能,界面简洁直观,适合学习和日常使用。