import tkinter as tk from tkinter import messagebox import re from math import * # 创建主窗口 window = tk.Tk() # 设置窗口大小和位置 window.geometry('520x300+600+300') # 不允许改变窗口大小 window.resizable(False, False) # 设置窗口标题 window.title('计算器') # 背景颜色,例:window.config(background="BlueViolet") window.config(background="Blue") # 自动刷新字符串变量,可用 set 和 get 方法进行传值和取值 content_var = tk.StringVar(window, '') # 创建单行文本框 content_entry = tk.Entry(window, textvariable=content_var, bd=10) # 设置文本框为只读 content_entry['state'] = 'readonly' # 设置文本框坐标及宽高 content_entry.place(x=20, y=10, width=300, height=38) # 记录计算过程 record_text = tk.Text(window, wrap=tk.WORD, height=10) record_text.place(x=320, y=50, width=180, height=240) # 按钮显示内容 values = ['eˣ', 'π', '**', '%', '//', 'ln', '√', '⌫', '(', ')', '/', 'lg', 'x!', '7', '8', '9', '*', 'tan', 'x³', '4', '5', '6', '-', 'cos', 'x²', '1', '2', '3', '+', 'sin'] # 其余特殊按钮 value = ['+/-', 'C', '0', '.', '='] index_s = 0 index = 0 # 将按钮进行 5x6 放置 for row in range(5): for col in range(6): d = values[index_s] index_s += 1 if row == 1: if col == 1 or col == 2 or col == 3: btn_digit = tk.Button(window, text=d, font=("Helvetica", 14, "bold"), command=lambda x=d: onclick(x), bg="gray", fg="black") btn_digit.place(x=20 + col * 50, y=50 + row * 40, width=50, height=40) elif col == 0 or col == 4: btn_digit = tk.Button(window, text=d, font=("Helvetica", 14, "bold"), command=lambda x=d: onclick(x), bg="DeepSkyBlue", fg="purple") btn_digit.place(x=20 + col * 50, y=50 + row * 40, width=50, height=40) else: btn_digit = tk.Button(window, text=d, font=("Helvetica", 14, "bold"), command=lambda x=d: onclick(x), bg="orange", fg="blue") btn_digit.place(x=20 + col * 50, y=50 + row * 40, width=50, height=40) elif row == 2 or row == 3 or row == 4: if col == 1 or col == 2 or col == 3: btn_digit = tk.Button(window, text=d, font=("Helvetica", 14, "bold"), command=lambda x=d: onclick(x), bg="LightPink", fg="red") btn_digit.place(x=20 + col * 50, y=50 + row * 40, width=50, height=40) elif col == 0 or col == 4: btn_digit = tk.Button(window, text=d, font=("Helvetica", 14, "bold"), command=lambda x=d: onclick(x), bg="DeepSkyBlue", fg="purple") btn_digit.place(x=20 + col * 50, y=50 + row * 40, width=50, height=40) else: btn_digit = tk.Button(window, text=d, font=("Helvetica", 14, "bold"), command=lambda x=d: onclick(x), bg="orange", fg="blue") btn_digit.place(x=20 + col * 50, y=50 + row * 40, width=50, height=40) elif col == 5: btn_digit = tk.Button(window, text=d, font=("Helvetica", 14, "bold"), command=lambda x=d: onclick(x), bg="orange", fg="blue") btn_digit.place(x=20 + col * 50, y=50 + row * 40, width=50, height=40) else: btn_digit = tk.Button(window, text=d, font=("Helvetica", 14, "bold"), command=lambda x=d: onclick(x), bg="DeepSkyBlue", fg="purple") btn_digit.place(x=20 + col * 50, y=50 + row * 40, width=50, height=40) for leo in range(5): c = value[index] index += 1 if leo == 2: btn_digit = tk.Button(window, text=c, font=("Helvetica", 14, "bold"), command=lambda x=c: onclick(x), bg="LightPink", fg="red") btn_digit.place(x=20 + leo * 50, y=250, width=50, height=40) elif leo == 0: btn_digit = tk.Button(window, text=c, font=("Helvetica", 14, "bold"), command=lambda x=c: onclick(x), bg="SpringGreen", fg="red") btn_digit.place(x=20 + leo * 50, y=250, width=50, height=40) elif leo == 1: btn_digit = tk.Button(window, text=c, font=("Helvetica", 14, "bold"), command=lambda x=c: onclick(x), bg="yellow", fg="red") btn_digit.place(x=20 + leo * 50, y=250, width=50, height=40) elif leo == 3: btn_digit = tk.Button(window, text=c, font=("Helvetica", 14, "bold"), command=lambda x=c: onclick(x), bg="SkyBlue", fg="red") btn_digit.place(x=20 + leo * 50, y=250, width=50, height=40) else: btn_digit = tk.Button(window, text=c, font=("Helvetica", 14, "bold"), command=lambda x=c: onclick(x), bg="LightCoral", fg="black") btn_digit.place(x=220, y=250, width=100, height=40) lab_text_record = tk.Label(window, text='历史记录', font=("Helvetica", 14, "bold"), bg="white", fg="black") lab_text_record.place(x=320, y=10, width=180, height=40) # 添加清除历史记录按钮 btn_clear_record = tk.Button(window, text='清除记录', font=("Helvetica", 14, "bold"), command=lambda: record_text.delete(1.0, tk.END), bg="white", fg="black") btn_clear_record.place(x=320, y=250, width=180, height=40) # 点击事件 def onclick(key): # 运算符 operation = ('+', '-', '*', '/', '**', '//', '%') # 获取文本框中的内容 content = content_var.get() # 如果已有内容是以小数点开头的,在前面加 0 if content.startswith('.'): content = '0' + content # 字符串可以直接用+来增加字符 # 根据不同的按钮作出不同的反应 if key in '0123456789': # 按下 0-9 在 content 中追加 content += key elif key == '.': # 将 content 从 +-*/ 这些字符的地方分割开来 last_part = re.split(r'[+\-*/]', content)[-1] if '.' in last_part: # 信息提示对话框 tk.messagebox.showerror('错误', '数字只有一个小数点,所以不能再次点击!') return else: content += key elif key == 'C': # 清除文本框 content = '' elif key == '=': try: # 对输入的表达式求值 result = str(eval(content.replace("π", str(pi)).replace("rad", "radians"))) record_text.insert(tk.END, f"{content} = {result}\n") content = result except ZeroDivisionError: tk.messagebox.showerror('错误', '这个值太大了,以至于无法算出其值,0不能作为除数!') return except Exception as e: tk.messagebox.showerror('错误', f'无效表达式: {e}') return elif key in operation: if content.endswith(operation): tk.messagebox.showerror('错误', '运算符号之间不能直接连接,需要加入数值!') return content += key elif key == '+/-': # 将正负号切换 if content.startswith('-'): content = content[1:] else: content = '-' + content elif key in '()': # 直接在内容后面追加括号 content += key elif key == '√': # 从 . 处分割存入 n,n 是一个列表 n = content.split('.') # 如果列表中所有的都是数字,就是为了检查表达式是不是正确的 if all(map(lambda x: x.isdigit(), n)): content = sqrt(eval(content)) else: tk.messagebox.showerror('错误', '在实数范围内,负数不能算数平方根!') return elif key == 'eˣ': # 添加常数e的x次方,content = exp(eval(content)) content += 'e**' elif key == '⌫': # 删除最后一个字符 content = content[:-1] elif key == 'x²': # 计算平方 try: content = str(float(content) ** 2) except Exception as e: tk.messagebox.showerror('错误', f'无效表达式: {e}') return elif key == 'x³': # 计算立方 try: content = str(float(content) ** 3) except Exception as e: tk.messagebox.showerror('错误', f'无效表达式: {e}') return elif key == 'x!': # 计算阶乘 try: num = int(content) if num < 0: tk.messagebox.showerror('错误', '请输入一个非负整数进行阶乘运算!') return content = str(factorial(num)) except ValueError: tk.messagebox.showerror('错误', '请输入一个非负整数进行阶乘运算!') return except Exception as e: tk.messagebox.showerror('错误', f'无效的表达式: {e}') return elif key == 'π': # 添加常数π content += 'π' elif key == 'sin': # 计算sin值,content = sin(eval(content)) content += 'sin(' elif key == 'cos': # 计算cos值,content = cos(eval(content)) content += 'cos(' elif key == 'tan': # 计算tan值,content = tan(eval(content)) content += 'tan(' elif key == 'lg': # 计算常数对数lg的值,content = log10(eval(content)) content += 'log10(' elif key == 'ln': # 计算自然对数ln的值,content = log(eval(content)) content += 'log(' elif key == 'rad': # 当输入数字到三角函数运算时,默认为弧度制。 content = str(eval(content)) + ' rad' # 将结果显示到文本框中 content_var.set(content) # 运行主循环 window.mainloop() # 2 + 9 * ((3*12) - 8) // 10 = 27 # 3 * 4 ** 2 // 8 % 7 = 6 # 3 + 5 % 6 * 2 // 8 = 4