You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
7.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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="blue")
# 自动刷新字符串变量,可用 set 和 get 方法进行传值和取值
content_var = tk.StringVar(window, '')
# 创建单行文本框
content_entry = tk.Entry(window, textvariable=content_var)
# 设置文本框为只读
content_entry['state'] = 'readonly'
# 设置文本框坐标及宽高
content_entry.place(x=20, y=10, width=300, height=30)
record_text = tk.Text(window, wrap=tk.WORD, height=10)
record_text.place(x=320, y=50, width=180, height=240)
# 按钮显示内容
value = ['e^x','', 'π', '%', '//','ln',
'**','', '(', ')', '/','lg',
'x!','7', '8', '9', '*','tan',
'','4', '5', '6', '-','cos',
'','1', '2', '3', '+','sin',]
value0 = ['+/-','C', '0', '.', '=',]
index = 0
index0 = 0
# 将按钮进行 5x6 放置
for row in range(5):
for col in range(6):
d = value[index]
index += 1
if (row==1 and (col==1 or col==2 or col==3)):
btn_digit = tk.Button(window, text=d, 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 (row==2 and (col==1 or col==2 or col==3)):
btn_digit = tk.Button(window, text=d, 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 (row==3 and (col==1 or col==2 or col==3)):
btn_digit = tk.Button(window, text=d, 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 (row==4 and (col==1 or col==2 or col==3)):
btn_digit = tk.Button(window, text=d, 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)
else:
btn_digit = tk.Button(window, text=d, 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 l in range(5):
c = value0[index0]
index0 += 1
if (l == 2):
btn_digit = tk.Button(window, text=c, command=lambda x=c: onclick(x), bg="LightPink", fg="red")
btn_digit.place(x=20 + l * 50, y=250, width=50, height=40)
elif (l == 0):
btn_digit = tk.Button(window, text=c, command=lambda x=c: onclick(x), bg="SpringGreen", fg="red")
btn_digit.place(x=20 + l * 50, y=250, width=50, height=40)
elif (l == 1):
btn_digit = tk.Button(window, text=c, command=lambda x=c: onclick(x), bg="yellow", fg="red")
btn_digit.place(x=20 + l * 50, y=250, width=50, height=40)
elif (l == 3):
btn_digit = tk.Button(window, text=c, command=lambda x=c: onclick(x), bg="SkyBlue", fg="red")
btn_digit.place(x=20 + l * 50, y=250, width=50, height=40)
else:
btn_digit = tk.Button(window, text=c, 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='清除记录', 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 == '':
# 从 . 处分割存入 nn 是一个列表
n = content.split('.')
# 如果列表中所有的都是数字,就是为了检查表达式是不是正确的
if all(map(lambda x: x.isdigit(), n)):
content = sqrt(eval(content))
else:
tk.messagebox.showerror('错误', '在实数范围内,负数不能算数平方根!')
return
elif key == 'e^x':
# 添加常数e的x次方
content = exp(eval(content))
elif key == '':
# 删除最后一个字符
content = content[:-1]
elif key == '':
# 计算平方
try:
content = str(float(content) ** 2)
except Exception as e:
tk.messagebox.showerror('错误', f'无效表达式: {e}')
return
elif key == '':
# 计算立方
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':
content = sin(eval(content))
elif key == 'cos':
content = cos(eval(content))
elif key == 'tan':
content = tan(eval(content))
elif key == 'lg':
content = log10(eval(content))
elif key == 'ln':
content = log(eval(content))
elif key == 'rad':
content = str(eval(content)) + ' rad'
# 将结果显示到文本框中
content_var.set(content)
# 运行主循环
window.mainloop()
# 2 + 9 * ((3*12) - 8) // 10 =