大毛科学计算器 (Scientific Calculator)
作者: 大毛技术网
版本: 1.0.0
日期: 2024-12-17
描述: 一个具有基础计算和科学计算功能的计算器
版权所有 © 2024 大毛技术网. 保留所有权利。
效果
代码
import tkinter as tk
from tkinter import messagebox
import math
class JiSuanQi:
def __init__(self):
self.chuangkou = tk.Tk()
self.chuangkou.title('大毛科学计算器')
self.chuangkou.geometry('320x480')
self.chuangkou.configure(bg='#f0f0f0')
self.chuangkou.resizable(False, False)
# 设置窗口圆角和阴影效果
try:
from ctypes import windll, byref, sizeof, c_int
windll.dwmapi.DwmSetWindowAttribute(
windll.user32.GetParent(self.chuangkou.winfo_id()),
20,
byref(c_int(1)),
sizeof(c_int)
)
except:
pass
# 添加模式标记
self.shi_gaoji = False
# 添加当前表达式变量
self.dangqian = ''
# 创建切换按钮
self.qiehuan_anniu = tk.Button(
self.chuangkou,
text='科学模式',
font=('Arial', 10),
bg='#4a90e2',
fg='white',
relief='flat',
bd=0,
command=self.qiehuan_moshi
)
# 设置底部作者
self.zuozhe_biaoqian = tk.Label(
self.chuangkou,
text='By 大毛技术网 © 2024',
font=('Arial', 10, 'bold'),
fg='#4a90e2',
bg='#f0f0f0'
)
self.zuozhe_biaoqian.grid(row=7, column=0, columnspan=4, pady=(2, 5))
# 创建界面
self.chuangjian_xianshi()
self.chuangjian_jiben_anniu()
# 放置切换按钮
self.qiehuan_anniu.grid(row=6, column=0, columnspan=4,
padx=4, pady=4, sticky='nsew')
def chuangjian_xianshi(self):
# 修改显示框样式
self.jieguo_var = tk.StringVar()
self.jieguo_var.set('0')
self.xianshi = tk.Entry(
self.chuangkou,
textvariable=self.jieguo_var,
justify='right',
font=('Arial', 32, 'bold'),
bd=0,
bg='#ffffff',
fg='#2c3e50',
relief='flat',
state='readonly'
)
self.xianshi.grid(row=0, column=0, columnspan=4,
padx=15, pady=25,
sticky='nsew',
ipady=20)
def chuangjian_jiben_anniu(self):
# 基本按钮文本
self.basic_texts = [
'C', '←', '%', '÷',
'7', '8', '9', 'x',
'4', '5', '6', '-',
'1', '2', '3', '+',
'±', '0', '.', '='
]
self.create_buttons(self.basic_texts)
def chuangjian_gaoji_anniu(self):
# 科学计算的按钮文本
self.advanced_texts = [
'C', '←', '(', ')',
'sin', 'cos', 'tan', '÷',
'π', 'e', 'x²', 'x',
'√', 'log', 'ln', '-',
'7', '8', '9', '+',
'4', '5', '6', '-',
'1', '2', '3', '=',
'±', '0', '.', '^'
]
self.create_buttons(self.advanced_texts, advanced=True)
def create_buttons(self, texts, advanced=False):
# 清除现有按钮和框架
for widget in self.chuangkou.grid_slaves():
if isinstance(widget, (tk.Button, tk.Frame)) and widget != self.xianshi:
widget.grid_forget()
# 布局逻辑
rows = 8 if advanced else 5
buttons_per_row = 4
# 重置所有行和列的权重
for i in range(12): # 使用足够大的数字覆盖所有可能的行
self.chuangkou.grid_rowconfigure(i, weight=0)
for i in range(4):
self.chuangkou.grid_columnconfigure(i, weight=1)
# 设置显示器所在行的权重
self.chuangkou.grid_rowconfigure(0, weight=1)
for i, text in enumerate(texts):
row = (i // buttons_per_row) + 1
col = i % buttons_per_row
# 更新按钮颜色方案
if text in ['÷', 'x', '-', '+', '=', '^']:
bg_color = '#ff9500' # 橙子色运算符
hover_color = '#ffaa33' # 悬停时的颜色
fg_color = 'white'
elif text in ['C', '←', '%', '±', 'sin', 'cos', 'tan', 'π', 'e', '√', 'log', 'ln', '(', ')', 'x²']:
bg_color = '#a5a5a5' # 灰色功能键
hover_color = '#b8b8b8' # 悬停时的颜色
fg_color = 'white' # 改为白色文字
else:
bg_color = '#e8e8e8' # 更亮的数字键背景
hover_color = '#f0f0f0' # 悬停时的颜色
fg_color = '#2c3e50' # 深色文字
# 创建外层框架用于实现缩放效果
outer_frame = tk.Frame(self.chuangkou, bg='#f0f0f0')
outer_frame.grid(row=row, column=col, padx=4, pady=4, sticky='nsew')
outer_frame.grid_columnconfigure(0, weight=1)
outer_frame.grid_rowconfigure(0, weight=1)
# 创建内框架用于放置按钮
inner_frame = tk.Frame(outer_frame, bg=bg_color)
inner_frame.grid(row=0, column=0, sticky='nsew')
# 配置内框架的网格权重,使按钮居中
inner_frame.grid_columnconfigure(0, weight=1)
inner_frame.grid_rowconfigure(0, weight=1)
button = tk.Button(inner_frame,
text=text,
font=('Arial', 14, 'bold'),
bg=bg_color,
fg=fg_color,
relief='flat',
bd=0,
activebackground=hover_color,
activeforeground=fg_color,
cursor='hand2',
anchor='center', # 设置文本居中
width=1, # 最小宽度,让按钮自适应大小
padx=10,
pady=8,
command=lambda t=text: self.button_click(t))
# 使用grid布局使按钮填充并居中
button.grid(row=0, column=0, sticky='nsew')
# 修改悬停和点击效果
def on_enter(e, btn=button, frame=inner_frame, h_color=hover_color):
btn.configure(bg=h_color)
frame.configure(bg=h_color)
# 使用place_configure来实现平滑的缩放效果
frame.place(relx=0.02, rely=0.02, relwidth=0.96, relheight=0.96)
def on_leave(e, btn=button, frame=inner_frame, b_color=bg_color):
btn.configure(bg=b_color)
frame.configure(bg=b_color)
frame.place_forget()
frame.grid(row=0, column=0, sticky='nsew')
def on_press(e, btn=button, frame=inner_frame, h_color=hover_color):
btn.configure(bg=h_color)
frame.configure(bg=h_color)
frame.place(relx=0.04, rely=0.04, relwidth=0.92, relheight=0.92)
def on_release(e, btn=button, frame=inner_frame, b_color=bg_color):
btn.configure(bg=b_color)
frame.configure(bg=b_color)
frame.place_forget()
frame.grid(row=0, column=0, sticky='nsew')
button.bind('<Enter>', on_enter)
button.bind('<Leave>', on_leave)
button.bind('<Button-1>', on_press)
button.bind('<ButtonRelease-1>', on_release)
# 调整切换按钮位置
if advanced:
self.qiehuan_anniu.grid(row=9, column=0, columnspan=4,
padx=4, pady=4, sticky='nsew')
self.zuozhe_biaoqian.grid(row=10, column=0, columnspan=4, pady=(0, 5))
else:
self.qiehuan_anniu.grid(row=6, column=0, columnspan=4,
padx=4, pady=4, sticky='nsew')
self.zuozhe_biaoqian.grid(row=7, column=0, columnspan=4, pady=(0, 5))
# 按钮太丑必须进行美化一下
self.qiehuan_anniu.configure(
bg='#4a90e2',
fg='white',
font=('Arial', 12, 'bold'),
relief='flat',
bd=0,
padx=15,
pady=10,
activebackground='#5c9ee6',
activeforeground='white'
)
def qiehuan_moshi(self):
self.shi_gaoji = not self.shi_gaoji
if self.shi_gaoji:
self.chuangkou.geometry('320x640')
# 清除所有按钮和框架
for widget in self.chuangkou.grid_slaves():
if isinstance(widget, (tk.Button, tk.Frame)) and widget != self.xianshi:
widget.grid_forget()
self.chuangjian_gaoji_anniu()
self.qiehuan_anniu.configure(text='基础模式')
else:
self.chuangkou.geometry('320x480')
# 清除所有按钮和框架
for widget in self.chuangkou.grid_slaves():
if isinstance(widget, (tk.Button, tk.Frame)) and widget != self.xianshi:
widget.grid_forget()
self.chuangjian_jiben_anniu()
self.qiehuan_anniu.configure(text='科学模式')
def button_click(self, text):
# 定义运算符列表
operators = ['÷', 'x', '-', '+', '^', '%']
# 检查是否是运算符
if text in operators:
# 如果当前表达式为空,且不是减号(因为考虑负数的情况),则不添加运算符
if not self.dangqian and text != '-':
return
# 如果最后一个字符是运算符,则不允许再添加运算符
if self.dangqian and self.dangqian[-1] in operators:
return
if text == 'x':
self.dangqian += 'x'
elif text == '÷':
self.dangqian += '÷'
elif text == 'C':
self.dangqian = ''
self.jieguo_var.set('0')
elif text == '←':
self.dangqian = self.dangqian[:-1]
self.jieguo_var.set(self.dangqian if self.dangqian else '0')
elif text == '=':
# 如果最后一个字符是运算符,则不进行计算
if self.dangqian and self.dangqian[-1] in operators:
messagebox.showerror('错误', '别闹,没这样的运算')
return
try:
# 科学计算器的特殊函数
expr = self.dangqian
expr = expr.replace('x', '*').replace('÷', '/')
expr = expr.replace('π', str(math.pi))
expr = expr.replace('e', str(math.e))
expr = expr.replace('sin', 'math.sin')
expr = expr.replace('cos', 'math.cos')
expr = expr.replace('tan', 'math.tan')
expr = expr.replace('log', 'math.log10')
expr = expr.replace('ln', 'math.log')
expr = expr.replace('√', 'math.sqrt')
expr = expr.replace('^', '**')
# 处理阶乘
if '!' in expr:
num = float(expr.replace('!', ''))
if num.is_integer() and num >= 0:
result = math.factorial(int(num))
else:
raise ValueError("别闹,没这样的运算")
else:
result = eval(expr)
# 格式化结果
if isinstance(result, float):
result = '{:.3f}'.format(result).rstrip('0').rstrip('.')
self.jieguo_var.set(result)
self.dangqian = str(result)
except Exception as e:
messagebox.showerror('错误', '别闹,没这样的运算')
self.dangqian = ''
self.jieguo_var.set('0')
elif text == 'x²':
try:
if self.dangqian:
num = eval(self.dangqian)
result = num * num
if isinstance(result, float):
result = '{:.3f}'.format(result).rstrip('0').rstrip('.')
self.dangqian = str(result)
self.jieguo_var.set(result)
except:
messagebox.showerror('错误', '别闹,没这样的运算')
elif text == '±':
try:
if self.dangqian:
if self.dangqian[0] == '-':
self.dangqian = self.dangqian[1:]
else:
self.dangqian = '-' + self.dangqian
self.jieguo_var.set(self.dangqian)
except:
pass
else:
self.dangqian += text
self.jieguo_var.set(self.dangqian)
def run(self):
self.chuangkou.mainloop()
if __name__ == '__main__':
calc = JiSuanQi()
calc.run()
代码打包
首先执行以下命令安装Python打包所需要的pip工具(如果提示你的pip版本过低,请先执行升级命令)
pip install pyinstaller
随后切换到你当前项目下后右键打开终端,随后执行以下命令进行打包([jisuanqi.py]根据实际修改成你自己的)
pyinstaller --onefile --windowed jisuanqi.py
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容