前言
小北的本篇博客是Python实现一个计算器的小程序
涉及到了tkinter 的一个使用和掌握
友友们要是还不是很懂tkinter 的话,可以康康下面这个视频~
Python超全tkinter案例讲解,基础教学视频!!
小北目前是一名在校大学生,正在学习Python,接触到了PYQT,利用所学的PYQT知识制作了一个简易计算器,实现了win11自带计算器的部分功能,并可以进行进制转换。
小北的能力有限,PYQT做了大半就中途放弃了,所以放在了文末“续”的后面,本文章会与诸多不合理或不专业之处,还请友友们谅解,多多指教~
简易计算器
简易计算器功能:
- 实现输入,计算,输出功能;
- 可以计算基本的加减乘除功能;
- 处理除法中除数不能为零的设计;
- 处理输入不能为空的设计;
- 记录历史计算,显示在右边文本框;
不同于之前的两个项目,这个项目的布局是网格布局,窗口的设计比较像,但是实际的网格布局实现过程中也是碰了许多的坑。
小北还通过使用QTdesinger来进行界面搭建,可以通过鼠标或者键盘进行数据输入和删除,基本实现简单的计算器功能,并且可以实现进制转换的功能。
小北一开始还现在CSDN的InsCode中做了一个极其简易的Python计算器小项目欢迎各Fork讨论鸭~:InsCode - 让你的灵感立刻落地在浏览器中实时运行代码,支持30多种语言和在线IDE,尽在 InsCode。https://inscode.csdn.net/@zhiyilang/Python
图片展示:
视频展示:
CSDN的InsCode简易的Python计算器
用Anacanda的Jupyter Notebook实现
小北将采用Python语言实现一个基本的计算器,该计算器具有以下功能:
1. 支持加、减、乘、除四种基本运算。
2. 支持小数的运算。
3. 支持多次连续计算。
这个程序要怎么实现呢,首先,我们需要导入tkinter模块:
import tkinter #导入tkinter模块
再来创造一个tkinter的窗口:
root = tkinter.Tk()
root.minsize(280,500)
再来实现我们的界面布局
#1.界面布局
#显示面板
result = tkinter.StringVar()
result.set(0) #显示面板显示结果1,用于显示默认数字0
result2 = tkinter.StringVar()
再来编写现显示版的脚本
#显示版
label = tkinter.Label(root,font = ('微软雅黑',20),bg = '#EEE9E9',bd ='9',fg = '#828282',anchor = 'se',textvariable
= result2)
label.place(width = 280,height = 170)
label2 = tkinter.Label(root,font = ('微软雅黑',30),bg = '#EEE9E9',bd ='9',fg = 'black',anchor = 'se',textvariable
= result)
label2.place(y = 170,width = 280,height = 60)
做一个计算器需要数字按钮的功能,所以要编写按钮的脚本
#数字键按钮
btn7 = tkinter.Button(root,text = '7',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('7'))
btn7.place(x = 0,y = 285,width = 70,height = 55)
btn8 = tkinter.Button(root,text = '8',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('8'))
btn8.place(x = 70,y = 285,width = 70,height = 55)
btn9 = tkinter.Button(root,text = '9',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('9'))
btn9.place(x = 140,y = 285,width = 70,height = 55)
btn4 = tkinter.Button(root,text = '4',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('4'))
btn4.place(x = 0,y = 340,width = 70,height = 55)
btn5 = tkinter.Button(root,text = '5',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('5'))
btn5.place(x = 70,y = 340,width = 70,height = 55)
btn6 = tkinter.Button(root,text = '6',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('6'))
btn6.place(x = 140,y = 340,width = 70,height = 55)
btn1 = tkinter.Button(root,text = '1',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('1'))
btn1.place(x = 0,y = 395,width = 70,height = 55)
btn2 = tkinter.Button(root,text = '2',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('2'))
btn2.place(x = 70,y = 395,width = 70,height = 55)
btn3 = tkinter.Button(root,text = '3',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('3'))
btn3.place(x = 140,y = 395,width = 70,height = 55)
btn0 = tkinter.Button(root,text = '0',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('0'))
btn0.place(x = 70,y = 450,width = 70,height = 55)
光有数字按钮还不够,还需要运算符号。
#运算符号按钮
btnac = tkinter.Button(root,text = 'AC',bd = 0.5,font = ('黑体',20),fg = 'orange',command = lambda :pressCompute('AC'))
btnac.place(x = 0,y = 230,width = 70,height = 55)
btnback = tkinter.Button(root,text = '←',font = ('微软雅黑',20),fg = '#4F4F4F',bd = 0.5,command = lambda:
pressCompute('b'))
btnback.place(x = 70,y = 230,width = 70,height = 55)
btndivi = tkinter.Button(root,text = '÷',font = ('微软雅黑',20),fg = '#4F4F4F',bd = 0.5,command = lambda:
pressCompute('/'))
btndivi.place(x = 140,y = 230,width = 70,height = 55)
btnmul = tkinter.Button(root,text ='×',font = ('微软雅黑',20),fg = "#4F4F4F",bd = 0.5,command = lambda:
pressCompute('*'))
btnmul.place(x = 210,y = 230,width = 70,height = 55)
btnsub = tkinter.Button(root,text = '-',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:
pressCompute('-'))
btnsub.place(x = 210,y = 285,width = 70,height = 55)
btnadd = tkinter.Button(root,text = '+',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:
pressCompute('+'))
btnadd.place(x = 210,y = 340,width = 70,height = 55)
btnequ = tkinter.Button(root,text = '=',bg = 'orange',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command =
lambda :pressEqual())
btnequ.place(x = 210,y = 395,width = 70,height = 110)
btnper = tkinter.Button(root,text = '%',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:
pressCompute('%'))
btnper.place(x = 0,y = 450,width = 70,height = 55)
btnpoint = tkinter.Button(root,text = '.',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:
pressCompute('.'))
btnpoint.place(x = 140,y = 450,width = 70,height = 55)
接下来的代码很简单,小北我就不细讲了
#操作函数
lists = [] #设置一个变量 保存运算数字和符号的列表
isPressSign = False #添加一个判断是否按下运算符号的标志,假设默认没有按下按钮
isPressNum = False
#数字函数
def pressNum(num): #设置一个数字函数 判断是否按下数字 并获取数字将数字写在显示版上
global lists #全局化lists和按钮状态isPressSign
global isPressSign
if isPressSign == False:
pass
else: #重新将运算符号状态设置为否
result.set(0)
isPressSign = False
#判断界面的数字是否为0
oldnum = result.get() #第一步
if oldnum =='0': #如过界面上数字为0 则获取按下的数字
result.set(num)
else: #如果界面上的而数字不是0 则链接上新按下的数字
newnum = oldnum + num
result.set(newnum) #将按下的数字写到面板中
#运算函数
def pressCompute(sign):
global lists
global isPressSign
num = result.get() #获取界面数字
lists.append(num) #保存界面获取的数字到列表中
lists.append(sign) #讲按下的运算符号保存到列表中
isPressSign = True
if sign =='AC': #如果按下的是'AC'按键,则清空列表内容,讲屏幕上的数字键设置为默认数字0
lists.clear()
result.set(0)
if sign =='b': #如果按下的是退格'',则选取当前数字第一位到倒数第二位
a = num[0:-1]
lists.clear()
result.set(a)
#获取运算结果函数
def pressEqual():
global lists
global isPressSign
curnum = result.get() #设置当前数字变量,并获取添加到列表
lists.append(curnum)
computrStr = ''.join(lists) #讲列表内容用join命令将字符串链接起来
endNum = eval(computrStr) #用eval命令运算字符串中的内容
# a = str(endNum)
# b = '='+a #给运算结果前添加一个 '=' 显示 不过这样写会有BUG
# c = b[0:10] #所有的运算结果取9位数
result.set(endNum) #讲运算结果显示到屏幕1
result2.set(computrStr) #将运算过程显示到屏幕2
lists.clear() #清空列表内容
最后,进入循环
root.mainloop()
Jupyter Notebook完整代码:
import tkinter #导入tkinter模块
root = tkinter.Tk()
root.minsize(280,500)
#1.界面布局
#显示面板
result = tkinter.StringVar()
result.set(0) #显示面板显示结果1,用于显示默认数字0
result2 = tkinter.StringVar() #显示面板显示结果2,用于显示计算过程
#显示版
label = tkinter.Label(root,font = ('微软雅黑',20),bg = '#EEE9E9',bd ='9',fg = '#828282',anchor = 'se',textvariable
= result2)
label.place(width = 280,height = 170)
label2 = tkinter.Label(root,font = ('微软雅黑',30),bg = '#EEE9E9',bd ='9',fg = 'black',anchor = 'se',textvariable
= result)
label2.place(y = 170,width = 280,height = 60)
#数字键按钮
btn7 = tkinter.Button(root,text = '7',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('7'))
btn7.place(x = 0,y = 285,width = 70,height = 55)
btn8 = tkinter.Button(root,text = '8',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('8'))
btn8.place(x = 70,y = 285,width = 70,height = 55)
btn9 = tkinter.Button(root,text = '9',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('9'))
btn9.place(x = 140,y = 285,width = 70,height = 55)
btn4 = tkinter.Button(root,text = '4',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('4'))
btn4.place(x = 0,y = 340,width = 70,height = 55)
btn5 = tkinter.Button(root,text = '5',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('5'))
btn5.place(x = 70,y = 340,width = 70,height = 55)
btn6 = tkinter.Button(root,text = '6',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('6'))
btn6.place(x = 140,y = 340,width = 70,height = 55)
btn1 = tkinter.Button(root,text = '1',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('1'))
btn1.place(x = 0,y = 395,width = 70,height = 55)
btn2 = tkinter.Button(root,text = '2',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('2'))
btn2.place(x = 70,y = 395,width = 70,height = 55)
btn3 = tkinter.Button(root,text = '3',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('3'))
btn3.place(x = 140,y = 395,width = 70,height = 55)
btn0 = tkinter.Button(root,text = '0',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda :
pressNum('0'))
btn0.place(x = 70,y = 450,width = 70,height = 55)
#运算符号按钮
btnac = tkinter.Button(root,text = 'AC',bd = 0.5,font = ('黑体',20),fg = 'orange',command = lambda :pressCompute('AC'))
btnac.place(x = 0,y = 230,width = 70,height = 55)
btnback = tkinter.Button(root,text = '←',font = ('微软雅黑',20),fg = '#4F4F4F',bd = 0.5,command = lambda:
pressCompute('b'))
btnback.place(x = 70,y = 230,width = 70,height = 55)
btndivi = tkinter.Button(root,text = '÷',font = ('微软雅黑',20),fg = '#4F4F4F',bd = 0.5,command = lambda:
pressCompute('/'))
btndivi.place(x = 140,y = 230,width = 70,height = 55)
btnmul = tkinter.Button(root,text ='×',font = ('微软雅黑',20),fg = "#4F4F4F",bd = 0.5,command = lambda:
pressCompute('*'))
btnmul.place(x = 210,y = 230,width = 70,height = 55)
btnsub = tkinter.Button(root,text = '-',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:
pressCompute('-'))
btnsub.place(x = 210,y = 285,width = 70,height = 55)
btnadd = tkinter.Button(root,text = '+',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:
pressCompute('+'))
btnadd.place(x = 210,y = 340,width = 70,height = 55)
btnequ = tkinter.Button(root,text = '=',bg = 'orange',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command =
lambda :pressEqual())
btnequ.place(x = 210,y = 395,width = 70,height = 110)
btnper = tkinter.Button(root,text = '%',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:
pressCompute('%'))
btnper.place(x = 0,y = 450,width = 70,height = 55)
btnpoint = tkinter.Button(root,text = '.',font = ('微软雅黑',20),fg = ('#4F4F4F'),bd = 0.5,command = lambda:
pressCompute('.'))
btnpoint.place(x = 140,y = 450,width = 70,height = 55)
#操作函数
lists = [] #设置一个变量 保存运算数字和符号的列表
isPressSign = False #添加一个判断是否按下运算符号的标志,假设默认没有按下按钮
isPressNum = False
#数字函数
def pressNum(num): #设置一个数字函数 判断是否按下数字 并获取数字将数字写在显示版上
global lists #全局化lists和按钮状态isPressSign
global isPressSign
if isPressSign == False:
pass
else: #重新将运算符号状态设置为否
result.set(0)
isPressSign = False
#判断界面的数字是否为0
oldnum = result.get() #第一步
if oldnum =='0': #如过界面上数字为0 则获取按下的数字
result.set(num)
else: #如果界面上的而数字不是0 则链接上新按下的数字
newnum = oldnum + num
result.set(newnum) #将按下的数字写到面板中
#运算函数
def pressCompute(sign):
global lists
global isPressSign
num = result.get() #获取界面数字
lists.append(num) #保存界面获取的数字到列表中
lists.append(sign) #讲按下的运算符号保存到列表中
isPressSign = True
if sign =='AC': #如果按下的是'AC'按键,则清空列表内容,讲屏幕上的数字键设置为默认数字0
lists.clear()
result.set(0)
if sign =='b': #如果按下的是退格'',则选取当前数字第一位到倒数第二位
a = num[0:-1]
lists.clear()
result.set(a)
#获取运算结果函数
def pressEqual():
global lists
global isPressSign
curnum = result.get() #设置当前数字变量,并获取添加到列表
lists.append(curnum)
computrStr = ''.join(lists) #讲列表内容用join命令将字符串链接起来
endNum = eval(computrStr) #用eval命令运算字符串中的内容
# a = str(endNum)
# b = '='+a #给运算结果前添加一个 '=' 显示 不过这样写会有BUG
# c = b[0:10] #所有的运算结果取9位数
result.set(endNum) #讲运算结果显示到屏幕1
result2.set(computrStr) #将运算过程显示到屏幕2
lists.clear() #清空列表内容
root.mainloop()
实例1:(白色)
Anacanda运行结果:![](https://i-blog.csdnimg.cn/blog_migrate/58f923ffc3c5f67f1de2293af2de1c94.png)
实例2:(黑色)
原代码:
import tkinter
import tkinter.font
class Calculator(object):
def __init__(self):
self.all_press_lists = []
self.is_press = False
self.is_press_num = False
self.root = tkinter.Tk()
self.result = tkinter.StringVar() # 显示输入的数字及结果
self.record = tkinter.StringVar() # 显示计算过程
def main(self):
self.root.minsize(300, 550)
self.root.title('计算器')
input_bg = "#393943"
num_fg = "#DCDCDC"
btn_fg = "#909194"
btn_bg = "#22222C"
btn_w = 75
btn_h = 70
my_font = tkinter.font.Font(family='微软雅黑', size=20) # 设置字体
self.result.set(0)
self.record.set('')
# 显示版
label = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=num_fg, anchor='se',
textvariable=self.record)
label.place(width=300, height=120)
label2 = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=num_fg, anchor='se',
textvariable=self.result)
label2.place(y=120, width=300, height=80)
# 第一行
btn_ac = tkinter.Button(self.root, text='c', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_compute('AC'))
btn_ac.place(x=btn_w * 0, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_back = tkinter.Button(self.root, text='←', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_compute('b'))
btn_back.place(x=btn_w * 1, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_per = tkinter.Button(self.root, text='%', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_compute('%'))
btn_per.place(x=btn_w * 2, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_divi = tkinter.Button(self.root, text='÷', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_compute('/'))
btn_divi.place(x=btn_w * 3, y=200 + btn_h * 0, width=btn_w, height=btn_h)
# 第二行
btn7 = tkinter.Button(self.root, text='7', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('7'))
btn7.place(x=btn_w * 0, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn8 = tkinter.Button(self.root, text='8', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('8'))
btn8.place(x=btn_w * 1, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn9 = tkinter.Button(self.root, text='9', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('9'))
btn9.place(x=btn_w * 2, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_mul = tkinter.Button(self.root, text='×', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_compute('*'))
btn_mul.place(x=btn_w * 3, y=200 + btn_h * 1, width=btn_w, height=btn_h)
# 第三行
btn4 = tkinter.Button(self.root, text='4', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('4'))
btn4.place(x=btn_w * 0, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn5 = tkinter.Button(self.root, text='5', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('5'))
btn5.place(x=btn_w * 1, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn6 = tkinter.Button(self.root, text='6', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('6'))
btn6.place(x=btn_w * 2, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn_sub = tkinter.Button(self.root, text='-', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_compute('-'))
btn_sub.place(x=btn_w * 3, y=200 + btn_h * 2, width=btn_w, height=btn_h)
# 第四行
btn1 = tkinter.Button(self.root, text='1', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('1'))
btn1.place(x=btn_w * 0, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn2 = tkinter.Button(self.root, text='2', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('2'))
btn2.place(x=btn_w * 1, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn3 = tkinter.Button(self.root, text='3', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('3'))
btn3.place(x=btn_w * 2, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn_add = tkinter.Button(self.root, text='+', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_compute('+'))
btn_add.place(x=btn_w * 3, y=200 + btn_h * 3, width=btn_w, height=btn_h)
# 第五行
btn0 = tkinter.Button(self.root, text='0', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('0'))
btn0.place(x=btn_w * 0, y=200 + btn_h * 4, width=btn_w * 2, height=btn_h)
btn_point = tkinter.Button(self.root, text='.', font=my_font, bg=btn_bg, fg=num_fg, bd=0,
command=lambda: self.press_num('.'))
btn_point.place(x=btn_w * 2, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn_equ = tkinter.Button(self.root, text='=', bg='#982425', font=my_font, fg=num_fg, bd=0,
command=lambda: self.press_equal())
btn_equ.place(x=btn_w * 3, y=200 + btn_h * 4, width=btn_w, height=btn_h)
self.root.mainloop()
# 按下数字键
def press_num(self, num):
if self.is_press is False:
pass
else:
self.result.set(0)
self.is_press = False
# 判断界面的数字是否为0
old_num = self.result.get()
if old_num == '0':
self.result.set(num)
else:
new_num = old_num + num
self.result.set(new_num)
# 按下运算键
def press_compute(self, sign):
num = self.result.get()
self.all_press_lists.append(num)
self.all_press_lists.append(sign)
self.is_press = True
if sign == 'AC': # 按下'AC',清空列表内容,显示0
self.all_press_lists.clear()
self.result.set(0)
if sign == 'b': # 按下退格,当前数字逐步减一
a = num[0:-1]
self.all_press_lists.clear()
self.result.set(a)
# 获取运算结果函数
def press_equal(self):
cur_num = self.result.get()
self.all_press_lists.append(cur_num)
compute_str = ''.join(self.all_press_lists)
try:
calculate_result = eval(compute_str)
except:
calculate_result = 'bad parameter'
self.result.set(calculate_result) # 显示结果
self.record.set(compute_str + "=") # 显示运算过程
self.all_press_lists.clear() # 清空列表内容
if __name__ == '__main__':
my_calculator = Calculator()
my_calculator.main()
总起:
一、设计思路(Anacanda的Jupyter Notebook 和基于PYQT的Visual Studio Code都一样)![](https://i-blog.csdnimg.cn/blog_migrate/6f13f11c0a3835112882fcfa1af86d2a.png)
在设计计算器程序时,我们需要考虑以下几个方面:
1. 界面设计:计算器需要一个简单的用户界面,用户可以通过该界面输入数字和运算符。
2. 数据类型:我们需要定义一些变量和数据类型来存储用户输入的数字和运算符,以及计算结果。
3. 运算逻辑:计算器需要根据用户输入的运算符来进行相应的数学运算,并输出计算结果。
二、界面设计
计算器的界面应该简洁明了,方便用户输入数字和运算符。我们可以使用Python的tkinter库来实现界面设计。
首先,我们需要导入tkinter库,并创建一个窗口对象:
import tkinter as tk
class CalculatorApp:
def __init__(self, window):
self.window = window
self.window.title("Calculator")
可以加上代码:window.mainloop()检验:(记得删除!!!)
然后,我们可以在窗口中添加一些组件,如文本框、按钮等:
# 添加文本框
text = tk.Entry(window, width=25, font=('Arial', 16))
text.pack(side='top', pady=10)
# 添加按钮
btn_1 = tk.Button(window, text='1', width=5, height=2)
btn_1.pack(side='left')
btn_2 = tk.Button(window, text='2', width=5, height=2)
btn_2.pack(side='left')
# ...
可以加上代码:window.mainloop()检验:(记得删除!!!)
这里我们只添加了数字按钮,其他运算符按钮的添加类似。
三、数据类型
在计算器中,我们需要定义一些变量和数据类型来存储用户输入的数字和运算符,以及计算结果。
首先,我们需要定义一个变量来存储用户输入的数字:
num = ''
然后,我们需要定义一个变量来存储用户选择的运算符:
operator = ''
最后,我们需要定义一个变量来存储计算结果:
result = 0.0
整合:
self.result = 0.0
self.operator = ''
self.num1 = ''
self.num2 = ''
self.num = ''
self.create_widgets()
四、运算逻辑
在计算器中,我们需要根据用户输入的运算符来进行相应的数学运算,并输出计算结果。
我们可以使用Python中的if语句来实现不同运算符的处理:
def create_widgets(self):
# Text Entry
self.text = tk.Entry(self.window, width=25, font=('Arial', 16))
self.text.pack(side='top', pady=10)
# Number Buttons
for i in range(1, 10):
button = tk.Button(self.window, text=str(i), width=5, height=2, command=lambda num=i: self.add_num(num))
button.pack(side='left')
# Operator Buttons
operators = ['+', '-', '*', '/']
for op in operators:
button = tk.Button(self.window, text=op, width=5, height=2, command=lambda operator=op: self.add_operator(operator))
button.pack(side='left')
# Clear and Equals Buttons
btn_clear = tk.Button(self.window, text='C', width=5, height=2, command=self.clear)
btn_clear.pack(side='left')
btn_equal = tk.Button(self.window, text='=', width=5, height=2, command=self.calculate)
btn_equal.pack(side='left')
def add_num(self, num):
if self.operator == '':
self.num1 += str(num)
self.text.insert('end', num)
else:
self.num2 += str(num)
self.text.insert('end', num)
def add_operator(self, op):
if self.num1 == '':
self.num1 = self.num
self.operator = op
self.num = ''
else:
self.num2 = self.num
self.calculate()
self.operator = op
self.num = ''
def clear(self):
self.result = 0.0
self.operator = ''
self.num1 = ''
self.num2 = ''
self.num = ''
self.text.delete(0, 'end')
def calculate(self):
if self.num1 and self.num2:
if self.operator == '+':
self.result = float(self.num1) + float(self.num2)
elif self.operator == '-':
self.result = float(self.num1) - float(self.num2)
elif self.operator == '*':
self.result = float(self.num1) * float(self.num2)
elif self.operator == '/':
if float(self.num2) != 0:
self.result = float(self.num1) / float(self.num2)
else:
self.result = "Error: Division by zero"
self.text.delete(0, 'end')
self.text.insert('end', str(self.result))
self.num1 = str(self.result)
self.num2 = ''
self.operator = ''
self.num = ''
这里我们使用了Python中的float()函数将字符串转换为浮点数类型,以便进行数学运算。
最后,我们需要将计算结果输出到文本框中:
if __name__ == "__main__":
window = tk.Tk()
app = CalculatorApp(window)
window.mainloop()
更加干净整洁的代码:
import tkinter as tk
class CalculatorApp:
def __init__(self, window):
self.window = window
self.window.title("Calculator")
self.result = 0.0
self.operator = ''
self.num1 = ''
self.num2 = ''
self.num = ''
self.create_widgets()
def create_widgets(self):
# Text Entry
self.text = tk.Entry(self.window, width=25, font=('Arial', 16))
self.text.pack(side='top', pady=10)
# Number Buttons
for i in range(1, 10):
button = tk.Button(self.window, text=str(i), width=5, height=2, command=lambda num=i: self.add_num(num))
button.pack(side='left')
# Operator Buttons
operators = ['+', '-', '*', '/']
for op in operators:
button = tk.Button(self.window, text=op, width=5, height=2, command=lambda operator=op: self.add_operator(operator))
button.pack(side='left')
# Clear and Equals Buttons
btn_clear = tk.Button(self.window, text='C', width=5, height=2, command=self.clear)
btn_clear.pack(side='left')
btn_equal = tk.Button(self.window, text='=', width=5, height=2, command=self.calculate)
btn_equal.pack(side='left')
def add_num(self, num):
if self.operator == '':
self.num1 += str(num)
self.text.insert('end', num)
else:
self.num2 += str(num)
self.text.insert('end', num)
def add_operator(self, op):
if self.num1 == '':
self.num1 = self.num
self.operator = op
self.num = ''
else:
self.num2 = self.num
self.calculate()
self.operator = op
self.num = ''
def clear(self):
self.result = 0.0
self.operator = ''
self.num1 = ''
self.num2 = ''
self.num = ''
self.text.delete(0, 'end')
def calculate(self):
if self.num1 and self.num2:
if self.operator == '+':
self.result = float(self.num1) + float(self.num2)
elif self.operator == '-':
self.result = float(self.num1) - float(self.num2)
elif self.operator == '*':
self.result = float(self.num1) * float(self.num2)
elif self.operator == '/':
if float(self.num2) != 0:
self.result = float(self.num1) / float(self.num2)
else:
self.result = "Error: Division by zero"
self.text.delete(0, 'end')
self.text.insert('end', str(self.result))
self.num1 = str(self.result)
self.num2 = ''
self.operator = ''
self.num = ''
if __name__ == "__main__":
window = tk.Tk()
app = CalculatorApp(window)
window.mainloop()
这里我们使用了全局变量来存储用户输入的数字和运算符,以及计算结果。我们还使用了lambda表达式来将数字和运算符与相应的按钮关联起来。
五、运行程序
修改上述代码:
import tkinter as tk
class CalculatorApp:
def __init__(self, window):
self.window = window
self.window.title("Calculator")
self.result = 0.0
self.operator = ''
self.num1 = ''
self.num2 = ''
self.create_widgets()
def create_widgets(self):
# Text Entry
self.text = tk.Entry(self.window, width=25, font=('Arial', 16))
self.text.grid(row=0, column=0, columnspan=4, padx=10, pady=10)
# Number Buttons
for i in range(1, 10):
button = tk.Button(self.window, text=str(i), width=5, height=2, command=lambda num=i: self.add_num(num))
button.grid(row=(i-1)//3+1, column=(i-1)%3)
# Operator Buttons
operators = ['+', '-', '*', '/']
for i, op in enumerate(operators):
button = tk.Button(self.window, text=op, width=5, height=2, command=lambda operator=op: self.add_operator(operator))
button.grid(row=i+1, column=3)
# Clear and Equals Buttons
btn_clear = tk.Button(self.window, text='C', width=5, height=2, command=self.clear)
btn_clear.grid(row=4, column=0)
btn_equal = tk.Button(self.window, text='=', width=5, height=2, command=self.calculate)
btn_equal.grid(row=4, column=1, columnspan=3)
def add_num(self, num):
if self.operator == '':
self.num1 += str(num)
self.text.insert('end', num)
else:
self.num2 += str(num)
self.text.insert('end', num)
def add_operator(self, op):
if self.num1 == '':
self.num1 = self.result
self.operator = op
self.num2 = ''
else:
self.num2 = ''
self.calculate()
self.operator = op
def clear(self):
self.result = 0.0
self.operator = ''
self.num1 = ''
self.num2 = ''
self.text.delete(0, 'end')
def calculate(self):
if self.num1 and self.num2:
if self.operator == '+':
self.result = float(self.num1) + float(self.num2)
elif self.operator == '-':
self.result = float(self.num1) - float(self.num2)
elif self.operator == '*':
self.result = float(self.num1) * float(self.num2)
elif self.operator == '/':
if float(self.num2) != 0:
self.result = float(self.num1) / float(self.num2)
else:
self.result = "Error: Division by zero"
self.text.delete(0, 'end')
self.text.insert('end', str(self.result))
self.num1 = str(self.result)
self.num2 = ''
self.operator = ''
if __name__ == "__main__":
window = tk.Tk()
app = CalculatorApp(window)
window.mainloop()
保存上述代码为calculator.py文件,并在命令行中执行以下命令来运行程序:
python calculator.py
程序运行后,将会弹出一个计算器窗口,用户可以通过该窗口进行数字和运算符的输入,计算结果将会显示在文本框中。用户可以通过清除按钮清空计算器,也可以通过等号按钮进行连续计算。
简易计算机就做好啦!!!
六、QTdesinger界面
在qt界面中,使用了QLabel、QLineEdit、QPushButton与QCheckBox四种插件,同时使用了Vertical Layout(水平布局) 、Horizontal Layout(垂直布局)与Grid Layout (栅格布局)三种布局方式。
窗口
实现最基本的窗口界面
import tkinter as tk
import tkinter.messagebox
win = tk.Tk() #窗口名称
win.title("简易计算器")
win.geometry('650x600') # 这里的乘是小x
geometry()设置窗口的大小,格式:高x宽+起始x位置+起始y位置,例如:“600x600+50+50”意思是大小为600*600,起始位置坐标为(50,50)
可以加上代码:win.mainloop()检验:(记得删除!!!)
布局
标题
使用标签Label实现,标签上可以展示文字,居中,可以设置背景色,字体字号,以及标签的大小。
b=tk.Label(win, text='简易计算器',justify=tk.CENTER, height=2 , width=50 ,font=('楷体', 20),background='lightcyan') # 文本框名字
b.grid(row=0,columnspan=6)
按键颜色、窗口颜色、字体类型与字体大小通过右侧属性编辑器中的styleSheet选项进行更改,使用时选择所要更改的对象,点击...进行更改。
可以加上代码:win.mainloop()检验:(记得删除!!!)
输入框
输入框a1,a2使用的是Entry,前面的名字使用的是Label标签
justify表示文字的位置,或者输入文字的起始位置是从那一边开始,有左和右,
width和height,代表宽度和高度
font,里面包含楷体和字号,这个可以不写,有默认值。
grid显示布局的位置,行列号。row,column分别代表行和列,rowspan,columnspan代表行列方向上占据的大小
通过输入框名字.get()获取输入框内的内容
b1=tk.Label(win, text='a:',justify=tk.CENTER, height=2 , width=5 ,font=('楷体', 15)) # 文本框名字
b1.grid(row=1,column=0)
a1 = tk.Entry(win, justify=tk.LEFT, width=15 , font=('楷体', 15)) # 文本框创建
a1.grid(row=1,column=1)
b2 = tk.Label(win, text='b:',justify=tk.CENTER, height=2 , width=5 , font=('楷体', 15)) # 文本框名字
b2.grid(row=2,column=0)
a2 = tk.Entry(win, justify=tk.LEFT, width=15 , font=('楷体', 15) ) # 文本框创建
a2.grid(row=2,column=1)
可以加上代码:win.mainloop()检验:(记得删除!!!)![](https://i-blog.csdnimg.cn/blog_migrate/5b5115b015422519c1b76f381ec4772d.png)
文本记录框
记录历史计算的文本,通过insert插入拼接完成的字符串数据,通过数值标记完成换行 两列换行操作。如果不设置文本框的大小,只设置占据的行列数时,会导致窗口变得大小不定,组件之间的空隙较大,不并不很美观。
txt = tk.Text(win,height=20, width=40 ,font=('楷体', 15)) #font对输入的文本的字体和大小进行规定
txt.grid(row=1,column=4,rowspan=4,columnspan=4) #大小是4*4
可以加上代码:win.mainloop()检验:(记得删除!!!)
按钮功能
当两个数据输进去以后,我们将数据按照按钮点击的需求进行计算,并且弹出结果。实现功能:
当输为空的时候,弹窗提示,并且保证可以再次输入数据等操作
除法运算的特殊之处,除数不能为零,也需要在输入错误时进行提示
当结果计算完成时,要完成算式的拼接,插入文本框中
提示计算的结果
清空输入框,等到下一次的计算输入
判断历史计算的次数,为插入算式的位置进行改变。两列数据之间要进行间隔的设置。
每一个按钮的设计方法相似,知识各有各的实现功能,大同小异,格式都相同,只是计算不一样。可以通过研究一个函数功能,类推其他几个。
num=0 #用来记录历史计算次数
def sum():
if a1.get()=='' or a2.get()=='':
return tkinter.messagebox.showinfo('消息提示', '输入不能为空')
global num
num += 1
a = float(a1.get()) #获取输入框内的内容,收集到的为字符型,需要进行转化
b = float(a2.get())
c = a + b
s = str('%d'%a + ' + '+'%d'%b + ' = ' + '%d'%c) #完成数据的拼接
if num%2==0:
s=s+ '\n' #第偶数个算式后面加上空格进行间隔
print(num)
else:
s=s+'\t' #第奇数个算式进行换行处理
txt.insert(tk.END,s)
tkinter.messagebox.showinfo('消息提示', '求商结果是:%d'%c)
a1.delete(0, tk.END) #清空输入框内的数据
a2.delete(0, tk.END)
def multiply():
if a1.get()=='' or a2.get()=='':
return tkinter.messagebox.showinfo('消息提示', '输入不能为空')
global num
num += 1
a = float(a1.get())
b = float(a2.get())
c = a * b
s = str('%d' % a + ' * ' + '%d' % b + ' = ' + '%d' % c)
if num%2==0:
s=s+ '\n'
print(num)
else:
s=s+'\t'
txt.insert(tk.END, s)
tkinter.messagebox.showinfo('消息提示', '求积结果是:%d'%c)
a1.delete(0, tk.END)
a2.delete(0, tk.END)
def subtract():
if a1.get()=='' or a2.get()=='':
return tkinter.messagebox.showinfo('消息提示', '输入不能为空')
global num
num += 1
a = float(a1.get())
b = float(a2.get())
c = a - b
s = str('%d' % a + ' - ' + '%d' % b + ' = ' + '%d' % c)
if num%2==0:
s=s+ '\n'
print(num)
else:
s=s+'\t'
txt.insert(tk.END, s)
tkinter.messagebox.showinfo('消息提示', '求差结果是:%d'%c)
a1.delete(0, tk.END)
a2.delete(0, tk.END)
def divide():
if a1.get()=='' or a2.get()=='':
return tkinter.messagebox.showinfo('消息提示', '输入不能为空')
global num
num += 1
a = float(a1.get())
b = float(a2.get())
if float(b)==0.0:
tkinter.messagebox.showinfo('消息提示', '除数不能为零!!!')
a2.delete(0 , tk.END) # 当除数为0时,不能进行计算,并且需要弹窗提示,清空数据
else:
c = a / b
s = str('%d' % a + ' / ' + '%d' % b + ' = ' + '%d' % c)
if num % 2 == 0:
s = s + '\n'
print(num)
else:
s = s + '\t'
txt.insert(tk.END, s)
tkinter.messagebox.showinfo('消息提示', '求商结果是:%d'%c)
a1.delete(0, tk.END)
a2.delete(0, tk.END)
按钮
这里有一个坑,刚开始我设计按钮的时候直接是:command = sum(),于是函数在我还没有点击按钮时就进行了一次计算,所以刚开始运行程序就提醒我输入不能为空。试了很多方法,才试到这个方法。在函数前面加上:“lamba:”。
a4 = tk.Button(win, text='求和',justify=tk.CENTER, width=10, font=('楷体', 15) ,command = lambda :sum() ) # 文本框创建
a4.grid(row=3, column=0)
a5 = tk.Button(win, text='求积', justify=tk.CENTER, width=10 , font=('楷体', 15), command = lambda :multiply()) # 文本框创建
a5.grid(row=3, column=1)
a6 = tk.Button(win, text='求差', justify=tk.CENTER, width=10, font=('楷体', 15), command = lambda :subtract()) # 文本框创建
a6.grid(row=4, column=0)
a7 = tk.Button(win, text='求商', justify=tk.CENTER, width=10, font=('楷体', 15), command = lambda :divide()) # 文本框创建
a7.grid(row=4, column=1)
附完整代码:
import tkinter as tk
import tkinter.messagebox
win = tk.Tk() #窗口名称
win.title("简易计算器")
win.geometry('650x600') # 这里的乘是小x
b=tk.Label(win, text='简易计算器',justify=tk.CENTER, height=2 , width=50 ,font=('楷体', 20),background='lightcyan') # 文本框名字
b.grid(row=0,columnspan=6)
b1=tk.Label(win, text='a:',justify=tk.CENTER, height=2 , width=5 ,font=('楷体', 15)) # 文本框名字
b1.grid(row=1,column=0)
a1 = tk.Entry(win, justify=tk.LEFT, width=15 , font=('楷体', 15)) # 文本框创建
a1.grid(row=1,column=1)
b2 = tk.Label(win, text='b:',justify=tk.CENTER, height=2 , width=5 , font=('楷体', 15)) # 文本框名字
b2.grid(row=2,column=0)
a2 = tk.Entry(win, justify=tk.LEFT, width=15 , font=('楷体', 15) ) # 文本框创建
a2.grid(row=2,column=1)
txt = tk.Text(win,height=20, width=40 ,font=('楷体', 15))
txt.grid(row=1,column=4,rowspan=4,columnspan=4)
num=0
def sum():
if a1.get()=='' or a2.get()=='':
return tkinter.messagebox.showinfo('消息提示', '输入不能为空')
global num
num += 1
a = float(a1.get())
b = float(a2.get())
c = a + b
s = str('%d'%a + ' + '+'%d'%b + ' = ' + '%d'%c)
if num%2==0:
s=s+ '\n'
print(num)
else:
s=s+'\t'
txt.insert(tk.END,s)
tkinter.messagebox.showinfo('消息提示', '求商结果是:%d'%c)
a1.delete(0, tk.END)
a2.delete(0, tk.END)
def multiply():
if a1.get()=='' or a2.get()=='':
return tkinter.messagebox.showinfo('消息提示', '输入不能为空')
global num
num += 1
a = float(a1.get())
b = float(a2.get())
c = a * b
s = str('%d' % a + ' * ' + '%d' % b + ' = ' + '%d' % c)
if num%2==0:
s=s+ '\n'
print(num)
else:
s=s+'\t'
txt.insert(tk.END, s)
tkinter.messagebox.showinfo('消息提示', '求积结果是:%d'%c)
a1.delete(0, tk.END)
a2.delete(0, tk.END)
def subtract():
if a1.get()=='' or a2.get()=='':
return tkinter.messagebox.showinfo('消息提示', '输入不能为空')
global num
num += 1
a = float(a1.get())
b = float(a2.get())
c = a - b
s = str('%d' % a + ' - ' + '%d' % b + ' = ' + '%d' % c)
if num%2==0:
s=s+ '\n'
print(num)
else:
s=s+'\t'
txt.insert(tk.END, s)
tkinter.messagebox.showinfo('消息提示', '求差结果是:%d'%c)
a1.delete(0, tk.END)
a2.delete(0, tk.END)
def divide():
if a1.get()=='' or a2.get()=='':
return tkinter.messagebox.showinfo('消息提示', '输入不能为空')
global num
num += 1
a = float(a1.get())
b = float(a2.get())
if float(b)==0.0:
tkinter.messagebox.showinfo('消息提示', '除数不能为零!!!')
a2.delete(0 , tk.END) # 删除文本框内索引为0-999的字符
else:
c = a / b
s = str('%d' % a + ' / ' + '%d' % b + ' = ' + '%d' % c)
if num % 2 == 0:
s = s + '\n'
print(num)
else:
s = s + '\t'
txt.insert(tk.END, s)
tkinter.messagebox.showinfo('消息提示', '求商结果是:%d'%c)
a1.delete(0, tk.END)
a2.delete(0, tk.END)
a4 = tk.Button(win, text='求和',justify=tk.CENTER, width=10, font=('楷体', 15) ,command = lambda :sum() ) # 文本框创建
a4.grid(row=3, column=0)
a5 = tk.Button(win, text='求积', justify=tk.CENTER, width=10 , font=('楷体', 15), command = lambda :multiply()) # 文本框创建
a5.grid(row=3, column=1)
a6 = tk.Button(win, text='求差', justify=tk.CENTER, width=10, font=('楷体', 15), command = lambda :subtract()) # 文本框创建
a6.grid(row=4, column=0)
a7 = tk.Button(win, text='求商', justify=tk.CENTER, width=10, font=('楷体', 15), command = lambda :divide()) # 文本框创建
a7.grid(row=4, column=1)
win.mainloop()
小北的博客只实现了较为简单的计算功能,当然也可以设计更多的功能,只需要加以研究,就可以完成~
集合标准和科学模式于一体
实现简单的加减乘除,支持小数点和负数运算
实现复合运算和取余运算
实现sin,arcsin,ln,平方根,以及幂的运算
实现十进制到二进制转换
实现e,π的输出
可以复制粘贴剪切计算器中的数据
可以全部清除和只清除一个
计算器样式:
视频展示:
集合标准和科学模式于一体
完整代码:
import re
from math import *
# 将算式从字符串处理成列表,解决横杠是负号还是减号的问题
def formula_format(formula):
"""
解释参数类型
:param formula: str
"""
formula = re.sub(' ', '', formula)
# re.sub()在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串
# 去掉算式中的空格s
# 以 '横杠数字' 分割, 其中正则表达式:(\-\d+\.?\d*) 括号内:
# \- 表示匹配横杠开头;\d+ 表示匹配数字1次或多次;\.?表示匹配小数点0次或1次;\d*表示匹配数字0次或多次。
# []中的字符是任选择一个使用,括号(…)可以把(…)看出一个整体,经常与"+"、"*"、"?"的连续使用,对(…)部分进行重复.
formula_list = [i for i in re.split('(\-[\d+,π,e]\.?\d*)', formula) if i]
# re.split()将一个字符串按照正则表达式匹配结果进行分割,返回列表类型
final_formula = [] # 最终的算式列表
for item in formula_list:
# 算式以横杠开头,则第一个数字为负数,横杠为负号
# re.match()从一个字符串的开始位置起匹配正则表达式,返回match对象
# 如果不是起始位置匹配成功的话,match()就返回none
# $字符比配字符串的结尾位置
if len(final_formula) == 0 and re.match('\-[\d+,π,e]\.?\d*$', item):
final_formula.append(item)
continue
# 如果当前的算式列表最后一个元素的第一个位置是运算符['+', '-', '*', '/', '(', '%', '^'],
# 则横杠为减号
if len(final_formula) > 0:
# 输出为none或者数字
if re.match('[\+\-\*\/\(\%\^]$', final_formula[-1]):
final_formula.append(item)
continue
# 按照运算符分割开
item_split = [i for i in re.split('([\+\-\*\/\(\)\%\^\√])', item) if i]
final_formula += item_split
return final_formula
# 判断是否是运算符,如果是返回True
def is_operator(e):
"""
:param e: str
:return: bool
"""
opers = ['+', '-', '*', '/', '(', ')', '%',
'^', '√', 'sin', 'arcsin', 'ln']
return True if e in opers else False # 在for循环中嵌套使用if和else语句
# 比较连续两个运算符来判断是压栈还是弹栈
def decision(tail_op, now_op):
"""
:param tail_op: 运算符栈的最后一个运算符
:param now_op: 从算式列表取出的当前运算符
:return: 1代表弹栈运算,0代表弹出运算符栈最后一个元素'(',-1表示压栈
"""
# 定义4种运算符级别
rate1 = ['+', '-']
rate2 = ['*', '/', '%']
rate3 = ['^', '√', 'sin', 'arcsin', 'ln']
rate4 = ['(']
rate5 = [')']
if tail_op in rate1:
if now_op in rate2 or now_op in rate3 or now_op in rate4:
return -1 # 说明当前运算符优先级高于运算符栈的最后一个运算符,需要压栈
else:
return 1 # 说明当前运算符优先级等于运算符栈的最后一个运算符,需要弹栈运算
elif tail_op in rate2:
if now_op in rate3 or now_op in rate4:
return -1
else:
return 1
elif tail_op in rate3:
if now_op in rate4:
return -1
else:
return 1
elif tail_op in rate4:
if now_op in rate5:
return 0 # '('遇上')',需要弹出'('并丢掉')',表明该括号内的算式已计算完成并将结果压入数字栈中
else:
return -1 # 只要栈顶元素为'('且当前元素不是')',都应压入栈中
# 传入两个数字,一个运算符,根据运算符不同返回相应结果
def calculate(n1, n2, operator):
"""
:param n1: float
:param n2: float
:param operator: + - * / % ^
:return: float
"""
result = 0
if operator == '+':
result = n1 + n2
if operator == '-':
result = n1 - n2
if operator == '*':
result = n1 * n2
if operator == '/':
result = n1 / n2
if operator == '%':
result = n1 % n2
if operator == '^':
result = n1 ** n2
return result
# 括号内的算式求出计算结果后,计算√ ̄()、sin()或arcsin()
def gaojie(op_stack, num_stack): # 运算符栈,数字栈
if op_stack[-1] == '√':
# pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回从列表中移除的元素对象。
# append() 函数可以向列表末尾添加元素
op = op_stack.pop()
num2 = num_stack.pop()
num_stack.append(sqrt(num2))
elif op_stack[-1] == 'sin':
op = op_stack.pop()
num2 = num_stack.pop()
num_stack.append(sin(num2))
elif op_stack[-1] == 'arcsin':
op = op_stack.pop()
num2 = num_stack.pop()
num_stack.append(asin(num2))
elif op_stack[-1] == 'ln':
op = op_stack.pop()
num2 = num_stack.pop()
num_stack.append(log(num2))
# 负责遍历算式列表中的字符,决定压入数字栈中或压入运算符栈中或弹栈运算
def final_calc(formula_list):
"""
:param formula_list: 算式列表
:return: 计算结果
"""
num_stack = [] # 数字栈
op_stack = [] # 运算符栈
for item in formula_list:
operator = is_operator(item)
# 压入数字栈
if not operator:
# π和e转换成可用于计算的值
if item == 'π':
num_stack.append(pi)
elif item == '-π':
num_stack.append(-pi)
elif item == 'e':
num_stack.append(e)
elif item == '-e':
num_stack.append(-e)
else:
num_stack.append(float(item)) # 字符串转换为浮点数
# 如果是运算符
else:
while True:
# 如果运算符栈为空,则无条件入栈
if len(op_stack) == 0:
op_stack.append(item)
break
# 决定压栈或弹栈
tag = decision(op_stack[-1], item)
# 如果是-1,则压入运算符栈并进入下一次循环
if tag == -1:
op_stack.append(item)
break
# 如果是0,则弹出运算符栈内最后一个'('并丢掉当前')',进入下一次循环
elif tag == 0:
op_stack.pop()
# '('前是'√ ̄'、'sin'或'arcsin'时,对括号内算式的计算结果作相应的运算
gaojie(op_stack, num_stack)
break
# 如果是1,则弹出运算符栈内最后一个元素和数字栈内最后两个元素
elif tag == 1:
if item in ['√', 'sin', 'arcsin']:
op_stack.append(item)
break
op = op_stack.pop()
num2 = num_stack.pop()
num1 = num_stack.pop()
# 将计算结果压入数字栈并接着循环,直到遇到break跳出循环
num_stack.append(calculate(num1, num2, op))
# 大循环结束后,数字栈和运算符栈中可能还有元素的情况
while len(op_stack) != 0:
op = op_stack.pop()
num2 = num_stack.pop()
num1 = num_stack.pop()
num_stack.append(calculate(num1, num2, op))
result = str(num_stack[0])
# 去掉无效的0和小数点,例:1.0转换为1
if result[len(result) - 1] == '0' and result[len(result) - 2] == '.':
result = result[0:-2]
return result
if __name__ == '__main__':
#formula = "2 * ( 3 - 5 * ( - 6 + 3 * 2 / 2 ) )"
formula = "e"
formula_list = formula_format(formula)
result = final_calc(formula_list)
print("算式:", formula)
print("计算结果:", result)
from tkinter import *
from functools import partial
#partial() 函数允许你给一个或多个参数设置固定的值,减少接下来被调用时的参数个数。
from tkinter import *
# 生成计算器主界面
def buju(root):
menu = Menu(root) # 创建主菜单
#新建一个空的菜单,将原menu菜单的menu属性指定为submune1,即filemenu1为menu的下拉菜单
#tearoff属性:通常情况下,菜单可以被撕掉,第一个位置(位置0)在选择列表中被删除元素占据
# 并且额外的选择从位置1开始。
# 如果设置了tearoff=0,菜单将不会有一个tearoff特性,并且选择将从位置0开始添加。
submenu1 = Menu(menu, tearoff=0) # 分窗,0为在原窗,1为点击分为两个窗口
#add_cascade()方法:通过将给定的菜单与父菜单相关联,创建一个新的分层菜单。
menu.add_cascade(label='编辑', menu=submenu1)# 添加子选项(label参数为显示内容)
#add_command (options)方法:将菜单项添加到菜单中。
submenu1.add_command(
#创建了一个名为“XX”的标签,按下后执行bianji/编辑函数,
label='复制', command=lambda: bianji(entry, 'copy')) # 添加命令
submenu1.add_command(label='剪切', command=lambda: bianji(entry, 'cut'))
submenu1.add_command(label='粘贴', command=lambda: bianji(entry, 'paste'))
submenu2 = Menu(menu, tearoff=0)
menu.add_cascade(label='查看', menu=submenu2)
submenu2.add_command(label='帮助', command=lambda: chakan(entry, 'help'))
submenu2.add_command(label='作者', command=lambda: chakan(entry, 'author'))
root.config(menu=menu)# 重新配置,添加菜单
label = Label(root, width=36, height=1, bd=5, bg='white', anchor='se',
textvariable=label_text) # 标签,可以显示文字或图片
label.grid(row=0, columnspan=5) # 布局器,向窗口注册并显示控件
#rowspan:设置单元格纵向跨越的列数
#Entry(根对象, [属性列表]),实现添加输入框,width设置显示宽度
#bd设置按钮的边框大小,bg设置背景色,front设置字体及大小
#justify设置多行文本的对其方式
entry = Entry(root, width=23, bd=5, bg='white',
justify="right", font=('微软雅黑', 12)) # 文本框(单行)
entry.grid(row=1, column=0, columnspan=5, sticky=N + W +
S + E, padx=5, pady=5) # 设置控件周围x、y方向空白区域保留大小
#cursor为鼠标悬停光标
myButton = partial(Button, root, width=5, cursor='hand2', activebackground='#90EE90') # 偏函数:带有固定参数的函数
button_sin = myButton(text='sin', command=lambda: get_input(entry, 'sin(')) # 按钮
button_arcsin = myButton(text='arcsin', command=lambda: get_input(entry, 'arcsin('))
button_exp = myButton(text='e', command=lambda: get_input(entry, 'e'))
button_ln = myButton(text='ln', command=lambda: get_input(entry, 'ln('))
button_xy = myButton(text='x^y', command=lambda: get_input(entry, '^'))
button_sin.grid(row=2, column=0)
button_arcsin.grid(row=2, column=1)
button_exp.grid(row=2, column=2)
button_ln.grid(row=2, column=3)
button_xy.grid(row=2, column=4)
button_shanyige = myButton(text='←', command=lambda: backspace(entry)) # command指定按钮消息的回调函数
button_shanquanbu = myButton(text=' C ', command=lambda: clear(entry))
button_zuokuohao = myButton(text='(', command=lambda: get_input(entry, '('))
button_youkuohao = myButton(text=')', command=lambda: get_input(entry, ')'))
button_genhao = myButton(text='√x', command=lambda: get_input(entry, '√('))
button_shanyige.grid(row=3, column=0)
button_shanquanbu.grid(row=3, column=1)
button_zuokuohao.grid(row=3, column=2)
button_youkuohao.grid(row=3, column=3)
button_genhao.grid(row=3, column=4)
button_7 = myButton(text=' 7 ', command=lambda: get_input(entry, '7'))
button_8 = myButton(text=' 8 ', command=lambda: get_input(entry, '8'))
button_9 = myButton(text=' 9 ', command=lambda: get_input(entry, '9'))
button_chu = myButton(text=' / ', command=lambda: get_input(entry, '/'))
button_yu = myButton(text='%', command=lambda: get_input(entry, '%'))
button_7.grid(row=4, column=0)
button_8.grid(row=4, column=1)
button_9.grid(row=4, column=2)
button_chu.grid(row=4, column=3)
button_yu.grid(row=4, column=4)
button_4 = myButton(text=' 4 ', command=lambda: get_input(entry, '4'))
button_5 = myButton(text=' 5 ', command=lambda: get_input(entry, '5'))
button_6 = myButton(text=' 6 ', command=lambda: get_input(entry, '6'))
button_cheng = myButton(text=' * ', command=lambda: get_input(entry, '*'))
button_jiecheng = myButton(text='二进制', command=lambda: jinzhi(entry))
button_4.grid(row=5, column=0)
button_5.grid(row=5, column=1)
button_6.grid(row=5, column=2)
button_cheng.grid(row=5, column=3)
button_jiecheng.grid(row=5, column=4)
button_1 = myButton(text=' 1 ', command=lambda: get_input(entry, '1'))
button_2 = myButton(text=' 2 ', command=lambda: get_input(entry, '2'))
button_3 = myButton(text=' 3 ', command=lambda: get_input(entry, '3'))
button_jian = myButton(text=' - ', command=lambda: get_input(entry, '-'))
button_dengyu = myButton(text=' \n = \n ', command=lambda: calculator(entry))
button_1.grid(row=6, column=0)
button_2.grid(row=6, column=1)
button_3.grid(row=6, column=2)
button_jian.grid(row=6, column=3)
button_dengyu.grid(row=6, column=4, rowspan=2) # rowspan:设置单元格横向跨越的行数
button_pai = myButton(text=' π ', command=lambda: get_input(entry, 'π'))
button_0 = myButton(text=' 0 ', command=lambda: get_input(entry, '0'))
button_xiaoshudian = myButton(text=' . ', command=lambda: get_input(entry, '.'))
button_jia = myButton(text=' + ', command=lambda: get_input(entry, '+'))
button_pai.grid(row=7, column=0)
button_0.grid(row=7, column=1)
button_xiaoshudian.grid(row=7, column=2)
button_jia.grid(row=7, column=3)
# 对文本框中的算式或答案进行复制、剪切或粘贴
def bianji(entry, argu):
"""
:param entry: 文本框
:param argu: 按钮对应的值
"""
if argu == 'copy':
entry.event_generate("<<Copy>>")
elif argu == 'cut':
entry.event_generate("<<Cut>>")
clear(entry)
elif argu == 'paste':
entry.event_generate("<<Paste>>")
# 查看使用帮助和作者信息
def chakan(entry, argu):
root = Tk()
root.resizable(0, 0)
text = Text(root, width=20, height=2, bd=5, bg='#FFFACD', font=('微软雅黑', 12))
text.grid(padx=5, pady=5)
if argu == 'help':
root.title('帮助')
text.insert(INSERT, '哈你的希望落空了吧\n')
text.insert(INSERT, '这里可没有帮助')
elif argu == 'author':
root.title('作者')
text.insert(INSERT, 'Author:许许\n')
text.insert(INSERT, 'Time:2022.06.17')
# 删除最后一次输入内容
def backspace(entry):
entry.delete(len(entry.get()) - 1) # 删除文本框的最后一个输入值
# 删除所有输入内容和显示内容
def clear(entry):
entry.delete(0, END) # 删除文本框的所有内容
label_text.set('')
# 点击计算器输入按钮后向文本框中添加内容
def get_input(entry, argu):
formula = entry.get()
for char in formula:
if '\u4e00' <= char <= '\u9fa5':
clear(entry) # 删除文本框中的汉字显示,减少手动删除操作
entry.insert(INSERT, argu) # 使用END时,键盘敲入和按键输入组合操作会出错
# 十进制整数转换为二进制整数
def jinzhi(entry):
try:
formula = entry.get()
if re.match('\d+$', formula):
number = int(formula)
cunchu = [] # 放置每次除以2后的余数
result = ''
while number:
cunchu.append(number % 2)
number //= 2 # 整数除法,返回商
while cunchu:
result += str(cunchu.pop()) # 将所有余数倒置得到结果
clear(entry)
entry.insert(END, result)
label_text.set(''.join(formula + '='))
else:
clear(entry)
entry.insert(END, '请输入十进制整数')
except:
clear(entry)
entry.insert(END, '出错')
# 点击“=”后进行计算
def calculator(entry):
try:
formula = entry.get()
# 输入内容只是数字或π或e时,仍显示该内容
if re.match('-?[\d+,π,e]\.?\d*$', formula):
label_text.set(''.join(formula + '='))
return
# 输入内容是算式时,显示其计算结果
result = final_calc(formula_format(formula))
clear(entry)
entry.insert(END, result) # 将结果输出到文本框中
label_text.set(''.join(formula + '='))
except:
clear(entry)
entry.insert(END, '出错')
if __name__ == '__main__':
root = Tk() # 生成窗口
root.title('简易计算器') # 窗口的名字
root.resizable(0, 0) # 窗口大小可调性,分别表示x,y方向的可变性
global label_text # 定义全局变量
label_text = StringVar()
buju(root)
root.mainloop() # 进入消息循环(必需组件),否则生成的窗口一闪而过
实现一个具有可视化界面的多功能计算器(升级版)
项目基本信息
项目具体要求详细 | https://bbs.csdn.net/topics/617294583 |
最终目标 | 完成一个具有可视化界面的科学计算器 |
Jupyter Notebook 展示:
(简易模式)
(科学计算器模式)
视频展示:
实现一个具有可视化界面的多功能计算器(升级版)
完整源代码:
import tkinter
import tkinter.font
import math
class scienceCalculator(object):
def __init__(self):
self.root = tkinter.Tk()
self.all_press_lists = [] # 保存运算数字和符号的列表
self.is_press_compute = False # 判断是否按下运算按钮,默认没有按下
self.result = tkinter.StringVar() # 显示输入的数字及结果
self.record = tkinter.StringVar() # 显示计算过程
def main(self):
self.root.minsize(400, 690) # 显示框的最小长宽
self.root.title('科学计算器') # 标题
#self.root.iconbitmap("./calc.ico") # 左上角图标
input_bg, num_fg, btn_fg, btn_background = "#f8f8f8", "#000011", "#000011", "#ffffff" # 各种颜色
btn_w, btn_h = 80, 70 # 按钮的长宽
my_font = tkinter.font.Font(family='微软雅黑', size=20) # 设置字体
self.result.set(0)
self.record.set('')
# 显示版
label = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=num_fg, anchor='se',
textvariable=self.record)
label.place(width=400, height=120)
label2 = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=num_fg, anchor='se',
textvariable=self.result)
label2.place(y=120, width=400, height=80)
btn_change=tkinter.Button(self.root, text='切 换', font=tkinter.font.Font(family='微软雅黑', size=20), bg=btn_background, fg="#49506c", bd=0,
command=lambda: self.press_change())
btn_change.place(x=btn_w * 0, y=0, width=btn_w, height=btn_h/2)
# 第一行
btn_ce = tkinter.Button(self.root, text='CE', font=my_font, bg='#cdeeef', fg=btn_fg, bd=0,
command=lambda: self.press_ac('CE'))
btn_ce.place(x=btn_w * 0, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_ac = tkinter.Button(self.root, text='C', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_ac('C'))
btn_ac.place(x=btn_w * 1, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_back = tkinter.Button(self.root, text='Back', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_back('b'))
btn_per = tkinter.Button(self.root, text='%', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('%'))
btn_back.place(x=btn_w * 2, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_divi = tkinter.Button(self.root, text='÷', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('/'))
btn_per.place(x=btn_w * 3, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_divi.place(x=btn_w * 4, y=200 + btn_h * 0, width=btn_w, height=btn_h)
# 第二行
btn_asin=tkinter.Button(self.root, text='asin', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('asin'))
btn_acos= tkinter.Button(self.root, text='acos', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('acos'))
btn_atan= tkinter.Button(self.root, text='atan', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('atan'))
btn_log2=tkinter.Button(self.root, text='log2', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('log2'))
btn_e=tkinter.Button(self.root, text='e', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('e'))
btn_asin.place(x=btn_w * 0, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_acos.place(x=btn_w * 1, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_atan.place(x=btn_w * 2, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_log2.place(x=btn_w * 3, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_e.place(x=btn_w * 4, y=200 + btn_h * 1, width=btn_w, height=btn_h)
#第三行
btn_sin=tkinter.Button(self.root, text='sin', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('sin'))
btnl= tkinter.Button(self.root, text='(', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('('))
btnr= tkinter.Button(self.root, text=')', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num(')'))
btn_mi=tkinter.Button(self.root, text='^', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('^'))
btn_sqrt=tkinter.Button(self.root, text='√', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('√'))
btn_sin.place(x=btn_w * 0, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btnl.place(x=btn_w * 1, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btnr.place(x=btn_w * 2, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn_mi.place(x=btn_w * 3, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn_sqrt.place(x=btn_w * 4, y=200 + btn_h * 2, width=btn_w, height=btn_h)
# 第三行
btn_cos= tkinter.Button(self.root, text='cos', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('cos'))
btn_cos.place(x=btn_w * 0, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn7 = tkinter.Button(self.root, text='7', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('7'))
btn7.place(x=btn_w * 1, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn8 = tkinter.Button(self.root, text='8', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('8'))
btn8.place(x=btn_w * 2, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn9 = tkinter.Button(self.root, text='9', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('9'))
btn9.place(x=btn_w * 3, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn_mul = tkinter.Button(self.root, text='×', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('*'))
btn_mul.place(x=btn_w * 4, y=200 + btn_h * 3, width=btn_w, height=btn_h)
# 第四行
btn_tan = tkinter.Button(self.root, text='tan', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('tan'))
btn_tan.place(x=btn_w * 0, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn4 = tkinter.Button(self.root, text='4', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('4'))
btn4.place(x=btn_w * 1, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn5 = tkinter.Button(self.root, text='5', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('5'))
btn5.place(x=btn_w * 2, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn6 = tkinter.Button(self.root, text='6', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('6'))
btn6.place(x=btn_w * 3, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn_sub = tkinter.Button(self.root, text='-', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('-'))
btn_sub.place(x=btn_w * 4, y=200 + btn_h * 4, width=btn_w, height=btn_h)
# 第五行
btn_log = tkinter.Button(self.root, text='ln', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('ln'))
btn_log.place(x=btn_w * 0, y=200 + btn_h * 5, width=btn_w, height=btn_h)
btn1 = tkinter.Button(self.root, text='1', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('1'))
btn1.place(x=btn_w * 1, y=200 + btn_h * 5, width=btn_w, height=btn_h)
btn2 = tkinter.Button(self.root, text='2', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('2'))
btn2.place(x=btn_w * 2, y=200 + btn_h * 5, width=btn_w, height=btn_h)
btn3 = tkinter.Button(self.root, text='3', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('3'))
btn3.place(x=btn_w * 3, y=200 + btn_h * 5, width=btn_w, height=btn_h)
btn_add = tkinter.Button(self.root, text='+', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('+'))
btn_add.place(x=btn_w * 4, y=200 + btn_h * 5, width=btn_w, height=btn_h)
# 第六行
btn_ln = tkinter.Button(self.root, text='lg', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('lg'))
btn_ln.place(x=btn_w * 0, y=200 + btn_h * 6, width=btn_w , height=btn_h)
btn_pai = tkinter.Button(self.root, text='π', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('π'))
btn_pai.place(x=btn_w * 1, y=200 + btn_h * 6, width=btn_w , height=btn_h)
btn0 = tkinter.Button(self.root, text='0', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('0'))
btn0.place(x=btn_w * 2, y=200 + btn_h * 6, width=btn_w , height=btn_h)
btn_point = tkinter.Button(self.root, text='.', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('.'))
btn_point.place(x=btn_w * 3, y=200 + btn_h * 6, width=btn_w, height=btn_h)
btn_equ = tkinter.Button(self.root, text='=', bg='#00bbbe', font=my_font, fg=num_fg, bd=0,
command=lambda: self.press_equal())
btn_equ.place(x=btn_w * 4, y=200 + btn_h * 6, width=btn_w, height=btn_h)
self.root.mainloop()
#按下change
def press_change(self):
self.root.destroy()
my_calculator = Calculator()
my_calculator.main()
# 按下数字
def press_num(self, num):
if self.is_press_compute is True: # 如果判断等号按键被按下
self.record.set("")
self.result.set(0) # 清空self.result
self.is_press_compute = False
# 判断界面的数字是否为0
old_num = self.result.get()
new_num=[]
if old_num == '0' and num != '.':
new_num=num
else:
new_num = old_num+num
#判断特殊的符号
if num == '^':
num='**'
elif num == '√':
num='math.sqrt('
new_num+='('
elif num == 'sin':
num='math.sin('
new_num+='('
elif num == 'cos':
num='math.cos('
new_num+='('
elif num == 'tan':
num='math.tan('
new_num+='('
elif num == 'lg':
num='math.log10('
new_num+='('
elif num == 'ln':
num='math.log('
new_num+='('
elif num == 'π':
num='math.pi'
elif num == 'asin':
num='math.asin('
new_num+='('
elif num == 'acos':
num='math.acos('
new_num+='('
elif num == 'atan':
num='math.atan('
new_num+='('
elif num == 'e':
num='math.e'
elif num == 'log2':
num='math.log2('
new_num+='('
self.result.set(new_num)
temp=self.all_press_lists
temp+=num
self.all_press_lists=temp
#按下AC
def press_ac(self,sign):
self.all_press_lists.clear()
self.record.set("")
self.result.set(0)
#按下back
def press_back(self, sign):
num=self.result.get()
a = num[0:-1]
self.result.set(a)
num=self.all_press_lists
if len(num)>5 and num[-2] == '.' and num[-3] == 'h' and num[-4] == 't':
a = num[:-6]
self.all_press_lists=a
elif len(num)>3 and num[-1] == 'i' and num[-2] == 'p':
a = num[:-7]
self.all_press_lists=a
elif len(num)>1 and num[-1] == '*' and num[-2] == '*':
a = num[:-2]
self.all_press_lists=a
elif len(num)>8 and num[-1] == 't' and num[-2] == 'r':
a = num[:-9]
self.all_press_lists=a
elif len(num)>8 and num[-1] == '1' and num[-2] =='g' and num[-3] == 'o' and num[-4] == 'l':
a = num[:-9]
self.all_press_lists=a
elif len(num)>7 and num[-1] == 'g' and num[-2] =='o' and num[-3] == 'l' and num[-4] == '.':
a = num[:-8]
self.all_press_lists=a
elif len(num)>6 and num[-1] == 'o' and num[-2] =='l' and num[-3] == '.' and num[-4] == 'h':
a = num[:-7]
self.all_press_lists=a
else:
a = num[0:-1]
self.all_press_lists=a
# 获取运算结果
def press_equal(self):
temp=self.result.get()
compute_str = ''.join(self.all_press_lists)
try:
calculate_result = eval(compute_str)
except:
calculate_result = 'error'
self.result.set(calculate_result) # 显示结果
self.record.set(temp + "=") # 显示运算过程
self.all_press_lists.clear() # 清空列表内容
self.is_press_compute = True
class Calculator:
def __init__(self):
self.root = tkinter.Tk()
self.all_press_lists = [] # 保存运算数字和符号的列表
self.is_press_compute = False # 判断是否按下运算按钮,默认没有按下
self.result = tkinter.StringVar() # 显示输入的数字及结果
self.record = tkinter.StringVar() # 显示计算过程
def main(self):
self.root.minsize(375, 620) # 显示框的最小长宽
self.root.title('标准计算器') # 标题
btn_w, btn_h = 93.75, 84 #按钮宽和高
my_font = tkinter.font.Font(family='微软雅黑', size=20) # 设置字体
self.result.set(0)
self.record.set('')
input_bg, btn_fg, btn_bg = "#f8f8f8", "#000011", "#ffffff" # 设定颜色
# displayscreen
label = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=btn_fg, anchor='se',
textvariable=self.record)
label.place(width=375, height=120)
label2 = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=btn_fg, anchor='se',
textvariable=self.result)
label2.place(y=120, width=375, height=80)
btn_change=tkinter.Button(self.root, text='切 换', font=tkinter.font.Font(family='微软雅黑', size=20), bg=btn_bg, fg="#49506c", bd=0,
command=lambda: self.press_change())
btn_change.place(x=btn_w * 0, y=0, width=btn_w, height=btn_h/2)
# 第一行
btn_ac = tkinter.Button(self.root, text='c', font=my_font, bg="#cdeeef", fg=btn_fg, bd=0,
command=lambda: self.press_ac('AC'))
btn_ac.place(x=btn_w * 0, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_back = tkinter.Button(self.root, text='Back', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_back('b'))
btn_back.place(x=btn_w * 1, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_per = tkinter.Button(self.root, text='%', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('%'))
btn_per.place(x=btn_w * 2, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_divi = tkinter.Button(self.root, text='÷', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('/'))
btn_divi.place(x=btn_w * 3, y=200 + btn_h * 0, width=btn_w, height=btn_h)
# 第二行
btn7 = tkinter.Button(self.root, text='7', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('7'))
btn7.place(x=btn_w * 0, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn8 = tkinter.Button(self.root, text='8', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('8'))
btn8.place(x=btn_w * 1, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn9 = tkinter.Button(self.root, text='9', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('9'))
btn9.place(x=btn_w * 2, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_mul = tkinter.Button(self.root, text='×', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('*'))
btn_mul.place(x=btn_w * 3, y=200 + btn_h * 1, width=btn_w, height=btn_h)
# 第三行
btn4 = tkinter.Button(self.root, text='4', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('4'))
btn4.place(x=btn_w * 0, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn5 = tkinter.Button(self.root, text='5', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('5'))
btn5.place(x=btn_w * 1, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn6 = tkinter.Button(self.root, text='6', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('6'))
btn6.place(x=btn_w * 2, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn_sub = tkinter.Button(self.root, text='-', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('-'))
btn_sub.place(x=btn_w * 3, y=200 + btn_h * 2, width=btn_w, height=btn_h)
# 第四行
btn1 = tkinter.Button(self.root, text='1', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('1'))
btn1.place(x=btn_w * 0, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn2 = tkinter.Button(self.root, text='2', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('2'))
btn2.place(x=btn_w * 1, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn3 = tkinter.Button(self.root, text='3', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('3'))
btn3.place(x=btn_w * 2, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn_add = tkinter.Button(self.root, text='+', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('+'))
btn_add.place(x=btn_w * 3, y=200 + btn_h * 3, width=btn_w, height=btn_h)
# 第五行
btn_pai=tkinter.Button(self.root, text='π', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('π'))
btn_pai.place(x=btn_w * 0, y=200 + btn_h * 4, width=btn_w , height=btn_h)
btn0 = tkinter.Button(self.root, text='0', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('0'))
btn0.place(x=btn_w * 1, y=200 + btn_h * 4, width=btn_w , height=btn_h)
btn_point = tkinter.Button(self.root, text='.', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('.'))
btn_point.place(x=btn_w * 2, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn_equ = tkinter.Button(self.root, text='=', bg='#00bbbe', font=my_font, fg=btn_fg, bd=0,
command=lambda: self.press_equal())
btn_equ.place(x=btn_w * 3, y=200 + btn_h * 4, width=btn_w, height=btn_h)
self.root.mainloop()
def press_change(self):
self.root.destroy()
my_calculator = scienceCalculator()
my_calculator.main()
# 按下数字
def press_num(self, num):
if self.is_press_compute is True: # 如果判断等号按键被按下
self.record.set("")
self.result.set(0) # 清空self.result
self.is_press_compute = False
# 判断界面的数字是否为0
old_num = self.result.get()
new_num=[]
if old_num == '0' and num != '.':
new_num=num
else:
new_num = old_num+num
#判断特殊的符号
if num == '^':
num='**'
elif num == '√':
num='math.sqrt('
new_num+='('
elif num == 'sin':
num='math.sin('
new_num+='('
elif num == 'cos':
num='math.cos('
new_num+='('
elif num == 'tan':
num='math.tan('
new_num+='('
elif num == 'lg':
num='math.log10('
new_num+='('
elif num == 'ln':
num='math.log('
new_num+='('
elif num == 'π':
num='math.pi'
elif num == 'asin':
num='math.asin('
new_num+='('
elif num == 'acos':
num='math.acos('
new_num+='('
elif num == 'atan':
num='math.atan('
new_num+='('
elif num == 'e':
num='math.e'
elif num == 'log2':
num='math.log2('
new_num+='('
self.result.set(new_num)
temp=self.all_press_lists
temp+=num
self.all_press_lists=temp
#按下AC
def press_ac(self,sign):
self.all_press_lists.clear()
self.record.set("")
self.result.set(0)
# 按下back
def press_back(self, sign):
num=self.result.get()
a = num[0:-1]
self.result.set(a)
num=self.all_press_lists
if len(num)>5 and num[-2] == '.' and num[-3] == 'h' and num[-4] == 't':
a = num[:-6]
self.all_press_lists=a
elif len(num)>3 and num[-1] == 'i' and num[-2] == 'p':
a = num[:-7]
self.all_press_lists=a
elif len(num)>1 and num[-1] == '*' and num[-2] == '*':
a = num[:-2]
self.all_press_lists=a
elif len(num)>8 and num[-1] == 't' and num[-2] == 'r':
a = num[:-9]
self.all_press_lists=a
elif len(num)>8 and num[-1] == '1' and num[-2] =='g' and num[-3] == 'o' and num[-4] == 'l':
a = num[:-9]
self.all_press_lists=a
elif len(num)>7 and num[-1] == 'g' and num[-2] =='o' and num[-3] == 'l' and num[-4] == '.':
a = num[:-8]
self.all_press_lists=a
elif len(num)>6 and num[-1] == 'o' and num[-2] =='l' and num[-3] == '.' and num[-4] == 'h':
a = num[:-7]
self.all_press_lists=a
else:
a = num[0:-1]
self.all_press_lists=a
# 获取运算结果
def press_equal(self):
temp=self.result.get()
compute_str = ''.join(self.all_press_lists)
try:
calculate_result = eval(compute_str)
except:
calculate_result = 'error'
self.result.set(calculate_result) # 显示结果
self.record.set(temp + "=") # 显示运算过程
self.all_press_lists.clear() # 清空列表内容
self.is_press_compute = True
if __name__ == '__main__':
my_calculator = Calculator()
my_calculator.main()
1. PSP表格
PSP是卡耐基梅隆大学(CMU)的专家们针对软件工程师所提出的一套模型:Personal Software Process (PSP, 个人开发流程,或称个体软件过程)。
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
• Estimate | • 估计这个任务需要多少时间 | ||
Development | 开发 | ||
• Analysis | • 需求分析 (包括学习新技术) | ||
• Design Spec | • 生成设计文档 | ||
• Design Review | • 设计复审 | ||
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | ||
• Design | • 具体设计 | ||
• Coding | • 具体编码 | ||
• Code Review | • 代码复审 | ||
• Test | • 测试(自我测试,修改代码,提交修改) | ||
Reporting | 报告 | ||
• Test Repor | • 测试报告 | ||
• Size Measurement | • 计算工作量 | ||
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | ||
合计 |
PSP的目的是:记录工程师如何实现需求的效率,和我们使用项目管理工具(例如微软的Project Professional,或者禅道等)进行项目进度规划类似。
解题思路描述
本来想用html+css+js做一个微信小程序,但是发现微信小程序把eval函数给禁了,手搓运算的代码又来不及,于是改用python。
问题一、界面设计
借助python的tkinter库可实现GUI设计
问题二、不同功能的切换
在界面部分,每当按下"切换"键,便可以实现在标准计算器和科学计算器间来回切换。
问题三、科学计算器运算的实现
主要是利用python的eval()函数来进行各种运算。定义三个字符串,一个用于存放需要eval()运算的表达式,一个用来作为按下等号后显示出来的算式,还有一个用来当作运算的结果。每当按下按钮时,按钮会传递相应的参数给运算函数,并相应的放入对应的字符串中。需要注意的是当使用科学计算器时,对于三角函数、幂、开方、反三角函数、对数等这些特殊运算需要套一个if来进行特判,以保证放入eval()中的字符串正确。
def press_num(self, num):
if self.is_press_compute is True: # 如果判断等号按键被按下
self.record.set("")
self.result.set(0) # 清空self.result
self.is_press_compute = False
# 判断界面的数字是否为0
old_num = self.result.get()
new_num=[]
if old_num == '0' and num != '.':
new_num=num
else:
new_num = old_num+num
#判断特殊的符号
if num == '^':
num='**'
elif num == '√':
num='math.sqrt('
new_num+='('
elif num == 'sin':
num='math.sin('
new_num+='('
elif num == 'cos':
num='math.cos('
new_num+='('
elif num == 'tan':
num='math.tan('
new_num+='('
elif num == 'lg':
num='math.log10('
new_num+='('
elif num == 'ln':
num='math.log('
new_num+='('
elif num == 'π':
num='math.pi'
elif num == 'asin':
num='math.asin('
new_num+='('
elif num == 'acos':
num='math.acos('
new_num+='('
elif num == 'atan':
num='math.atan('
new_num+='('
elif num == 'e':
num='math.e'
elif num == 'log2':
num='math.log2('
new_num+='('
self.result.set(new_num)
temp=self.all_press_lists
temp+=num
self.all_press_lists=temp
def press_equal(self):
temp=self.result.get()
compute_str = ''.join(self.all_press_lists)
try:
calculate_result = eval(compute_str)
except:
calculate_result = 'error'
self.result.set(calculate_result) # 显示结果
self.record.set(temp + "=") # 显示运算过程
self.all_press_lists.clear() # 清空列表内容
self.is_press_compute = True
问题四、标准计算器的实现
科学计算器的函数能够完美适配标准计算器的运算函数,因此,当需要用标准计算器进行运算时,可以直接调用科学计算器的函数。
问题五、Back删除函数的实现
在使用删除操作时,需要注意的是由于放入eval的字符串和展示给用户的字符串是不同的,可能出现显示给用户的是e而eval中的字符串是math.e,当用户删除e之后eval的字符串变为math.而导致计算出错。所以需要对特殊字符进行特判。
#按下back
def press_back(self, sign):
num=self.result.get()
a = num[0:-1]
self.result.set(a)
num=self.all_press_lists
if len(num)>5 and num[-2] == '.' and num[-3] == 'h' and num[-4] == 't':
a = num[:-6]
self.all_press_lists=a
elif len(num)>3 and num[-1] == 'i' and num[-2] == 'p':
a = num[:-7]
self.all_press_lists=a
elif len(num)>1 and num[-1] == '*' and num[-2] == '*':
a = num[:-2]
self.all_press_lists=a
elif len(num)>8 and num[-1] == 't' and num[-2] == 'r':
a = num[:-9]
self.all_press_lists=a
elif len(num)>8 and num[-1] == '1' and num[-2] =='g' and num[-3] == 'o' and num[-4] == 'l':
a = num[:-9]
self.all_press_lists=a
elif len(num)>7 and num[-1] == 'g' and num[-2] =='o' and num[-3] == 'l' and num[-4] == '.':
a = num[:-8]
self.all_press_lists=a
elif len(num)>6 and num[-1] == 'o' and num[-2] =='l' and num[-3] == '.' and num[-4] == 'h':
a = num[:-7]
self.all_press_lists=a
else:
a = num[0:-1]
self.all_press_lists=a
接口设计和实现过程
定义了两个类
Calculator类用于实现标准计算器
scienceCalculator类用于实现科学计算器
不同计算器间的跳转
放一个按钮"切换",当按下这个按钮时,便触发函数press_change实现跳转。
跳转到Calculator:
def press_change(self):
self.root.destroy()
my_calculator = Calculator()
my_calculator.main()
跳转到scienceCalculator:
def press_change(self):
self.root.destroy()
my_calculator = scienceCalculator()
my_calculator.main()
界面设计
标准计算器:
界面:
def main(self):
self.root.minsize(375, 620) # 显示框的最小长宽
self.root.title('标准计算器') # 标题
btn_w, btn_h = 93.75, 84 #按钮宽和高
my_font = tkinter.font.Font(family='微软雅黑', size=20) # 设置字体
self.result.set(0)
self.record.set('')
input_bg, btn_fg, btn_bg = "#f8f8f8", "#000011", "#ffffff" # 设定颜色
# displayscreen
label = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=btn_fg, anchor='se',
textvariable=self.record)
label.place(width=375, height=120)
label2 = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=btn_fg, anchor='se',
textvariable=self.result)
label2.place(y=120, width=375, height=80)
btn_change=tkinter.Button(self.root, text='切 换', font=tkinter.font.Font(family='微软雅黑', size=20), bg=btn_bg, fg="#49506c", bd=0,
command=lambda: self.press_change())
btn_change.place(x=btn_w * 0, y=0, width=btn_w, height=btn_h/2)
# 第一行
btn_ac = tkinter.Button(self.root, text='c', font=my_font, bg="#cdeeef", fg=btn_fg, bd=0,
command=lambda: self.press_ac('AC'))
btn_ac.place(x=btn_w * 0, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_back = tkinter.Button(self.root, text='Back', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_back('b'))
btn_back.place(x=btn_w * 1, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_per = tkinter.Button(self.root, text='%', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('%'))
btn_per.place(x=btn_w * 2, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_divi = tkinter.Button(self.root, text='÷', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('/'))
btn_divi.place(x=btn_w * 3, y=200 + btn_h * 0, width=btn_w, height=btn_h)
# 第二行
btn7 = tkinter.Button(self.root, text='7', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('7'))
btn7.place(x=btn_w * 0, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn8 = tkinter.Button(self.root, text='8', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('8'))
btn8.place(x=btn_w * 1, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn9 = tkinter.Button(self.root, text='9', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('9'))
btn9.place(x=btn_w * 2, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_mul = tkinter.Button(self.root, text='×', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('*'))
btn_mul.place(x=btn_w * 3, y=200 + btn_h * 1, width=btn_w, height=btn_h)
# 第三行
btn4 = tkinter.Button(self.root, text='4', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('4'))
btn4.place(x=btn_w * 0, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn5 = tkinter.Button(self.root, text='5', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('5'))
btn5.place(x=btn_w * 1, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn6 = tkinter.Button(self.root, text='6', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('6'))
btn6.place(x=btn_w * 2, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn_sub = tkinter.Button(self.root, text='-', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('-'))
btn_sub.place(x=btn_w * 3, y=200 + btn_h * 2, width=btn_w, height=btn_h)
# 第四行
btn1 = tkinter.Button(self.root, text='1', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('1'))
btn1.place(x=btn_w * 0, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn2 = tkinter.Button(self.root, text='2', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('2'))
btn2.place(x=btn_w * 1, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn3 = tkinter.Button(self.root, text='3', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('3'))
btn3.place(x=btn_w * 2, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn_add = tkinter.Button(self.root, text='+', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('+'))
btn_add.place(x=btn_w * 3, y=200 + btn_h * 3, width=btn_w, height=btn_h)
# 第五行
btn_pai=tkinter.Button(self.root, text='π', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('π'))
btn_pai.place(x=btn_w * 0, y=200 + btn_h * 4, width=btn_w , height=btn_h)
btn0 = tkinter.Button(self.root, text='0', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('0'))
btn0.place(x=btn_w * 1, y=200 + btn_h * 4, width=btn_w , height=btn_h)
btn_point = tkinter.Button(self.root, text='.', font=my_font, bg=btn_bg, fg=btn_fg, bd=0,
command=lambda: self.press_num('.'))
btn_point.place(x=btn_w * 2, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn_equ = tkinter.Button(self.root, text='=', bg='#00bbbe', font=my_font, fg=btn_fg, bd=0,
command=lambda: self.press_equal())
btn_equ.place(x=btn_w * 3, y=200 + btn_h * 4, width=btn_w, height=btn_h)
self.root.mainloop()
科学计算器:
界面:
def main(self):
self.root.minsize(400, 690) # 显示框的最小长宽
self.root.title('科学计算器') # 标题
#self.root.iconbitmap("./calc.ico") # 左上角图标
input_bg, num_fg, btn_fg, btn_background = "#f8f8f8", "#000011", "#000011", "#ffffff" # 各种颜色
btn_w, btn_h = 80, 70 # 按钮的长宽
my_font = tkinter.font.Font(family='微软雅黑', size=20) # 设置字体
self.result.set(0)
self.record.set('')
# 显示版
label = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=num_fg, anchor='se',
textvariable=self.record)
label.place(width=375, height=120)
label2 = tkinter.Label(self.root, font=my_font, bg=input_bg, bd='9', fg=num_fg, anchor='se',
textvariable=self.result)
label2.place(y=120, width=375, height=80)
btn_change=tkinter.Button(self.root, text='切 换', font=tkinter.font.Font(family='微软雅黑', size=20), bg=btn_background, fg="#49506c", bd=0,
command=lambda: self.press_change())
btn_change.place(x=btn_w * 0, y=0, width=btn_w, height=btn_h/2)
# 第一行
btn_ce = tkinter.Button(self.root, text='CE', font=my_font, bg='#cdeeef', fg=btn_fg, bd=0,
command=lambda: self.press_ac('CE'))
btn_ce.place(x=btn_w * 0, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_ac = tkinter.Button(self.root, text='C', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_ac('C'))
btn_ac.place(x=btn_w * 1, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_back = tkinter.Button(self.root, text='Back', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_back('b'))
btn_per = tkinter.Button(self.root, text='%', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('%'))
btn_back.place(x=btn_w * 2, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_divi = tkinter.Button(self.root, text='÷', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('/'))
btn_per.place(x=btn_w * 3, y=200 + btn_h * 0, width=btn_w, height=btn_h)
btn_divi.place(x=btn_w * 4, y=200 + btn_h * 0, width=btn_w, height=btn_h)
# 第二行
btn_asin=tkinter.Button(self.root, text='asin', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('asin'))
btn_acos= tkinter.Button(self.root, text='acos', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('acos'))
btn_atan= tkinter.Button(self.root, text='atan', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('atan'))
btn_log2=tkinter.Button(self.root, text='log2', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('log2'))
btn_e=tkinter.Button(self.root, text='e', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('e'))
btn_asin.place(x=btn_w * 0, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_acos.place(x=btn_w * 1, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_atan.place(x=btn_w * 2, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_log2.place(x=btn_w * 3, y=200 + btn_h * 1, width=btn_w, height=btn_h)
btn_e.place(x=btn_w * 4, y=200 + btn_h * 1, width=btn_w, height=btn_h)
#第三行
btn_sin=tkinter.Button(self.root, text='sin', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('sin'))
btnl= tkinter.Button(self.root, text='(', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('('))
btnr= tkinter.Button(self.root, text=')', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num(')'))
btn_mi=tkinter.Button(self.root, text='^', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('^'))
btn_sqrt=tkinter.Button(self.root, text='√', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('√'))
btn_sin.place(x=btn_w * 0, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btnl.place(x=btn_w * 1, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btnr.place(x=btn_w * 2, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn_mi.place(x=btn_w * 3, y=200 + btn_h * 2, width=btn_w, height=btn_h)
btn_sqrt.place(x=btn_w * 4, y=200 + btn_h * 2, width=btn_w, height=btn_h)
# 第三行
btn_cos= tkinter.Button(self.root, text='cos', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('cos'))
btn_cos.place(x=btn_w * 0, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn7 = tkinter.Button(self.root, text='7', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('7'))
btn7.place(x=btn_w * 1, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn8 = tkinter.Button(self.root, text='8', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('8'))
btn8.place(x=btn_w * 2, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn9 = tkinter.Button(self.root, text='9', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('9'))
btn9.place(x=btn_w * 3, y=200 + btn_h * 3, width=btn_w, height=btn_h)
btn_mul = tkinter.Button(self.root, text='×', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('*'))
btn_mul.place(x=btn_w * 4, y=200 + btn_h * 3, width=btn_w, height=btn_h)
# 第四行
btn_tan = tkinter.Button(self.root, text='tan', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('tan'))
btn_tan.place(x=btn_w * 0, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn4 = tkinter.Button(self.root, text='4', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('4'))
btn4.place(x=btn_w * 1, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn5 = tkinter.Button(self.root, text='5', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('5'))
btn5.place(x=btn_w * 2, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn6 = tkinter.Button(self.root, text='6', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('6'))
btn6.place(x=btn_w * 3, y=200 + btn_h * 4, width=btn_w, height=btn_h)
btn_sub = tkinter.Button(self.root, text='-', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('-'))
btn_sub.place(x=btn_w * 4, y=200 + btn_h * 4, width=btn_w, height=btn_h)
# 第五行
btn_log = tkinter.Button(self.root, text='ln', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('ln'))
btn_log.place(x=btn_w * 0, y=200 + btn_h * 5, width=btn_w, height=btn_h)
btn1 = tkinter.Button(self.root, text='1', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('1'))
btn1.place(x=btn_w * 1, y=200 + btn_h * 5, width=btn_w, height=btn_h)
btn2 = tkinter.Button(self.root, text='2', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('2'))
btn2.place(x=btn_w * 2, y=200 + btn_h * 5, width=btn_w, height=btn_h)
btn3 = tkinter.Button(self.root, text='3', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('3'))
btn3.place(x=btn_w * 3, y=200 + btn_h * 5, width=btn_w, height=btn_h)
btn_add = tkinter.Button(self.root, text='+', font=my_font, bg=btn_background, fg=btn_fg, bd=0,
command=lambda: self.press_num('+'))
btn_add.place(x=btn_w * 4, y=200 + btn_h * 5, width=btn_w, height=btn_h)
# 第六行
btn_ln = tkinter.Button(self.root, text='lg', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('lg'))
btn_ln.place(x=btn_w * 0, y=200 + btn_h * 6, width=btn_w , height=btn_h)
btn_pai = tkinter.Button(self.root, text='π', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('π'))
btn_pai.place(x=btn_w * 1, y=200 + btn_h * 6, width=btn_w , height=btn_h)
btn0 = tkinter.Button(self.root, text='0', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('0'))
btn0.place(x=btn_w * 2, y=200 + btn_h * 6, width=btn_w , height=btn_h)
btn_point = tkinter.Button(self.root, text='.', font=my_font, bg=btn_background, fg=num_fg, bd=0,
command=lambda: self.press_num('.'))
btn_point.place(x=btn_w * 3, y=200 + btn_h * 6, width=btn_w, height=btn_h)
btn_equ = tkinter.Button(self.root, text='=', bg='#00bbbe', font=my_font, fg=num_fg, bd=0,
command=lambda: self.press_equal())
btn_equ.place(x=btn_w * 4, y=200 + btn_h * 6, width=btn_w, height=btn_h)
self.root.mainloop()
运算的实现
每次按下按钮,都会传递相应参数给运算函数,运算函数再将其加入对应的字符串中,最后按下等号后,再将需要运算的字符串放入eval中进行运算
def press_num(self, num):
if self.is_press_compute is True: # 如果判断等号按键被按下
self.record.set("")
self.result.set(0) # 清空self.result
self.is_press_compute = False
# 判断界面的数字是否为0
old_num = self.result.get()
new_num=[]
if old_num == '0' and num != '.':
new_num=num
else:
new_num = old_num+num
#判断特殊的符号
if num == '^':
num='**'
elif num == '√':
num='math.sqrt('
new_num+='('
elif num == 'sin':
num='math.sin('
new_num+='('
elif num == 'cos':
num='math.cos('
new_num+='('
elif num == 'tan':
num='math.tan('
new_num+='('
elif num == 'lg':
num='math.log10('
new_num+='('
elif num == 'ln':
num='math.log('
new_num+='('
elif num == 'π':
num='math.pi'
elif num == 'asin':
num='math.asin('
new_num+='('
elif num == 'acos':
num='math.acos('
new_num+='('
elif num == 'atan':
num='math.atan('
new_num+='('
elif num == 'e':
num='math.e'
elif num == 'log2':
num='math.log2('
new_num+='('
self.result.set(new_num)
temp=self.all_press_lists
temp+=num
self.all_press_lists=temp
def press_equal(self):
temp=self.result.get()
compute_str = ''.join(self.all_press_lists)
try:
calculate_result = eval(compute_str)
except:
calculate_result = 'error'
self.result.set(calculate_result) # 显示结果
self.record.set(temp + "=") # 显示运算过程
self.all_press_lists.clear() # 清空列表内容
self.is_press_compute = True
关键代码展示:
#按下change
def press_change(self):
self.root.destroy()
my_calculator = Calculator()
my_calculator.main()
# 按下数字
def press_num(self, num):
if self.is_press_compute is True: # 如果判断等号按键被按下
self.record.set("")
self.result.set(0) # 清空self.result
self.is_press_compute = False
# 判断界面的数字是否为0
old_num = self.result.get()
new_num=[]
if old_num == '0' and num != '.':
new_num=num
else:
new_num = old_num+num
#判断特殊的符号
if num == '^':
num='**'
elif num == '√':
num='math.sqrt('
new_num+='('
elif num == 'sin':
num='math.sin('
new_num+='('
elif num == 'cos':
num='math.cos('
new_num+='('
elif num == 'tan':
num='math.tan('
new_num+='('
elif num == 'lg':
num='math.log10('
new_num+='('
elif num == 'ln':
num='math.log('
new_num+='('
elif num == 'π':
num='math.pi'
elif num == 'asin':
num='math.asin('
new_num+='('
elif num == 'acos':
num='math.acos('
new_num+='('
elif num == 'atan':
num='math.atan('
new_num+='('
elif num == 'e':
num='math.e'
elif num == 'log2':
num='math.log2('
new_num+='('
self.result.set(new_num)
temp=self.all_press_lists
temp+=num
self.all_press_lists=temp
#按下AC
def press_ac(self,sign):
self.all_press_lists.clear()
self.record.set("")
self.result.set(0)
#按下back
def press_back(self, sign):
num=self.result.get()
a = num[0:-1]
self.result.set(a)
num=self.all_press_lists
if len(num)>5 and num[-2] == '.' and num[-3] == 'h' and num[-4] == 't':
a = num[:-6]
self.all_press_lists=a
elif len(num)>3 and num[-1] == 'i' and num[-2] == 'p':
a = num[:-7]
self.all_press_lists=a
elif len(num)>1 and num[-1] == '*' and num[-2] == '*':
a = num[:-2]
self.all_press_lists=a
elif len(num)>8 and num[-1] == 't' and num[-2] == 'r':
a = num[:-9]
self.all_press_lists=a
elif len(num)>8 and num[-1] == '1' and num[-2] =='g' and num[-3] == 'o' and num[-4] == 'l':
a = num[:-9]
self.all_press_lists=a
elif len(num)>7 and num[-1] == 'g' and num[-2] =='o' and num[-3] == 'l' and num[-4] == '.':
a = num[:-8]
self.all_press_lists=a
elif len(num)>6 and num[-1] == 'o' and num[-2] =='l' and num[-3] == '.' and num[-4] == 'h':
a = num[:-7]
self.all_press_lists=a
else:
a = num[0:-1]
self.all_press_lists=a
# 获取运算结果
def press_equal(self):
temp=self.result.get()
compute_str = ''.join(self.all_press_lists)
try:
calculate_result = eval(compute_str)
except:
calculate_result = 'error'
self.result.set(calculate_result) # 显示结果
self.record.set(temp + "=") # 显示运算过程
self.all_press_lists.clear() # 清空列表内容
self.is_press_compute = True
对应的删除操作Back也需要进行特判:
#按下back
def press_back(self, sign):
num=self.result.get()
a = num[0:-1]
self.result.set(a)
num=self.all_press_lists
if len(num)>5 and num[-2] == '.' and num[-3] == 'h' and num[-4] == 't':
a = num[:-6]
self.all_press_lists=a
elif len(num)>3 and num[-1] == 'i' and num[-2] == 'p':
a = num[:-7]
self.all_press_lists=a
elif len(num)>1 and num[-1] == '*' and num[-2] == '*':
a = num[:-2]
self.all_press_lists=a
elif len(num)>8 and num[-1] == 't' and num[-2] == 'r':
a = num[:-9]
self.all_press_lists=a
elif len(num)>8 and num[-1] == '1' and num[-2] =='g' and num[-3] == 'o' and num[-4] == 'l':
a = num[:-9]
self.all_press_lists=a
elif len(num)>7 and num[-1] == 'g' and num[-2] =='o' and num[-3] == 'l' and num[-4] == '.':
a = num[:-8]
self.all_press_lists=a
elif len(num)>6 and num[-1] == 'o' and num[-2] =='l' and num[-3] == '.' and num[-4] == 'h':
a = num[:-7]
self.all_press_lists=a
else:
a = num[0:-1]
self.all_press_lists=a
需要注意的是,如果有一个“大聪明”胡乱按计算器按钮,让计算器运算不合要求的式子,这时候我们就需要对错误式子输出"error"
try:
calculate_result = eval(compute_str)
except:
calculate_result = 'error'
单元测试
测试代码:
import unittest
from tkinter import Tk
from calc import Calculator
from calc import scienceCalculator
import math
class Test_test_1(unittest.TestCase):
#__ , 启动!
def setUp(self):
self.root = Tk()
self.Calculator = Calculator()
self.sciCalculator=scienceCalculator()
#关闭
def tearDown(self):
self.root.destroy()
#测试加
def test_add(self):
self.Calculator.press_num( '7')
self.Calculator.press_num( '+')
self.Calculator.press_num( '2')
self.Calculator.press_equal()
self.assertEqual(self.Calculator.result.get(), '9')
self.sciCalculator.press_num( '7')
self.sciCalculator.press_num( '+')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), '9')
#测试减
def test_sub(self):
self.Calculator.press_num( '7')
self.Calculator.press_num( '-')
self.Calculator.press_num( '2')
self.Calculator.press_equal()
self.assertEqual(self.Calculator.result.get(), '5')
self.sciCalculator.press_num( '7')
self.sciCalculator.press_num( '-')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), '5')
#测试乘
def test_mul(self):
self.Calculator.press_num( '7')
self.Calculator.press_num( '*')
self.Calculator.press_num( '2')
self.Calculator.press_equal()
self.assertEqual(self.Calculator.result.get(), '14')
self.sciCalculator.press_num( '7')
self.sciCalculator.press_num( '*')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), '14')
#测试除
def test_div(self):
self.Calculator.press_num( '7')
self.Calculator.press_num( '/')
self.Calculator.press_num( '2')
self.Calculator.press_equal()
self.assertEqual(self.Calculator.result.get(), '3.5')
self.sciCalculator.press_num( '7')
self.sciCalculator.press_num( '/')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), '3.5')
#测试mod
def test_mod(self):
self.Calculator.press_num( '7')
self.Calculator.press_num( '%')
self.Calculator.press_num( '2')
self.Calculator.press_equal()
self.assertEqual(self.Calculator.result.get(), '1')
self.sciCalculator.press_num( '7')
self.sciCalculator.press_num( '%')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), '1')
#测试AllClear
def test_ac(self):
self.Calculator.press_ac( 'C')
self.assertEqual(self.Calculator.result.get(), '0')
self.sciCalculator.press_ac( 'C')
self.assertEqual(self.sciCalculator.result.get(), '0')
#测试clear_entry
def test_ce(self):
self.Calculator.press_ac( 'CE')
self.assertEqual(self.Calculator.result.get(), '0')
self.sciCalculator.press_ac( 'CE')
self.assertEqual(self.sciCalculator.result.get(), '0')
#测试back
def test_back(self):
self.Calculator.press_num( '7')
self.Calculator.press_back( 'b')
self.assertEqual(self.Calculator.all_press_lists,[])
self.assertEqual(self.Calculator.result.get(),'')
self.sciCalculator.press_num( '7')
self.sciCalculator.press_back( 'b')
self.assertEqual(self.sciCalculator.all_press_lists,[])
self.assertEqual(self.sciCalculator.result.get(),'')
#测试根号
def test_genhao(self):
self.sciCalculator.press_num( '√')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.sqrt(2)")))
#测试幂
def test_cf(self):
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( '^')
self.sciCalculator.press_num( '3')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), '8')
#测试ln
def test_ln(self):
self.sciCalculator.press_num( 'ln')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.log(2)")))
#测试lg
def test_lg(self):
self.sciCalculator.press_num( 'lg')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.log10(2)")))
#测试log2
def test_log2(self):
self.sciCalculator.press_num( 'log2')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.log2(2)")))
#测试pai
def test_pai(self):
self.sciCalculator.press_num("π")
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.pi")))
#测试e
def test_e(self):
self.sciCalculator.press_num("e")
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.e")))
#测试sin
def test_sin(self):
self.sciCalculator.press_num( 'sin')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.sin(2)")))
#测试cos
def test_cos(self):
self.sciCalculator.press_num( 'cos')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.cos(2)")))
#测试tan
def test_tan(self):
self.sciCalculator.press_num( 'tan')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.tan(2)")))
#测试asin
def test_asin(self):
self.sciCalculator.press_num( 'sin')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.sin(2)")))
#测试acos
def test_acos(self):
self.sciCalculator.press_num( 'cos')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.cos(2)")))
#测试atan
def test_atan(self):
self.sciCalculator.press_num( 'tan')
self.sciCalculator.press_num( '2')
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), str(eval("math.tan(2)")))
#测试错误判断
def test_error(self):
self.sciCalculator.press_num( ')')
self.sciCalculator.press_equal()
self.assertEqual(self.sciCalculator.result.get(), "error")
self.Calculator.press_num( ')')
self.Calculator.press_equal()
self.assertEqual(self.Calculator.result.get(), "error")
if __name__ == '__main__':
unittest.main()
测试结果:
异常处理
对不符合规定的算式,直接输出error
def press_equal(self):
temp=self.result.get()
compute_str = ''.join(self.all_press_lists)
try:
calculate_result = eval(compute_str)
except:
calculate_result = 'error'
self.result.set(calculate_result) # 显示结果
self.record.set(temp + "=") # 显示运算过程
self.all_press_lists.clear() # 清空列表内容
self.is_press_compute = True
心得体会
在这次的Python高级语言程序设计课程中,小北虽然因为是第一次,也在很多地方磨了很多时间,但是总体还是收获颇丰。小北不仅学到了Python的很多语法Python的tkinter库的使用,还积累了一些前端界面的设计经验,并且加强了利用编程解决问题的能力!
同时,小北我也学会了Python的诸多工具的使用,学会了如何利用coverage测试代码覆盖率,学会了单元测试,以及利用Pyinstaller将Python文件做成.exe文件的方法等等...这真是依次酣畅淋漓的变成体验课哇~
失败结合品:实例1
原代码:
from tkinter import *
from math import pi
from math import e
import math
win=Tk()
win.title('计算器')
win.geometry('450x680')
ans=0.0
flag=0
falg=0
def er_yuan():
num=str(en.get())
for i in range(0,len(num)):
if (str.isdigit(num[i]) or num[i] == '.') == 0:
number=eval(num[0:i])
print(number)
en.delete(0,END)
if num[i]=='^':
en.insert(0,str(number**(eval(num[i+1:]))))
else:
en.insert(0,str(number*(10**eval(num[i+3:]))))
return
def numinput(number):
global flag
if (flag):
en.delete(0,END)
flag=0
first_num=en.get()
en.delete(0,END)
en.insert(0,str(first_num)+str(number))
def clear():
en.delete(0,END)
def delete_n():
en.delete(len(str(en.get()))-1,END)
def x_1():
num=str(en.get())
n=1
# if(num[-1]==')'):#如果想要整体做1/x可以使用加括号的方法
# en.delete(0,END)
# en.insert(0,str(1/eval(num[1:-2])))
# return
if(num[-1]==')'):
for i in range(len(num)-2,0,-1):
if(num[i]==')'):
n+=1
elif num[i]=='(':
n-=1
if(n==0):
en.delete(0,END)
# print(num[i+1:-2])
en.insert(0,num[0:i]+str(1/eval(num[i+1:-1])))
#注意切片也是满足左开右闭的情况,只有右侧不取数字时才有
# 可以得到从对应位置到最后的结果
return
for i in range(len(num)-1,0,-1):
if (str.isdigit(num[i]) or num[i]=='.')==0:
pp=float(num[i+1:])
if pp==0:
en.delete(0,END)
en.insert('error')
print('ok')
en.delete(0,END)
en.insert(0,num[0:i+1]+str(1/pp))
return
en.delete(0,END)
en.insert(0,str(1/float(num[0:])))
def mi_2():
num=str(en.get())
for i in range(len(num)-1,0,-1):#只需要读到第二个字符即可,因为如果第二个字符都不是字符
#则即使前面是字符也是属于单目符号(这里只有 自取负符号-)对结果无关紧要
if (str.isdigit(num[i]) or num[i]=='.')==0:
en.delete(0,END)
en.insert(0,num[0:i+1]+str(eval(num[i:])*eval(num[i:])))
return
en.delete(0,END)
en.insert(0,str(eval(num)*eval(num)))
#当点了=之后如果第一个为数字则就可以重新开始若要使用之前的数据可以使用ans
# 但是如果是使用的符号则需要使用之前的数字不做修改
def add_char(x):
global falg
if (x=='exp' or x=='^'):
falg=1
num = en.get()
en.delete(0,END)
global flag
if(flag):
en.insert(0,str(ans)+x)
flag=0
else:
en.insert(0, str(num) +x)
def end1():
global ans
global flag
global falg
# for i in str(en.get()):
if falg:
er_yuan()
falg=0
return
num=eval(str(en.get()))
en.delete(0,END)
en.insert(0,str(num))
ans=num
flag=1
def ans_():
global ans
num=en.get()
en.delete(0, END)
en.insert(0, str(num)+str(ans))
def juedui():
num = str(en.get())
en.delete(0, END)
en.insert(0, str(abs(eval(num))))
def jiechen():
num = str(en.get())
en.delete(0, END)
sum=1
k=abs(eval(num))
for i in range(2,k+1,1):
sum*=i
en.insert(0, str(sum))
def sqrt_():
num = str(en.get())
for i in range(len(num) - 1, 0, -1):
if (str.isdigit(num[i]) or num[i]=='.')==0:
en.delete(0, END)
en.insert(0, num[0:i+1] + str(math.sqrt(eval(num[i+1:]))))
return
en.delete(0, END)
en.insert(0, str(math.sqrt(eval(num))))
def zhi_10():
num = str(en.get())
for i in range(len(num) - 1, 0, -1):
if (str.isdigit(num[i]) or num[i]=='.')==0:
en.delete(0, END)
en.insert(0, num[0:i+1] + str(10**(eval(num[i+1:]))))
return
en.delete(0, END)
en.insert(0, str(10**(eval(num))))
def fu():
num=en.get()
en.delete(0,END)
en.insert(0,'-'+str(num))
def log_():
num = str(en.get())
for i in range(len(num) - 1, 0, -1):
if (str.isdigit(num[i]) or num[i] == '.') == 0:
en.delete(0, END)
en.insert(0, num[0:i + 1] + str(math.log10(eval(num[i + 1:]))))
return
en.delete(0, END)
if eval(num[0:])<=0:
en.insert(0,'error')
return
en.insert(0, str(math.log10(eval(num[0:]))))
def IN_():
num = str(en.get())
for i in range(len(num) - 1, 0, -1):
if (str.isdigit(num[i]) or num[i] == '.') == 0:
en.delete(0, END)
en.insert(0, num[0:i + 1] + str(math.log(eval(num[i + 1:]))))
return
en.delete(0, END)
if eval(num[0:]) <= 0:
en.insert(0, 'error')
return
en.insert(0, str(math.log(eval(num[0:]))))
but7=Button(win,text=7,width=3,font=('Arial',31),command=lambda :numinput(7))
but8=Button(win,text=8,width=3,font=('Arial',31),command=lambda :numinput(8))
but9=Button(win,text=9,width=3,font=('Arial',31),command=lambda :numinput(9))
but4=Button(win,text=4,width=3,font=('Arial',31),command=lambda :numinput(4))
but5=Button(win,text=5,width=3,font=('Arial',31),command=lambda :numinput(5))
but6=Button(win,text=6,width=3,font=('Arial',31),command=lambda :numinput(6))
but1=Button(win,text=1,width=3,font=('Arial',31),command=lambda :numinput(1))
but2=Button(win,text=2,width=3,font=('Arial',31),command=lambda :numinput(2))
but3=Button(win,text=3,width=3,font=('Arial',31),command=lambda :numinput(3))
but0=Button(win,text=0,width=3,font=('Arial',31),command=lambda :numinput(0))
bu1=Button(win,text='ans',width=3,font=('Arial',31),command=ans_)
bu2=Button(win,text='π',width=3,font=('Arial',31),command=lambda :numinput(pi))
bu3=Button(win,text='e',width=3,font=('Arial',31),command=lambda :numinput(e))
bu4=Button(win,text='CE',width=3,font=('Arial',31),command=clear)
bu5=Button(win,text='del',width=3,font=('Arial',31),command=delete_n)
bu6=Button(win,text='x^2',width=3,font=('Arial',31),command=mi_2)
bu7=Button(win,text='1/x',width=3,font=('Arial',31),command=x_1)
bu8=Button(win,text='|x|',width=3,font=('Arial',31),command=juedui)
bu9=Button(win,text='exp',width=3,font=('Arial',31),command=lambda :add_char('exp'))
bu0=Button(win,text='mod',width=3,font=('Arial',31),command=lambda:add_char('%'))
b1=Button(win,text='sqrt()',width=3,font=('Arial',31),command=sqrt_)
b2=Button(win,text='(',width=3,font=('Arial',31),command=lambda :add_char('('))
b3=Button(win,text=')',width=3,font=('Arial',31),command=lambda :add_char(')'))
b4=Button(win,text='n!',width=3,font=('Arial',31),command=jiechen)
b5=Button(win,text='/',width=3,font=('Arial',31),command=lambda :add_char('/'))
b6=Button(win,text='x^y',width=3,font=('Arial',31),command=lambda :add_char('^'))
b7=Button(win,text='*',width=3,font=('Arial',31),command=lambda :add_char('*'))
b8=Button(win,text='10^x',width=3,font=('Arial',31),command=zhi_10)
b9=Button(win,text='-',width=3,font=('Arial',31),command=lambda :add_char('-'))
b0=Button(win,text='log',width=3,font=('Arial',31),command=log_)
b11=Button(win,text='+',width=3,font=('Arial',31),command=lambda :add_char('+'))
b12=Button(win,text='ln',width=3,font=('Arial',31),command=IN_)
b13=Button(win,text='+/-',width=3,font=('Arial',31),command=fu)
b14=Button(win,text='.',width=3,font=('Arial',31),command=lambda :add_char('.'))
b15=Button(win,text='=',width=3,font=('Arial',31),command=end1)
b6.place(x=0,y=320)
but7.place(x=90,y=320)
but8.place(x=180,y=320)
but9.place(x=270,y=320)
b7.place(x=360,y=320)
but4.place(x=90,y=410)
but5.place(x=180,y=410)
but6.place(x=270,y=410)
b8.place(x=0,y=410)
b9.place(x=360,y=410)
but1.place(x=90,y=500)
but2.place(x=180,y=500)
but3.place(x=270,y=500)
b0.place(x=0,y=500)
b11.place(x=360,y=500)
b13.place(x=90,y=590)
but0.place(x=180,y=590)
b14.place(x=270,y=590)
b12.place(x=0,y=590)
b15.place(x=360,y=590)
bu2.place(x=90,y=50)
bu3.place(x=180,y=50)
bu4.place(x=270,y=50)
bu1.place(x=0,y=50)
bu5.place(x=360,y=50)
bu7.place(x=90,y=140)
bu8.place(x=180,y=140)
bu9.place(x=270,y=140)
bu6.place(x=0,y=140)
bu0.place(x=360,y=140)
b2.place(x=90,y=230)
b3.place(x=180,y=230)
b4.place(x=270,y=230)
b1.place(x=0,y=230)
b5.place(x=360,y=230)
en=Entry(win,width=30,font=('Arial',20))
en.place(x=0,y=0)
mainloop()
实例2
1. 导包
import tkinter as tk
import tkinter.messagebox
import re
import math
#from functions import *
import导入包,as是给tkinter重新起了个名字,messagebox是一个错误提示框(如:分母为0,会错误提示)
functions.py是一个自定义函数,计算数值时用。
2. 初始化初级界面
root = tk.Tk()
root.minsize(300, 400) # 窗口大小300*400
root.resizable(0, 0)
root.title('Jhze的计算器') # 计算器名字
3. 创建初级页面
生成初级页面的所有按钮,这里看起来代码很累赘,尝试用循环实现,但是循环生成的按钮样子不好看,没有调到想要的效果。所以就选择这样一个一个的生成。
这里利用button中一个很重要的参数command来回调函数,具体就是你可以通过点击按钮来获取想应的值,并且做相关的操作。
# 运算符号按钮
# 第一行
btnac = tkinter.Button(root, text='AC', bd=0.5, font=('黑体', 20), fg='orange', command=lambda \
x='AC': buttonClick(x))
btnac.place(x=0, y=150, width=75, height=50)
btnback = tkinter.Button(root, text='←', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='←': buttonClick(x))
btnback.place(x=75, y=150, width=75, height=50)
btndivi = tkinter.Button(root, text='^', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='^': buttonClick(x))
btndivi.place(x=150, y=150, width=75, height=50)
btnmul = tkinter.Button(root, text='+', font=('微软雅黑', 20), fg="#4F4F4F", bd=0.5, command=lambda \
x='+': buttonClick(x))
btnmul.place(x=225, y=150, width=75, height=50)
# 第二行
btn7 = tkinter.Button(root, text='7', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='7': buttonClick(x))
btn7.place(x=0, y=200, width=75, height=50)
btn8 = tkinter.Button(root, text='8', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='8': buttonClick(x))
btn8.place(x=75, y=200, width=75, height=50)
btn9 = tkinter.Button(root, text='9', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='9': buttonClick(x))
btn9.place(x=150, y=200, width=75, height=50)
btnsub = tkinter.Button(root, text='-', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='-': buttonClick(x))
btnsub.place(x=225, y=200, width=75, height=50)
# 第三行
btn4 = tkinter.Button(root, text='4', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='4': buttonClick(x))
btn4.place(x=0, y=250, width=75, height=50)
btn5 = tkinter.Button(root, text='5', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='5': buttonClick(x))
btn5.place(x=75, y=250, width=75, height=50)
btn6 = tkinter.Button(root, text='6', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='6': buttonClick(x))
btn6.place(x=150, y=250, width=75, height=50)
btnadd = tkinter.Button(root, text='×', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='×': buttonClick(x))
btnadd.place(x=225, y=250, width=75, height=50)
# 第四行
btn1 = tkinter.Button(root, text='1', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='1': buttonClick(x))
btn1.place(x=0, y=300, width=75, height=50)
btn2 = tkinter.Button(root, text='2', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='2': buttonClick(x))
btn2.place(x=75, y=300, width=75, height=50)
btn3 = tkinter.Button(root, text='3', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='3': buttonClick(x))
btn3.place(x=150, y=300, width=75, height=50)
btnechu = tkinter.Button(root, text='÷', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='÷': buttonClick(x))
btnechu.place(x=225, y=300, width=75, height=50)
# 第五行
btnper = tkinter.Button(root, text='高级', font=('微软雅黑', 20), fg='orange', bd=0.5,
command=lambda x='高级': buttonClick(x))
btnper.place(x=0, y=350, width=75, height=50)
btn0 = tkinter.Button(root, text='0', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='0': buttonClick(x))
btn0.place(x=75, y=350, width=75, height=50)
btnpoint = tkinter.Button(root, text='.', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='.': buttonClick(x))
btnpoint.place(x=150, y=350, width=75, height=50)
btnequ = tkinter.Button(root, text='=', bg='orange', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5,
command=lambda x='=': buttonClick(x))
btnequ.place(x=225, y=350, width=75, height=50)
4.绘制输出文本框
contentVar = tkinter.StringVar(root, '')
contentEntry = tkinter.Entry(root, textvariable=contentVar, state='readonly', font=("Arial", 12))
contentEntry.place(x=0, y=110, width=300, height=40)
5.低级页面的响应事件处理
这里我们通过buttonClick()来响应事件。
1.如果btn是‘0123456789’数值,直接赋值给content。
2.如果btn是‘AC’,响应清屏
3.如果btn是‘←’,回退一个字符,其实这里最方便的是用切片法很容易实现
4.如果btn是‘=’,则将content这个字符串计算值,并输出。因为是初级页面,只有简单的四则运算,完全可以用python自带的函数eval()来计算值。
def buttonClick(btn):
content = contentVar.get()
if content.startswith('.'): # 小数点前加0
content = '0' + content
if btn in '0123456789':
content += btn
elif btn == '.':
lastPart = re.split(r'\+|-|\*|/', content)[-1]
if '.' in lastPart:
tk.messagebox.showerror('错误', 'Input Error')
return
else:
content += btn
elif btn == 'AC':
content = ''
elif btn == '=':
try:
for operat in content:
if operat == '÷':
content = content.replace('÷', '/')
elif operat == '×':
content = content.replace('×', '*')
value = eval(content)
content = str(round(value, 10))
except:
tk.messagebox.showerror('错误', 'VALUE ERROR')
return
elif btn in operators:
if content.endswith(operators):
tk.messagebox.showerror('错误', 'FORMAT ERROR')
return
content += btn
elif btn == '^':
n = content.split('.')
if all(map(lambda x: x.isdigit(), n)):
content = eval(content)*eval(content)
else:
tk.messagebox.showerror('错误', 'Input Error')
return
elif btn == '←': # 如果按下的是退格‘’,则选取当前数字第一位到倒数第二位
content = content[0:-1]
elif btn == '高级':
其实此时已经实现了一个简单的初级页面,能进行四则运算,并且能输出相应的值。就差高级这个接口的实现啦,接下来就让我们来实现高级这个按钮的功能吧。
6.低级页面中高级按钮的实现
[注意]:以下代码全部都是在“高级”这个按钮下来实现的,注意python语言的缩进。也就是在上述的 elif btn==‘高级’:之下实现。
点击高级按钮之后,响应对应事件,因为我们页面大小不变,所以我们需要调用btnac.destroy() 来销毁低级页面的按钮,同理调用:btn1.destroy()、btn2.destroy()等等。也就意味着把初级页面的按钮全部销毁,重新布局。此时有7行按钮生成。
这里小北我说一下最初的构思,本来想点击高级按钮之后,将原来的按钮缩小比例,并且增加新的高级按钮。这样可以实现,而且减少页面布局代码,但是这样做的同时,初级界面的那个‘高级’按钮还会在,曾试图改变它的名称,但效果不是很好。并且高级与初级页面在计算的时候都是用的同一种方法,通过command回调函数来实现。高级页面需要正则表达式对点击获取的字符串进行处理。所以出现诸多问题。因此没有用页面按钮比例缩小的那构思。而是直接将初级页面的按钮全部清理,重新布局。这样就解决了那些问题。也完成了高级<---->低级页面的来回跳转。看起来有种缩放的效果。请读者自行体会。
contentEntry.place(x=0, y=45, width=300, height=40) # 重新绘制输出框
# 运算符号按钮
# 第一行
btncsc = tkinter.Button(root, text='csc', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='csc': buttonClick1(x))
btncsc.place(x=0, y=85, width=60, height=45)
btnrad = tkinter.Button(root, text='rad', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='rad': buttonClick1(x))
btnrad.place(x=60, y=85, width=60, height=45)
btnsin = tkinter.Button(root, text='sin', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='sin': buttonClick1(x))
btnsin.place(x=120, y=85, width=60, height=45)
btncos = tkinter.Button(root, text='cos', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='cos': buttonClick1(x))
btncos.place(x=180, y=85, width=60, height=45)
btntan = tkinter.Button(root, text='tan', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='tan': buttonClick1(x))
btntan.place(x=240, y=85, width=60, height=45)
# 第二行
btnxsec = tkinter.Button(root, text='sec', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='sec': buttonClick1(x))
btnxsec.place(x=0, y=130, width=60, height=45)
btnlog = tkinter.Button(root, text='lg', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='lg': buttonClick1(x))
btnlog.place(x=60, y=130, width=60, height=45)
btnln = tkinter.Button(root, text='ln', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='ln': buttonClick1(x))
btnln.place(x=120, y=130, width=60, height=45)
btnleft = tkinter.Button(root, text='(', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='(': buttonClick1(x))
btnleft.place(x=180, y=130, width=60, height=45)
btnrigh = tkinter.Button(root, text=')', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x=')': buttonClick1(x))
btnrigh.place(x=240, y=130, width=60, height=45)
# 第三行
btnaxy = tkinter.Button(root, text='x^y', bd=0.5, font=('黑体', 20), bg=('#96CDCD'), command=lambda \
x='x^y': buttonClick1(x))
btnaxy.place(x=0, y=175, width=60, height=45)
btnac.destroy()
btnac1 = tkinter.Button(root, text='AC', bd=0.5, font=('黑体', 20), fg='orange', command=lambda \
x='AC': buttonClick1(x))
btnac1.place(x=60, y=175, width=60, height=45)
btnback.destroy()
btnback1 = tkinter.Button(root, text='←', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='←': buttonClick1(x))
btnback1.place(x=120, y=175, width=60, height=45)
btndivi.destroy()
btndivi1 = tkinter.Button(root, text='^', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='^': buttonClick1(x))
btndivi1.place(x=180, y=175, width=60, height=45)
btnmul.destroy()
btnmul1 = tkinter.Button(root, text='+', font=('微软雅黑', 20), fg="#4F4F4F", bd=0.5, command=lambda \
x='+': buttonClick1(x))
btnmul1.place(x=240, y=175, width=60, height=45)
# 第四行
btnx = tkinter.Button(root, text='X!', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='X!': buttonClick1(x))
btnx.place(x=0, y=220, width=60, height=45)
btn7.destroy()
btn71 = tkinter.Button(root, text='7', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='7': buttonClick1(x))
btn71.place(x=60, y=220, width=60, height=45)
btn8.destroy()
btn81 = tkinter.Button(root, text='8', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='8': buttonClick1(x))
btn81.place(x=120, y=220, width=60, height=45)
btn9.destroy()
btn91 = tkinter.Button(root, text='9', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='9': buttonClick1(x))
btn91.place(x=180, y=220, width=60, height=45)
btnsub.destroy()
btnsub1 = tkinter.Button(root, text='-', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='-': buttonClick1(x))
btnsub1.place(x=240, y=220, width=60, height=45)
# 第五行
btn4x = tkinter.Button(root, text='1/X', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='1/X': buttonClick1(x))
btn4x.place(x=0, y=265, width=60, height=45)
btn4.destroy()
btn41 = tkinter.Button(root, text='4', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='4': buttonClick1(x))
btn41.place(x=60, y=265, width=60, height=45)
btn5.destroy()
btn51 = tkinter.Button(root, text='5', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='5': buttonClick1(x))
btn51.place(x=120, y=265, width=60, height=45)
btn6.destroy()
btn61 = tkinter.Button(root, text='6', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='6': buttonClick1(x))
btn61.place(x=180, y=265, width=60, height=45)
btnadd.destroy()
btnadd1 = tkinter.Button(root, text='×', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='×': buttonClick1(x))
btnadd1.place(x=240, y=265, width=60, height=45)
# 第六行
btnpi = tkinter.Button(root, text='π', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='π': buttonClick1(x))
btnpi.place(x=0, y=310, width=60, height=45)
btnpi.flash()
btn1.destroy()
btn11 = tkinter.Button(root, text='1', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='1': buttonClick1(x))
btn11.place(x=60, y=310, width=60, height=45)
btn2.destroy()
btn21 = tkinter.Button(root, text='2', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='2': buttonClick1(x))
btn21.place(x=120, y=310, width=60, height=45)
btn3.destroy()
btn31 = tkinter.Button(root, text='3', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='3': buttonClick1(x))
btn31.place(x=180, y=310, width=60, height=45)
btnechu.destroy()
btnechu1 = tkinter.Button(root, text='÷', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='÷': buttonClick1(x))
btnechu1.place(x=240, y=310, width=60, height=45)
# 第七行
btnperr = tkinter.Button(root, text='低级', font=('微软雅黑', 20), fg='orange', bd=0.5,
command=lambda x='低级': buttonClick1(x))
btnperr.place(x=0, y=355, width=60, height=45)
btnper.destroy()
btnper1 = tkinter.Button(root, text='e', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5,
command=lambda x='e': buttonClick1(x))
btnper1.place(x=60, y=355, width=60, height=45)
btn0.destroy()
btn01 = tkinter.Button(root, text='0', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='0': buttonClick1(x))
btn01.place(x=120, y=355, width=60, height=45)
btnpoint.destroy()
btnpoint1 = tkinter.Button(root, text='.', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='.': buttonClick1(x))
btnpoint1.place(x=180, y=355, width=60, height=45)
btnequ.destroy()
btnequ1 = tkinter.Button(root, text='=', bg='orange', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5,
command=lambda x='=': buttonClick1(x))
btnequ1.place(x=240, y=355, width=60, height=45)
7.高级页面的响应事件的处理
先来说明一下计算器计算某个表达式用到的原理:
比如要计算这个表达式:2+3*(sin(0)+lg(10))-2
1.首先用正则表达式对这个字符串处理,计算出sin(0)=0,字符串变为:2+3*(0+lg(10))-2
2.再用正则表达式处理字符串,计算出lg(10)=1,字符串变为:2+3*(0+1)-2
3.再用正则表达式处理字符串,计算括号(0+1) =1,此时字符串变成:3+3*1-2
4.四则运算直接调用python自带的函数eval()直接计算结果。
笔者用此思想来实现下述高级页面表达式的计算。
【注】:重要实现的要点说明
1.高级页面依然保留初级页面所有布局、功能,在此基础上增加了很多新功能。
2.在高级页面输完表达式,当我们点击‘=’时,计算某个表达式值。用到上述思想。
3.我们以计算一个表达式中含有sin(x)为例来进行简单的说明:
(1)我们首先判断sin是不是在某个表达式中。
(2)使用正则表达式:strsin = r’sin(\d+)|sin(-?\d+.\d+)‘来提取如相应的表达式。
(3) 此时得到是一个字符串表达式’sin(2)’,我们再用正则表达式提取里面的数字value。调用math库里面是sin函数。来计算sin(2), 如:value = str(sin_t(float(value))) 这里的sin_t()是一个自定义函数。在下述functions.py文件里面。
(4)此时我们将计算得到的数值,调用replace() 进行替换。就能达到想要的效果了哦。
别的表达式都是用的同样的方法,这里不再赘述。请读者根据源代码自行体会。
def buttonClick1(btn):
content = contentVar.get()
if content.startswith('.'): # 小数点前加0
content = '0' + content
if btn in '0123456789()':
content += btn
elif btn == '.':
lastPart = re.split(r'\+|-|\*|/', content)[-1]
if '.' in lastPart:
tk.messagebox.showerror('错误', 'Input Error')
return
else:
content += btn
elif btn == '^':
n = content.split('.')
if all(map(lambda x: x.isdigit(), n)):
content = eval(content) * eval(content)
else:
tk.messagebox.showerror('错误', 'Input Error')
return
elif btn == 'AC':
content = ''
elif btn == '=':
try:
for operat in content:
if operat == '÷':
content = content.replace('÷', '/')
elif operat == '×':
content = content.replace('×', '*')
elif operat == '^':
content = content.replace('^', '**')
strsin = r'sin\(\d+\)|sin\(\-?\d+\.\d+\)'
if 'sin' in content:
m = re.search(strsin, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(sin_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(sin_t(float(value)))
content = content.replace(exchange1, value)
strcos = r'cos\(\d+\)|cos\(\-?\d+\.\d+\)'
if 'cos' in content:
m = re.search(strcos, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(cos_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(cos_t(float(value)))
content = content.replace(exchange1, value)
strtan = r'tan\(\d+\)|tan\(\-?\d+\.\d+\)'
if 'tan' in content:
m = re.search(strtan, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(tan_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(tan_t(float(value)))
content = content.replace(exchange1, value)
strsec = r'sec\(\-?\d+\)|sec\(\-?\d+\.\d+\)'
if 'sec' in content:
m = re.search(strsec, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(sec_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(sec_t(float(value)))
content = content.replace(exchange1, value)
strcsc = r'csc\(\d+\)'
if 'csc' in content:
m = re.search(strcsc, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(csc_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(csc_t(float(value)))
content = content.replace(exchange1, value)
strlg = r'lg\(\-?\d+\)|lg\(\-?\d+\.\d+\)'
if 'lg' in content:
m = re.search(strlg, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
if float(value) <= 0:
tk.messagebox.showerror('错误', 'FORMAT ERROR')
else:
value = str(lg_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
if int(value)<=0 :
tk.messagebox.showerror('错误', 'FORMAT ERROR')
else:
value = str(lg_t(float(value)))
content = content.replace(exchange1, value)
strln = r'ln\(\-?\d+\)|ln\(\-?\d+\.\d+\)'
if 'ln' in content:
m = re.search(strln, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
if float(value) <= 0:
tk.messagebox.showerror('错误', 'FORMAT ERROR')
else:
value = str(ln_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
if int(value) <= 0:
tk.messagebox.showerror('错误', 'FORMAT ERROR')
else:
value = str(ln_t(float(value)))
content = content.replace(exchange1, value)
value = eval(content)
content = str(round(value, 10))
except ZeroDivisionError:
tk.messagebox.showerror('错误', 'VALUE ERROR')
return
elif btn in operators:
if content.endswith(operators):
tk.messagebox.showerror('错误', 'FORMAT ERROR')
return
content += btn
elif btn == 'e':
content = 2.7182818284
elif btn == 'π':
content = 3.1415926535
elif btn == '1/X':
content = reciprocal(float(content))
elif btn == 'X!':
content = factorial(int(content))
elif btn == 'x^y':
content += '^'
elif btn == 'sin':
content += 'sin('
elif btn == 'cos':
content += 'cos('
elif btn == 'tan':
content += 'tan('
elif btn == 'sec':
content += 'sec('
elif btn == 'csc':
content += 'csc('
elif btn == 'lg':
content += 'lg('
elif btn == 'ln':
content += 'ln('
elif btn == '←': # 如果按下的是退格‘’,则选取当前数字第一位到倒数第二位
content = content[0:-1]
8.高级页面中低级按钮实现
这里还是用到的同样思想。对所有的高级按钮全部销毁。重新布局新的按钮。这里不再赘述。
elif btn == '低级':
contentEntry.place(x=0, y=110, width=300, height=40)
#第一行
btncsc.destroy()
btnrad.destroy()
btnsin.destroy()
btncos.destroy()
btntan.destroy()
# 第二行
btnxsec.destroy()
btnlog.destroy()
btnln.destroy()
btnleft.destroy()
btnrigh.destroy()
# 第三行
btnaxy.destroy()
btnac1.destroy()
btnback1.destroy()
btndivi1.destroy()
btnmul1.destroy()
# 第四行
btnx.destroy()
btn71.destroy()
btn81.destroy()
btn91.destroy()
btnsub1.destroy()
# 第五行
btn4x.destroy()
btn41.destroy()
btn51.destroy()
btn61.destroy()
btnadd1.destroy()
# 第六行
btnpi.destroy()
btn11.destroy()
btn21.destroy()
btn31.destroy()
btnechu1.destroy()
# 第七行
btnperr.destroy()
btnper1.destroy()
btn01.destroy()
btnpoint1.destroy()
btnequ1.destroy()
# 第一行
btnac = tkinter.Button(root, text='AC', bd=0.5, font=('黑体', 20), fg='orange', command=lambda \
x='AC': buttonClick(x))
btnac.flash()
btnac.place(x=0, y=150, width=75, height=50)
btnback = tkinter.Button(root, text='←', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='←': buttonClick(x))
btnback.place(x=75, y=150, width=75, height=50)
btndivi = tkinter.Button(root, text='^', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='^': buttonClick(x))
btndivi.place(x=150, y=150, width=75, height=50)
btnmul = tkinter.Button(root, text='+', font=('微软雅黑', 20), fg="#4F4F4F", bd=0.5, command=lambda \
x='+': buttonClick(x))
btnmul.place(x=225, y=150, width=75, height=50)
# 第二行
btn7 = tkinter.Button(root, text='7', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='7': buttonClick(x))
btn7.place(x=0, y=200, width=75, height=50)
btn8 = tkinter.Button(root, text='8', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='8': buttonClick(x))
btn8.place(x=75, y=200, width=75, height=50)
btn9 = tkinter.Button(root, text='9', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='9': buttonClick(x))
btn9.place(x=150, y=200, width=75, height=50)
btnsub = tkinter.Button(root, text='-', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='-': buttonClick(x))
btnsub.place(x=225, y=200, width=75, height=50)
# 第三行
btn4 = tkinter.Button(root, text='4', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='4': buttonClick(x))
btn4.place(x=0, y=250, width=75, height=50)
btn5 = tkinter.Button(root, text='5', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='5': buttonClick(x))
btn5.place(x=75, y=250, width=75, height=50)
btn6 = tkinter.Button(root, text='6', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='6': buttonClick(x))
btn6.place(x=150, y=250, width=75, height=50)
btnadd = tkinter.Button(root, text='×', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='×': buttonClick(x))
btnadd.place(x=225, y=250, width=75, height=50)
# 第四行
btn1 = tkinter.Button(root, text='1', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='1': buttonClick(x))
btn1.place(x=0, y=300, width=75, height=50)
btn2 = tkinter.Button(root, text='2', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='2': buttonClick(x))
btn2.place(x=75, y=300, width=75, height=50)
btn3 = tkinter.Button(root, text='3', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='3': buttonClick(x))
btn3.place(x=150, y=300, width=75, height=50)
btnechu = tkinter.Button(root, text='÷', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='÷': buttonClick(x))
btnechu.place(x=225, y=300, width=75, height=50)
# 第五行
btnper = tkinter.Button(root, text='高级', font=('微软雅黑', 20), fg='orange', bd=0.5,
command=lambda x='高级': buttonClick(x))
btnper.place(x=0, y=350, width=75, height=50)
btn0 = tkinter.Button(root, text='0', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='0': buttonClick(x))
btn0.place(x=75, y=350, width=75, height=50)
btnpoint = tkinter.Button(root, text='.', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='.': buttonClick(x))
btnpoint.place(x=150, y=350, width=75, height=50)
btnequ = tkinter.Button(root, text='=', bg='orange', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5,
command=lambda x='=': buttonClick(x))
btnequ.place(x=225, y=350, width=75, height=50)
contentVar.set(content)
contentVar.set(content)
9.运行代码
这里所有的代码以及完成。最后还差个functions.py源码啦。
operators = ('÷', '×', '-', '+', '=', '.')
root.mainloop()
10.functions.py实现
本来小北想要用泰勒公式来计算复杂的表达式。但是没有得到想要的结果。直接调用math库啦,感兴趣的友友可以尝试用泰勒公式计算。
#!/usr/bin/env python
__author__: "Jhze dnowz"
import math
# 计算机倒数
def reciprocal(value):
value = round(float(1) / (float(value)), 10)
return value
# 计算阶乘
def factorial(value):
sum = 1
if value==0 or value==1:
sum =1
for i in range(value):
sum += sum * i
return sum
# 计算sin
# def sin(x):
# e = 10^(-15)
# sum = 0
# evl = x
# n = 1
# while(abs(evl)>e):
# sum = sum+evl
# a = (-1)**n
# b = evl**(2*n+1)
# c = factorial((2*n+1))
# evl = a*b/c
# n +=1
#
# print(sin(1))
# 计算sin
def sin_t(x):
return round(math.sin(x),10)
# 计算cos
def cos_t(x):
return round(math.cos(x), 10)
# 计算tan
def tan_t(x):
return round(math.tan(x), 10)
# 计算csc
def csc_t(x):
return round(float(1)/math.sin(x), 10)
# 计算sec
def sec_t(x):
return round(float(1)/math.cos(x), 10)
# 计算lg
def lg_t(x):
return round(math.log10(x), 10)
# 计算ln
def ln_t(x):
return round(math.log(x, math.e), 10)
11.相关效果图
(低级模式)
(高级模式)
import tkinter as tk
import tkinter.messagebox
import re
import math
root = tk.Tk()
root.minsize(300, 400) # 窗口大小300*400
root.resizable(0, 0)
root.title('Jhze的计算器') # 计算器名字
# 运算符号按钮
# 第一行
btnac = tkinter.Button(root, text='AC', bd=0.5, font=('黑体', 20), fg='orange', command=lambda \
x='AC': buttonClick(x))
btnac.place(x=0, y=150, width=75, height=50)
btnback = tkinter.Button(root, text='←', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='←': buttonClick(x))
btnback.place(x=75, y=150, width=75, height=50)
btndivi = tkinter.Button(root, text='^', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='^': buttonClick(x))
btndivi.place(x=150, y=150, width=75, height=50)
btnmul = tkinter.Button(root, text='+', font=('微软雅黑', 20), fg="#4F4F4F", bd=0.5, command=lambda \
x='+': buttonClick(x))
btnmul.place(x=225, y=150, width=75, height=50)
# 第二行
btn7 = tkinter.Button(root, text='7', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='7': buttonClick(x))
btn7.place(x=0, y=200, width=75, height=50)
btn8 = tkinter.Button(root, text='8', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='8': buttonClick(x))
btn8.place(x=75, y=200, width=75, height=50)
btn9 = tkinter.Button(root, text='9', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='9': buttonClick(x))
btn9.place(x=150, y=200, width=75, height=50)
btnsub = tkinter.Button(root, text='-', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='-': buttonClick(x))
btnsub.place(x=225, y=200, width=75, height=50)
# 第三行
btn4 = tkinter.Button(root, text='4', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='4': buttonClick(x))
btn4.place(x=0, y=250, width=75, height=50)
btn5 = tkinter.Button(root, text='5', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='5': buttonClick(x))
btn5.place(x=75, y=250, width=75, height=50)
btn6 = tkinter.Button(root, text='6', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='6': buttonClick(x))
btn6.place(x=150, y=250, width=75, height=50)
btnadd = tkinter.Button(root, text='×', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='×': buttonClick(x))
btnadd.place(x=225, y=250, width=75, height=50)
# 第四行
btn1 = tkinter.Button(root, text='1', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='1': buttonClick(x))
btn1.place(x=0, y=300, width=75, height=50)
btn2 = tkinter.Button(root, text='2', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='2': buttonClick(x))
btn2.place(x=75, y=300, width=75, height=50)
btn3 = tkinter.Button(root, text='3', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='3': buttonClick(x))
btn3.place(x=150, y=300, width=75, height=50)
btnechu = tkinter.Button(root, text='÷', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='÷': buttonClick(x))
btnechu.place(x=225, y=300, width=75, height=50)
# 第五行
btnper = tkinter.Button(root, text='高级', font=('微软雅黑', 20), fg='orange', bd=0.5,
command=lambda x='高级': buttonClick(x))
btnper.place(x=0, y=350, width=75, height=50)
btn0 = tkinter.Button(root, text='0', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='0': buttonClick(x))
btn0.place(x=75, y=350, width=75, height=50)
btnpoint = tkinter.Button(root, text='.', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='.': buttonClick(x))
btnpoint.place(x=150, y=350, width=75, height=50)
btnequ = tkinter.Button(root, text='=', bg='orange', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5,
command=lambda x='=': buttonClick(x))
btnequ.place(x=225, y=350, width=75, height=50)
contentVar = tkinter.StringVar(root, '')
contentEntry = tkinter.Entry(root, textvariable=contentVar, state='readonly', font=("Arial", 12))
contentEntry.place(x=0, y=110, width=300, height=40)
def buttonClick(btn):
content = contentVar.get()
if content.startswith('.'): # 小数点前加0
content = '0' + content
if btn in '0123456789':
content += btn
elif btn == '.':
lastPart = re.split(r'\+|-|\*|/', content)[-1]
if '.' in lastPart:
tk.messagebox.showerror('错误', 'Input Error')
return
else:
content += btn
elif btn == 'AC':
content = ''
elif btn == '=':
try:
for operat in content:
if operat == '÷':
content = content.replace('÷', '/')
elif operat == '×':
content = content.replace('×', '*')
value = eval(content)
content = str(round(value, 10))
except:
tk.messagebox.showerror('错误', 'VALUE ERROR')
return
elif btn in operators:
if content.endswith(operators):
tk.messagebox.showerror('错误', 'FORMAT ERROR')
return
content += btn
elif btn == '^':
n = content.split('.')
if all(map(lambda x: x.isdigit(), n)):
content = eval(content)*eval(content)
else:
tk.messagebox.showerror('错误', 'Input Error')
return
elif btn == '←': # 如果按下的是退格‘’,则选取当前数字第一位到倒数第二位
content = content[0:-1]
elif btn == '高级':
contentEntry.place(x=0, y=45, width=300, height=40) # 重新绘制输出框
# 运算符号按钮
# 第一行
btncsc = tkinter.Button(root, text='csc', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='csc': buttonClick1(x))
btncsc.place(x=0, y=85, width=60, height=45)
btnrad = tkinter.Button(root, text='rad', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='rad': buttonClick1(x))
btnrad.place(x=60, y=85, width=60, height=45)
btnsin = tkinter.Button(root, text='sin', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='sin': buttonClick1(x))
btnsin.place(x=120, y=85, width=60, height=45)
btncos = tkinter.Button(root, text='cos', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='cos': buttonClick1(x))
btncos.place(x=180, y=85, width=60, height=45)
btntan = tkinter.Button(root, text='tan', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='tan': buttonClick1(x))
btntan.place(x=240, y=85, width=60, height=45)
# 第二行
btnxsec = tkinter.Button(root, text='sec', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='sec': buttonClick1(x))
btnxsec.place(x=0, y=130, width=60, height=45)
btnlog = tkinter.Button(root, text='lg', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='lg': buttonClick1(x))
btnlog.place(x=60, y=130, width=60, height=45)
btnln = tkinter.Button(root, text='ln', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='ln': buttonClick1(x))
btnln.place(x=120, y=130, width=60, height=45)
btnleft = tkinter.Button(root, text='(', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x='(': buttonClick1(x))
btnleft.place(x=180, y=130, width=60, height=45)
btnrigh = tkinter.Button(root, text=')', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5,
command=lambda x=')': buttonClick1(x))
btnrigh.place(x=240, y=130, width=60, height=45)
# 第三行
btnaxy = tkinter.Button(root, text='x^y', bd=0.5, font=('黑体', 20), bg=('#96CDCD'), command=lambda \
x='x^y': buttonClick1(x))
btnaxy.place(x=0, y=175, width=60, height=45)
btnac.destroy()
btnac1 = tkinter.Button(root, text='AC', bd=0.5, font=('黑体', 20), fg='orange', command=lambda \
x='AC': buttonClick1(x))
btnac1.place(x=60, y=175, width=60, height=45)
btnback.destroy()
btnback1 = tkinter.Button(root, text='←', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='←': buttonClick1(x))
btnback1.place(x=120, y=175, width=60, height=45)
btndivi.destroy()
btndivi1 = tkinter.Button(root, text='^', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='^': buttonClick1(x))
btndivi1.place(x=180, y=175, width=60, height=45)
btnmul.destroy()
btnmul1 = tkinter.Button(root, text='+', font=('微软雅黑', 20), fg="#4F4F4F", bd=0.5, command=lambda \
x='+': buttonClick1(x))
btnmul1.place(x=240, y=175, width=60, height=45)
# 第四行
btnx = tkinter.Button(root, text='X!', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='X!': buttonClick1(x))
btnx.place(x=0, y=220, width=60, height=45)
btn7.destroy()
btn71 = tkinter.Button(root, text='7', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='7': buttonClick1(x))
btn71.place(x=60, y=220, width=60, height=45)
btn8.destroy()
btn81 = tkinter.Button(root, text='8', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='8': buttonClick1(x))
btn81.place(x=120, y=220, width=60, height=45)
btn9.destroy()
btn91 = tkinter.Button(root, text='9', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='9': buttonClick1(x))
btn91.place(x=180, y=220, width=60, height=45)
btnsub.destroy()
btnsub1 = tkinter.Button(root, text='-', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='-': buttonClick1(x))
btnsub1.place(x=240, y=220, width=60, height=45)
# 第五行
btn4x = tkinter.Button(root, text='1/X', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='1/X': buttonClick1(x))
btn4x.place(x=0, y=265, width=60, height=45)
btn4.destroy()
btn41 = tkinter.Button(root, text='4', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='4': buttonClick1(x))
btn41.place(x=60, y=265, width=60, height=45)
btn5.destroy()
btn51 = tkinter.Button(root, text='5', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='5': buttonClick1(x))
btn51.place(x=120, y=265, width=60, height=45)
btn6.destroy()
btn61 = tkinter.Button(root, text='6', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='6': buttonClick1(x))
btn61.place(x=180, y=265, width=60, height=45)
btnadd.destroy()
btnadd1 = tkinter.Button(root, text='×', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='×': buttonClick1(x))
btnadd1.place(x=240, y=265, width=60, height=45)
# 第六行
btnpi = tkinter.Button(root, text='π', font=('微软雅黑', 20), bg=('#96CDCD'), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='π': buttonClick1(x))
btnpi.place(x=0, y=310, width=60, height=45)
btnpi.flash()
btn1.destroy()
btn11 = tkinter.Button(root, text='1', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='1': buttonClick1(x))
btn11.place(x=60, y=310, width=60, height=45)
btn2.destroy()
btn21 = tkinter.Button(root, text='2', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='2': buttonClick1(x))
btn21.place(x=120, y=310, width=60, height=45)
btn3.destroy()
btn31 = tkinter.Button(root, text='3', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='3': buttonClick1(x))
btn31.place(x=180, y=310, width=60, height=45)
btnechu.destroy()
btnechu1 = tkinter.Button(root, text='÷', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='÷': buttonClick1(x))
btnechu1.place(x=240, y=310, width=60, height=45)
# 第七行
btnperr = tkinter.Button(root, text='低级', font=('微软雅黑', 20), fg='orange', bd=0.5,
command=lambda x='低级': buttonClick1(x))
btnperr.place(x=0, y=355, width=60, height=45)
btnper.destroy()
btnper1 = tkinter.Button(root, text='e', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5,
command=lambda x='e': buttonClick1(x))
btnper1.place(x=60, y=355, width=60, height=45)
btn0.destroy()
btn01 = tkinter.Button(root, text='0', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='0': buttonClick1(x))
btn01.place(x=120, y=355, width=60, height=45)
btnpoint.destroy()
btnpoint1 = tkinter.Button(root, text='.', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='.': buttonClick1(x))
btnpoint1.place(x=180, y=355, width=60, height=45)
btnequ.destroy()
btnequ1 = tkinter.Button(root, text='=', bg='orange', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5,
command=lambda x='=': buttonClick1(x))
btnequ1.place(x=240, y=355, width=60, height=45)
def buttonClick1(btn):
content = contentVar.get()
if content.startswith('.'): # 小数点前加0
content = '0' + content
if btn in '0123456789()':
content += btn
elif btn == '.':
lastPart = re.split(r'\+|-|\*|/', content)[-1]
if '.' in lastPart:
tk.messagebox.showerror('错误', 'Input Error')
return
else:
content += btn
elif btn == '^':
n = content.split('.')
if all(map(lambda x: x.isdigit(), n)):
content = eval(content) * eval(content)
else:
tk.messagebox.showerror('错误', 'Input Error')
return
elif btn == 'AC':
content = ''
elif btn == '=':
try:
for operat in content:
if operat == '÷':
content = content.replace('÷', '/')
elif operat == '×':
content = content.replace('×', '*')
elif operat == '^':
content = content.replace('^', '**')
strsin = r'sin\(\d+\)|sin\(\-?\d+\.\d+\)'
if 'sin' in content:
m = re.search(strsin, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(sin_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(sin_t(float(value)))
content = content.replace(exchange1, value)
strcos = r'cos\(\d+\)|cos\(\-?\d+\.\d+\)'
if 'cos' in content:
m = re.search(strcos, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(cos_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(cos_t(float(value)))
content = content.replace(exchange1, value)
strtan = r'tan\(\d+\)|tan\(\-?\d+\.\d+\)'
if 'tan' in content:
m = re.search(strtan, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(tan_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(tan_t(float(value)))
content = content.replace(exchange1, value)
strsec = r'sec\(\-?\d+\)|sec\(\-?\d+\.\d+\)'
if 'sec' in content:
m = re.search(strsec, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(sec_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(sec_t(float(value)))
content = content.replace(exchange1, value)
strcsc = r'csc\(\d+\)'
if 'csc' in content:
m = re.search(strcsc, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
value = str(csc_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
value = str(csc_t(float(value)))
content = content.replace(exchange1, value)
strlg = r'lg\(\-?\d+\)|lg\(\-?\d+\.\d+\)'
if 'lg' in content:
m = re.search(strlg, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
if float(value) <= 0:
tk.messagebox.showerror('错误', 'FORMAT ERROR')
else:
value = str(lg_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
if int(value)<=0 :
tk.messagebox.showerror('错误', 'FORMAT ERROR')
else:
value = str(lg_t(float(value)))
content = content.replace(exchange1, value)
strln = r'ln\(\-?\d+\)|ln\(\-?\d+\.\d+\)'
if 'ln' in content:
m = re.search(strln, content)
if m is not None:
exchange = m.group()
exchange1 = exchange
if '.' in exchange:
exchange = re.search("\-?\d+\.\d+", exchange)
value = exchange.group()
if float(value) <= 0:
tk.messagebox.showerror('错误', 'FORMAT ERROR')
else:
value = str(ln_t(float(value)))
content = content.replace(exchange1, value)
else:
exchange = re.search("\-?\d+", exchange)
value = exchange.group()
if int(value) <= 0:
tk.messagebox.showerror('错误', 'FORMAT ERROR')
else:
value = str(ln_t(float(value)))
content = content.replace(exchange1, value)
value = eval(content)
content = str(round(value, 10))
except ZeroDivisionError:
tk.messagebox.showerror('错误', 'VALUE ERROR')
return
elif btn in operators:
if content.endswith(operators):
tk.messagebox.showerror('错误', 'FORMAT ERROR')
return
content += btn
elif btn == 'e':
content = 2.7182818284
elif btn == 'π':
content = 3.1415926535
elif btn == '1/X':
content = reciprocal(float(content))
elif btn == 'X!':
content = factorial(int(content))
elif btn == 'x^y':
content += '^'
elif btn == 'sin':
content += 'sin('
elif btn == 'cos':
content += 'cos('
elif btn == 'tan':
content += 'tan('
elif btn == 'sec':
content += 'sec('
elif btn == 'csc':
content += 'csc('
elif btn == 'lg':
content += 'lg('
elif btn == 'ln':
content += 'ln('
elif btn == '←': # 如果按下的是退格‘’,则选取当前数字第一位到倒数第二位
content = content[0:-1]
elif btn == '低级':
contentEntry.place(x=0, y=110, width=300, height=40)
#第一行
btncsc.destroy()
btnrad.destroy()
btnsin.destroy()
btncos.destroy()
btntan.destroy()
# 第二行
btnxsec.destroy()
btnlog.destroy()
btnln.destroy()
btnleft.destroy()
btnrigh.destroy()
# 第三行
btnaxy.destroy()
btnac1.destroy()
btnback1.destroy()
btndivi1.destroy()
btnmul1.destroy()
# 第四行
btnx.destroy()
btn71.destroy()
btn81.destroy()
btn91.destroy()
btnsub1.destroy()
# 第五行
btn4x.destroy()
btn41.destroy()
btn51.destroy()
btn61.destroy()
btnadd1.destroy()
# 第六行
btnpi.destroy()
btn11.destroy()
btn21.destroy()
btn31.destroy()
btnechu1.destroy()
# 第七行
btnperr.destroy()
btnper1.destroy()
btn01.destroy()
btnpoint1.destroy()
btnequ1.destroy()
# 第一行
btnac = tkinter.Button(root, text='AC', bd=0.5, font=('黑体', 20), fg='orange', command=lambda \
x='AC': buttonClick(x))
btnac.flash()
btnac.place(x=0, y=150, width=75, height=50)
btnback = tkinter.Button(root, text='←', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='←': buttonClick(x))
btnback.place(x=75, y=150, width=75, height=50)
btndivi = tkinter.Button(root, text='^', font=('微软雅黑', 20), fg='#4F4F4F', bd=0.5, command=lambda \
x='^': buttonClick(x))
btndivi.place(x=150, y=150, width=75, height=50)
btnmul = tkinter.Button(root, text='+', font=('微软雅黑', 20), fg="#4F4F4F", bd=0.5, command=lambda \
x='+': buttonClick(x))
btnmul.place(x=225, y=150, width=75, height=50)
# 第二行
btn7 = tkinter.Button(root, text='7', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='7': buttonClick(x))
btn7.place(x=0, y=200, width=75, height=50)
btn8 = tkinter.Button(root, text='8', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='8': buttonClick(x))
btn8.place(x=75, y=200, width=75, height=50)
btn9 = tkinter.Button(root, text='9', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='9': buttonClick(x))
btn9.place(x=150, y=200, width=75, height=50)
btnsub = tkinter.Button(root, text='-', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='-': buttonClick(x))
btnsub.place(x=225, y=200, width=75, height=50)
# 第三行
btn4 = tkinter.Button(root, text='4', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='4': buttonClick(x))
btn4.place(x=0, y=250, width=75, height=50)
btn5 = tkinter.Button(root, text='5', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='5': buttonClick(x))
btn5.place(x=75, y=250, width=75, height=50)
btn6 = tkinter.Button(root, text='6', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='6': buttonClick(x))
btn6.place(x=150, y=250, width=75, height=50)
btnadd = tkinter.Button(root, text='×', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='×': buttonClick(x))
btnadd.place(x=225, y=250, width=75, height=50)
# 第四行
btn1 = tkinter.Button(root, text='1', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='1': buttonClick(x))
btn1.place(x=0, y=300, width=75, height=50)
btn2 = tkinter.Button(root, text='2', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='2': buttonClick(x))
btn2.place(x=75, y=300, width=75, height=50)
btn3 = tkinter.Button(root, text='3', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='3': buttonClick(x))
btn3.place(x=150, y=300, width=75, height=50)
btnechu = tkinter.Button(root, text='÷', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='÷': buttonClick(x))
btnechu.place(x=225, y=300, width=75, height=50)
# 第五行
btnper = tkinter.Button(root, text='高级', font=('微软雅黑', 20), fg='orange', bd=0.5,
command=lambda x='高级': buttonClick(x))
btnper.place(x=0, y=350, width=75, height=50)
btn0 = tkinter.Button(root, text='0', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='0': buttonClick(x))
btn0.place(x=75, y=350, width=75, height=50)
btnpoint = tkinter.Button(root, text='.', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5, command=lambda \
x='.': buttonClick(x))
btnpoint.place(x=150, y=350, width=75, height=50)
btnequ = tkinter.Button(root, text='=', bg='orange', font=('微软雅黑', 20), fg=('#4F4F4F'), bd=0.5,
command=lambda x='=': buttonClick(x))
btnequ.place(x=225, y=350, width=75, height=50)
contentVar.set(content)
contentVar.set(content)
operators = ('÷', '×', '-', '+', '=', '.')
root.mainloop()
#!/usr/bin/env python
__author__: "Jhze dnowz"
import math
#!/usr/bin/env python
__author__: "Jhze dnowz"
import math
# 计算机倒数
def reciprocal(value):
value = round(float(1) / (float(value)), 10)
return value
# 计算阶乘
def factorial(value):
sum = 1
if value==0 or value==1:
sum =1
for i in range(value):
sum += sum * i
return sum
# 计算sin
# def sin(x):
# e = 10^(-15)
# sum = 0
# evl = x
# n = 1
# while(abs(evl)>e):
# sum = sum+evl
# a = (-1)**n
# b = evl**(2*n+1)
# c = factorial((2*n+1))
# evl = a*b/c
# n +=1
#
# print(sin(1))
# 计算sin
def sin_t(x):
return round(math.sin(x),10)
# 计算cos
def cos_t(x):
return round(math.cos(x), 10)
# 计算tan
def tan_t(x):
return round(math.tan(x), 10)
# 计算csc
def csc_t(x):
return round(float(1)/math.sin(x), 10)
# 计算sec
def sec_t(x):
return round(float(1)/math.cos(x), 10)
# 计算lg
def lg_t(x):
return round(math.log10(x), 10)
# 计算ln
def ln_t(x):
return round(math.log(x, math.e), 10)
12.动态效果图
![](https://i-blog.csdnimg.cn/blog_migrate/5e79278856ffd5ca5540682758c76f00.gif)
续,
感兴趣的友友们可以学习一下哈~
基于PYQT的Visual Studio Code实现
一、用QT设计师绘制界面保存成ui文件
1、打开QTdesigner
2、选择Dialog without Buttons,并单击“创建”按钮
3、添加控件
(1)拖拽“Label”控件,在文本属性中添加文字“请输入第一个数字:”;在Label水平位置拖拽一个“Line Edit”控件。
(2)拖拽“Label”控件,在文本属性中添加文字“请输入第二个额数字:”;在Label水平位置拖拽一个“Line Edit”控件。
(3)拖拽4个“PushButton”控件,在文本属性中分别添加文字“+”、“-”、“*”、“/”。
(4)拖拽“Label”控件,在文本属性中添加文字“结果:3+5=8”。
(5)现在的效果如图:
二、Qt6样式控制(QSS)
1、右键单击窗体,选择“改变样式表”,修改控件的样式。如下图所示:
2、在“编辑样式表”中输入下述指令:
*{
font-size:16px;
color:rgb(0, 85, 255);
}
颜色选择蓝色,效果如图:
三、使用布局管理器进行窗体布局
1、选择如图所示控件,点击“水平布局”(快捷键“ctrl+1”),进行水平布局。
2、选择如图所示控件,点击“水平布局”(快捷键“ctrl+1”),进行水平布局。![](https://i-blog.csdnimg.cn/blog_migrate/71261d2ae270bca05d93b36aa72d9107.png)
3、选择如图所示控件,点击“水平布局”(快捷键“ctrl+1”),进行水平布局。![](https://i-blog.csdnimg.cn/blog_migrate/d8a8616ecff8b2e12858c3b964b02cee.png)
4、选择所有控件,点击“垂直布局”(快捷键“ctrl+2”),进行垂直布局。如图所示![](https://i-blog.csdnimg.cn/blog_migrate/8fec2cc743838a6f4c04145a4b552f6c.png)
5、最后的效果如图:
四、PYQt6信号与槽的处理
1、选择窗体控件,将"objectName"属性变为“SimpleComputer”。
2、选择窗体控件,将"windowTitle"属性变为“简单计算器”。![](https://i-blog.csdnimg.cn/blog_migrate/1e37c6a2529ba68232157c54ff758665.png)
3、选择如图所示控件,将"objectName"属性变为“lineEdit_first”。![](https://i-blog.csdnimg.cn/blog_migrate/73fe50ba545a520bc4c1fed34c1a511e.png)
4、选择如图所示控件,将"objectName"属性变为“lineEdit_second”。![](https://i-blog.csdnimg.cn/blog_migrate/4c63ee0020efb2cd24572ec4ac1d53e3.png)
5、选择如图所示控件,将"objectName"属性变为“pushButton_add”。![](https://i-blog.csdnimg.cn/blog_migrate/db5817aaf657e878fc1e33f814b197ed.png)
6、选择如图所示控件,将"objectName"属性变为“pushButton_sub”。![](https://i-blog.csdnimg.cn/blog_migrate/dd9a9a086e10d7b4293a549ab5b5fc3f.png)
7、选择如图所示控件,将"objectName"属性变为“pushButton_mul”。![](https://i-blog.csdnimg.cn/blog_migrate/a98a044d2ebe0c1399ccc7028f07d138.png)
8、选择如图所示控件,将"objectName"属性变为“pushButton_divide”。![](https://i-blog.csdnimg.cn/blog_migrate/7e7280b3a58ce93b8c940f516136a374.png)
9、选择如图所示控件,将"objectName"属性变为“label_result”。![](https://i-blog.csdnimg.cn/blog_migrate/fe97bc692c997903604f5069253263ab.png)
10、“ctrl+s”保存文件,文件名为“simple_computer.ui”。
11、在anaconda中将“simple_computer.ui”文件变为“simple_computer.py”。如下图所示:![](https://i-blog.csdnimg.cn/blog_migrate/d10129e9d624e2b3ccd3b010db3b14e8.png)
12、生成的“simple_computer.py”代码如下:
# Form implementation generated from reading ui file 'simple_computer.ui'
#
# Created by: PyQt6 UI code generator 6.4.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_SimpleComputer(object):
def setupUi(self, SimpleComputer):
SimpleComputer.setObjectName("SimpleComputer")
SimpleComputer.resize(400, 300)
SimpleComputer.setStyleSheet("*{\n"
" font-size:16px;\n"
" color:rgb(0, 85, 255);\n"
"}")
self.widget = QtWidgets.QWidget(SimpleComputer)
self.widget.setGeometry(QtCore.QRect(10, 40, 322, 128))
self.widget.setObjectName("widget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(self.widget)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(self.widget)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label_2 = QtWidgets.QLabel(self.widget)
self.label_2.setObjectName("label_2")
self.horizontalLayout_2.addWidget(self.label_2)
self.lineEdit_2 = QtWidgets.QLineEdit(self.widget)
self.lineEdit_2.setText("")
self.lineEdit_2.setObjectName("lineEdit_2")
self.horizontalLayout_2.addWidget(self.lineEdit_2)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.pushButton = QtWidgets.QPushButton(self.widget)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout_3.addWidget(self.pushButton)
self.pushButton_2 = QtWidgets.QPushButton(self.widget)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout_3.addWidget(self.pushButton_2)
self.pushButton_3 = QtWidgets.QPushButton(self.widget)
self.pushButton_3.setObjectName("pushButton_3")
self.horizontalLayout_3.addWidget(self.pushButton_3)
self.pushButton_4 = QtWidgets.QPushButton(self.widget)
self.pushButton_4.setObjectName("pushButton_4")
self.horizontalLayout_3.addWidget(self.pushButton_4)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.label_3 = QtWidgets.QLabel(self.widget)
self.label_3.setObjectName("label_3")
self.verticalLayout.addWidget(self.label_3)
self.retranslateUi(SimpleComputer)
QtCore.QMetaObject.connectSlotsByName(SimpleComputer)
def retranslateUi(self, SimpleComputer):
_translate = QtCore.QCoreApplication.translate
SimpleComputer.setWindowTitle(_translate("SimpleComputer", "简单计算器"))
self.label.setText(_translate("SimpleComputer", "请输入第一个数字:"))
self.label_2.setText(_translate("SimpleComputer", "请输入第二个数字:"))
self.pushButton.setText(_translate("SimpleComputer", "+"))
self.pushButton_2.setText(_translate("SimpleComputer", "-"))
self.pushButton_3.setText(_translate("SimpleComputer", "*"))
self.pushButton_4.setText(_translate("SimpleComputer", "/"))
self.label_3.setText(_translate("SimpleComputer", "结果:3+5=8"))
13、在“simple_computer.py”文件同级建立“simple_computer_main.py”文件。代码如下:
#引入系统模块
import sys
#引入PyQt6模块
from PyQt6.QtWidgets import (
QApplication,QDialog,QMessageBox
)
#引入平级的simple_computer模块
import simple_computer
#创建MySimpleCompute类
class MySimpleCompute(simple_computer.Ui_SimpleComputer,QDialog):
#创建构造函数
def __init__(self):
#继承父类
super().__init__()
#调用父类的setupUi函数
self.setupUi(self)
#调用显示窗口
self.show()
#将pushButton_add绑定事件函数,进行加法计算
self.pushButton_add.clicked.connect(self.do_compute("add"))
# 将pushButton_sub绑定事件函数,进行减法计算
self.pushButton_sub.clicked.connect(self.do_compute("sub"))
# 将pushButton_mul绑定事件函数,进行乘法计算
self.pushButton_mul.clicked.connect(self.do_compute("mul"))
# 将pushButton_dovide绑定事件函数,进行除法计算
self.pushButton_divide.clicked.connect(self.do_compute("div"))
#创建do_compute函数,执行具体的计算
def do_compute(self,method):
#创建do_compute的内部函数
def compute():
# 将lineEdit_first的文本属性赋值给first
first = self.lineEdit_first.text()
second = self.lineEdit_second.text()
# 判断lineEdit_first的输入是否为文本,如果不是,弹出提示框
try:
first = float(first)
except:
QMessageBox.warning(self, "信息提示", "第一个数字,不是数字,请重新输入")
# 判断lineEdit_second的输入是否为文本,如果不是,弹出提示框
try:
second = float(second)
except:
QMessageBox.warning(self, "信息提示", "第二个数字,不是数字,请重新输入")
#运算符号的初始值为空
symbol=""
#运算结果的初始值为0
result=0
#加法运算
if method=="add":
result=first+second
symbol="+"
#减法运算
elif method=="sub":
result=first-second
symbol = "-"
#乘法运算
elif method=="mul":
result=first*second
symbol = "*"
#除法运算
elif method=="div":
#判断分母是否为0,若为0,弹出警告框
if second==0:
QMessageBox.warning(self,"信息提示","除法的时候,第二个数字不能为0")
result=round(first/second,2)
symbol = "/"
#将运算结果赋值为label_result
self.label_result.setText(f"结果:{first}{symbol}{second}={result}")
#如果运算成功,弹出“计算成功”的提示信息
QMessageBox.information(self,"信息提示","计算成功")
return
return compute
if __name__ == '__main__':
#app的入口函数
app=QApplication(sys.argv)
#初始化类MySimpleCompute函数
mySimpleCompute=MySimpleCompute()
#退出系统
sys.exit(app.exec())
五、pyinstaller打包命令
1、在Anaconda终端输入以下命令:
pyinstaller -F -w bmi_compute_main.py
对文件进行打包。如图;
2、打包后的文件如图所示:
六、小结
小北通过一个计算器的例子,演示PyQt6的简单应用,虽然跟Python的应用关系不大,所以放在了最后,希望对友友们的学习也能有所帮助~
(后续的内容就是小北在做PYQT时候的一些分享,感兴趣的又有可以参与学习,找小北我继续讨论鸭~)
UI文件编译成Python后部分代码 :
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "简易计算器"))
self.label_2.setText(_translate("MainWindow", "简易计算器"))
self.label_3.setText(_translate("MainWindow", "输入:"))
self.label_4.setText(_translate("MainWindow", "结果:"))
self.but7.setText(_translate("MainWindow", "7"))
self.pushButton.setText(_translate("MainWindow", "退格"))
self.butMul.setText(_translate("MainWindow", "*"))
self.but4.setText(_translate("MainWindow", "4"))
self.butclar.setText(_translate("MainWindow", "清除"))
self.butMul_3.setText(_translate("MainWindow", "e"))
self.butMul_2.setText(_translate("MainWindow", "π"))
self.butDot.setText(_translate("MainWindow", "."))
self.but6.setText(_translate("MainWindow", "6"))
self.but0.setText(_translate("MainWindow", "0"))
self.but5.setText(_translate("MainWindow", "5"))
self.butSub.setText(_translate("MainWindow", "-"))
self.but9.setText(_translate("MainWindow", "9"))
self.but00.setText(_translate("MainWindow", "00"))
self.butAdd.setText(_translate("MainWindow", "+"))
self.but2.setText(_translate("MainWindow", "2"))
self.butAdd_3.setText(_translate("MainWindow", ")"))
self.but3.setText(_translate("MainWindow", "3"))
self.but1.setText(_translate("MainWindow", "1"))
self.butDiv.setText(_translate("MainWindow", "/"))
self.but8.setText(_translate("MainWindow", "8"))
self.butClr.setText(_translate("MainWindow", "C"))
self.butEqr.setText(_translate("MainWindow", "="))
self.butAdd_2.setText(_translate("MainWindow", "("))
self.label.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-size:18pt; font-weight:600;\">进制转换:</span></p></body></html>"))
self.butBin.setText(_translate("MainWindow", "二进制"))
self.checkBox.setText(_translate("MainWindow", "二进制直接输入"))
self.butOct.setText(_translate("MainWindow", "八进制"))
self.checkBox1.setText(_translate("MainWindow", "八进制直接输入"))
self.butHex.setText(_translate("MainWindow", "十六进制"))
self.checkBox2.setText(_translate("MainWindow", "十六进制直接输入"))
主程序代码
请注意,在主程序代码编写时,出去基本的MainWindow窗口之外,其它方法实现过程中本人未用面向对象的方式编写,只使用面向过程方式编写,因此代码可能比较冗杂。(注意UI文件的命名必须为MainW)
1.主窗体设置代码
# 系统包
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget
# 项目包
from Ui_MainWindow import Ui_MainWindow
from math import *
from PyQt5.QtCore import *
# 主窗体设置
self.show() #窗口显示
if __name__ == '__main__': #窗口驱动
app = QtWidgets.QApplication(sys.argv)
MainWindow = CMainWindow()
sys.exit(app.exec_())
2.数字按键输入代码
def Push1(self): #数字1输入
c = self.checkBox.isChecked() #c、d、e分别代表二、八、十六进制
d = self.checkBox1.isChecked()# 当所对应选项卡勾选时,返回True
e = self.checkBox2.isChecked()#未勾选时,返回False
if c == True: #二进制勾选时,将1写入二进制对应的文本框中
self.txtBin.insert("1")
if d == True: #二进制勾选时,将1写入八进制对应的文本框中
self.txtOct.insert("1")
if e == True: #二进制勾选时,将1写入十六进制对应的文本框中
self.txtHex.insert("1")
if c == False and d == False and e == False:#都未勾选时
self.txtDisplay.insert("1") #将数字写入到计算文本框中
这里只展示数字一的按键输入,其它数字的按键输入与此类似。
解析:因为使用的QCheckBox控件,勾选时返回True,未勾选时返回False,所以我们在这里可以通过勾没勾选来选择将数据输入到那个文本框中。
3.数字键盘输入代码
def keyPressEvent(self, event):
if (event.key() == Qt.Key_1): #当键盘1按键按下时
c = self.checkBox.isChecked()
d = self.checkBox1.isChecked()
e = self.checkBox2.isChecked()
if c == True:
self.txtBin.insert("1")
if d == True:
self.txtOct.insert("1")
if e == True:
self.txtHex.insert("1")
if c == False and d == False and e == False:
self.txtDisplay.insert("1")
这里只展示数字一的键盘输入,其它数字的输入与此类似。
相较于数字按键输入,这里之多了两行代码,其余部分与数字按键输入相同
def keyPressEvent(self, event):
if (event.key() == Qt.Key_1):#当键盘1按下时
在这里定义一个键盘输入方法,当event事件返回的数值等于键盘1的数值时,执行。若不知道怎么表示按键( Qt.Key_1),则可以换成键盘对应代码,如 event.key() == 52 (同等于event.key() == Qt.Key_4)。在这里小北会列出一部分按键代码,供友友们参考~
1 2 3 4 5 6 7
49 50 51 52 53 54 55
8 9 0 + - * /
56 57 48 45 45 42 47
4.按键清除代码
def Pushclar(self): #清除
c = self.checkBox.isChecked()
d = self.checkBox1.isChecked()
e = self.checkBox2.isChecked()
if c == True:
self.txtBin.clear()
if d == True:
self.txtOct.clear()
if e == True:
self.txtHex.clear()
if c == False and d == False and e == False:
self.txtNumber.clear()
self.txtOct.clear()
self.txtBin.clear()
self.txtHex.clear()
逻辑判断大体与上面相同,使用self.文本名.clear()对指定文本进行清除,这里我们不过多赘述。但要注意,上述的写法当对应进制被勾选时,清除勾选进制的文本,若都未勾选,则清除计算结果和所有进制文本。
5.运算代码
def calculate(self):
c = self.checkBox.isChecked()
d = self.checkBox1.isChecked()
e = self.checkBox2.isChecked()
text = self.txtDisplay.text()
if c == False and d == False and e == False:
try:
self.txtNumber.setText(str(eval(text)))
#self.txtDisplay.setText(str(eval(text)))
#eval() 函数用来执行一个字符串表达式,并返回表达式的值。
except:
self.txtNumber.setText('错误')
6.进制转换代码
def PushHex(self):
c = self.checkBox.isChecked()
d = self.checkBox1.isChecked()
e = self.checkBox2.isChecked()
if e == True:
try:
e = float(self.txtHex.text())
f = int(round(e,0))
i = hex(f)
self.txtHex.setText(str(i))
except:
self.txtNumber.setText("数据有误,请重新输入")
elif c == False and d == False and e == False:
try:
e = float(self.txtNumber.text())
f = int(round(e,0))
i = hex(f)
self.txtHex.setText(str(i))
except:
self.txtNumber.setText("数据有误,请重新输入")
我们以十六进制举例,二进制与八进制同理。
c、d、e还是读取是否勾选,若十六进制被勾选时,代码执行的是读取十六进制文本中的数据,先转换为float类型,之后通过round函数进行四舍五入,在转换为int类型,最后利用Hex函数进行进制的转换,在输出到十六进制文本框中。若十六进制未被勾选,则读取计算结果文本框中数据容,先转换为float类型,之后通过round函数进行四舍五入,在转换为int类型,最后利用Hex函数进行进制的转换,输出到十六进制文本框中。比较啰嗦,但是较好理解与实现。
7.按键与键盘退格代码
def backspace(self): #按键退格
c = self.checkBox.isChecked()
d = self.checkBox1.isChecked()
e = self.checkBox2.isChecked()
if c == True:
self.txtBin.backspace()
if d == True:
self.txtOct.backspace()
if e == True:
self.txtHex.backspace()
if c == False and d == False and e == False:
self.txtDisplay.backspace()
def keyPressEvent(self, event):
if (event.key() == 16777219): #按键按下退格时
c = self.checkBox.isChecked()
d = self.checkBox1.isChecked()
e = self.checkBox2.isChecked()
if c == True:
self.txtBin.backspace()
if d == True:
self.txtOct.backspace()
if e == True:
self.txtHex.backspace()
if c == False and d == False and e == False:
self.txtDisplay.backspace()
按键退格与键盘退格也是类似。都是先读取选中的那个文本,在进行相应的退格。但是退格不能再输出文本框应用。
Python——PYQT5的计算器(源码+打包)
一、效果图
只是单纯的练手,然后再学习一下如何打包
二、源码
三、如何打包
安装PyInstaller
pip install pyinstaller
VS Code终端不行 ,我们试试"cmd"
(出现问题:Python | pyinstaller不是内部或外部命令的解决方法)
使用命令pip install pyinstaller
并使用pip list
检查是否安装成功
设置Python环境变量
右键此电脑-高级系统设置-环境变量-系统变量-Path
安装:
pip install pyinstaller
重点:可单独建立虚拟环境打包,不然可能文件会很大
eg:
pyinstaller -w -F --icon=icon.ico video_collect.py
Error1
No such file or directory: 'C:\Users\yuyang\AppData\Local\Temp\_MExx\xxxx\xx错误
命名一个hook-xxxx的py文件,xxxx代表包名,本例中为uiautomator2
在.py中写入:
from PyInstaller.utils.hooks import collect_data_files
datas = collect_data_files(package="xxxx", include_py_files=True) #include_py_files=True,代表要copy的文件包含脚本文件,此处False报错
保存将此py文件放入Pyinstaller下的hook的文件夹中,重新打包spec。
pyinstaller -F absoultpath.py
Error2
打开界面后显示No module requests;
解决:
1、pip install requests
2、卸载pyinstaller,重新安装
3、重新开启命令行
Error3
问题分析:
原因是pyinstaller 不在Python的环境变量中无法直接运行
1.查看是否安装成功pyinstaller。执行命令 pip show pyinstaller
2.确认Python环境变量是否正常,执行命令python
Python环境正常,pyinstaller安装页成功了。基本就可以确定问题了。是因为所安装的第三方包不在Python的环境里。找到Python的位置
Python 3.12.1安装pyinstaller却没有.exe文件
C:\Python312\Lib\site-packages
已经安装好了pyinstaller,但是在终端执行时报错:
pyinstaller : 无法将“pyinstaller”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
所在位置 行:1 字符: 1
+ pyinstaller --onefile MySc.py
+ ~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (pyinstaller:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
原因:没有添加系统环境变量
首先我们找到pyinstaller库安装的位置:
在文件里面打开设置,找到Python解释器,在软件包里面找到 pyinstaller ,此时将鼠标悬停在上面,则会显示出该软件包所在绝对路径。
之后再次打开终端执行命令:pyinstaller --onefile 文件名
将该目录也按第二种方法添加到Path系统环境变量中即可!!!
快速打包命令:
pyinstaller -wF -i logo.ico main.py
main.py:是我要打包的python项目文件
-i:为main.exe文件指定的图标(如果没有,则不需要该参数)
logo.ico :生成.exe文件的图标(推荐一个在线转换ico图标的网址)
-F:生成结果是一个exe文件,所有的第三方依赖、资源和代码均被打包进该exe内
-w :不显示命令行窗口(如不用此参数,打包后的程序在运行时会弹出一个命令行窗口)
打包成功
基本用法 : pyinstaller [选项] 文件名.py
常用选项
-F, --onefile:将应用程序打包为单个可执行文件
-D, --onedir:将应用程序打包为目录
-c, --console:使用控制台模式(在终端窗口中运行应用程序)
-w, --noconsole:使用Windows模式(没有控制台窗口)
--name:指定应用程序的名称
--distpath:指定输出目录
--clean:在打包之前清除临时文件夹日志
-d, --debug:生成运行时调试器
--log-level:设置日志级别,供调试嵌入其他文件
--add-data:将data文件夹嵌入到生成的可执行文件中
--add-binary:将binary文件与其他文件一起嵌入到可执行文件中
--hidden-import:打包特定的Python库,例如--hidden-import=PIL
--version:显示版本信息
--help:显示帮助信息
以上是_pyinstaller的常用选项和命令,可以根据需要进行选择和使用。
有时候,打包exe程序后的文件大小会非常大!如何减小呢?
四、如何减小打包程序大小(方法1)
1、安装pipenv
pip install pipenv
2、新建一个文件夹
安装完成后,随便找一个盘符,在这个盘符的根目录(最好是根目录)新建一个文件夹,作为虚拟环境,然后双击进入该文件夹3、安装python版本(在虚拟环境下安装所需的python版本)
pipenv install -python 3.6
系统有可能提示无法转换为 “utf-8”,具体原因是因为中文转码的问题,但是不必深究。
这时候最好的方法是重启电脑
重启电脑后,不要打开任何其他程序,重复上述第2步
4、激活虚拟环境(在命令行下)
pipenv shell
如何系统提示无法转换为“utf-8”,则再次重启电脑
然后重新进入power shell,再尝试运行 pipenv shell
5、安装需要的库(仅需安装需要打包的.py文件中所用到的库)
根据要打包的程序中需要导入的库,在pipenv环境下重新安装,例如:pipenv install pyinstaller pipenv install removebg
6、进行打包
把py脚本文件复制到这个新建的目录下,重新运行 pyinstallerpyinstaller -wF -i logo.ico main.py
五、如何减小打包程序大小(方法2)
使用 PyInstaller 将 PyQt5 程序打包成 exe 文件,并用 UPX 压缩生成的文件,即可生成尽可能小的 exe 文件。
1、安装 PyInstaller 和 UPX
打开命令行窗口(Windows 下可以按下 Win+R 后,输入 cmd 启动),输入以下命令安装 PyInstaller 和 UPX:
pip install pyinstaller pip install upx
2、创建 PyInstaller 打包配置文件
在 PyInstaller 命令行中输入以下命令,创建一个打包配置文件 myapp.spec:
pyinstaller -y -w myapp.py
-y 表示自动覆盖现有的 build 和 dist 文件夹
-w 表示去除控制台窗口
此时当前目录会出现一个 build 文件夹和一个 dist 文件夹,dist 文件夹中会生成一个不压缩的 exe 文件。
3、修改 PyInstaller 打包配置文件
在当前目录下,使用编辑器打开 myapp.spec
文件,添加以下代码:
import upx
upx_path = "your_upx_path" # UPX 所在路径
a = Analysis(['myapp.py'],
pathex=['your_path_for_py_file'], # myapp.py 所在路径
binaries=[],
datas=[],
hiddenimports=['sip', 'PyQt5.QtCore', 'PyQt5.QtGui', 'PyQt5.QtWidgets'],
hookspath=['hooks'],
runtime_tmpdir=None,
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
alg='AES256',
key=None,
upx=True, # 是否开启压缩
upx_path=upx_path, # UPX 所在路径
console=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=None,
alg='AES256',
key=None,
unbuffered=False)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='myapp',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True, # 经过测试,tostring() 或 tobytes() 方法生成的资源文件即是这里的 a.zipped_data
upx_path=upx_path, # UPX 所在路径
upx_exclude=[],
runtime_tmpdir=None,
console=False,
icon=None)
注意:
upx_path
需要填写 UPX.exe 所在的文件夹路径
hiddenimports
需要添加 PyQt5 相关的模块
4、打包 exe 文件
在命令行中输入以下命令,将 myapp.spec 文件转换为 exe 文件:
pyinstaller -y -c myapp.spec
生成的文件在 dist 文件夹内,文件名是在 myapp.spec 文件中 name 参数指定的。
-c 表示使用控制台程序,如果不需要控制台程序,可以将 -c 改为 -w。
5、使用 UPX 压缩 exe 文件
在命令行中输入以下命令,使用 UPX 压缩 exe 文件:
upx --best myapp.exe
myapp.exe
是需要压缩的文件名
--best
表示使用最高级别的压缩
附代码:
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QMainWindow, QApplication
from calculator import Ui_calculator_MainWindow
class MyMainForm(QMainWindow, Ui_calculator_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.start_x = None
self.start_y = None
self.anim=None
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.setWindowFlags(Qt.FramelessWindowHint) # 设置窗口标志:隐藏窗口边框
# Bind button scale up and scale down
self.btn_max.clicked.connect(self.btn_max_click)
self.btn_min.clicked.connect(self.minimize)
self.btn_stop.clicked.connect(self.closeEvent)
# 输入
self.input = ''
# 绑定方法
self.bin_number()
# 输入显示
def add_input(self,input):
self.input +=input
self.number_input.setPlainText(str(self.input))
# 计算结果
def calculate_res(self):
try:
self.number_output.display(eval(self.input))
except Exception:
self.number_input.setPlainText('输入格式错误!')
self.input = ''
finally:
# self.input = ''
pass
# clear LCD number
def clear_input(self):
self.input = ''
self.number_input.setPlainText('')
# back one number
def back_number(self):
self.input = self.input[:-1]
self.number_input.setPlainText(self.input)
# add button events
def bin_number(self):
# number events
self.b_one.clicked.connect(lambda: self.add_input('1'))
self.b_tow.clicked.connect(lambda: self.add_input('2'))
self.b_three.clicked.connect(lambda: self.add_input('3'))
self.b_four.clicked.connect(lambda: self.add_input('4'))
self.b_five.clicked.connect(lambda: self.add_input('5'))
self.b_six.clicked.connect(lambda: self.add_input('6'))
self.b_seven.clicked.connect(lambda: self.add_input('7'))
self.b_eight.clicked.connect(lambda: self.add_input('8'))
self.b_nine.clicked.connect(lambda: self.add_input('9'))
self.b_point.clicked.connect(lambda: self.add_input('.'))
self.b_add.clicked.connect(lambda: self.add_input('+'))
self.b_divide.clicked.connect(lambda: self.add_input('/'))
self.b_multiple.clicked.connect(lambda: self.add_input('*'))
self.a_substract.clicked.connect(lambda: self.add_input('-'))
# calculate result
self.b_equal.clicked.connect(lambda: self.calculate_res())
# back one number
self.b_back.clicked.connect(lambda: self.back_number())
# clear input
self.b_clear.clicked.connect(lambda: self.clear_input())
# Window scale up and scale down
def btn_max_click(self):
if self.isMaximized():
self.showNormal()
# self.btn_stop.setText('放大窗口')
else:
self.showMaximized()
# self.btn_stop.setText('缩小窗口')
# 重写 closeEvent 函数,关闭窗口并停止程序运行
def closeEvent(self, event):
sys.exit()
# 最小化窗口
def minimize(self):
self.showMinimized()
# 鼠标左键释放时被触发
def mouseReleaseEvent(self, event):
self.start_x = None
self.start_y = None
# 在鼠标左键按下时被触发
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
super(MyMainForm, self).mousePressEvent(event)
self.start_x = event.x()
self.start_y = event.y()
# 在鼠标移动时被触发
def mouseMoveEvent(self, event):
try:
super(MyMainForm, self).mouseMoveEvent(event)
dis_x = event.x() - self.start_x
dis_y = event.y() - self.start_y
self.move(self.x() + dis_x, self.y() + dis_y)
except:
pass
# 窗口设置阴影效果
def effect_shadow_style(self, widget):
effect_shadow = QtWidgets.QGraphicsDropShadowEffect(self)
effect_shadow.setOffset(12, 12) # 偏移
effect_shadow.setBlurRadius(128) # 阴影半径
effect_shadow.setColor(QColor(155, 230, 237, 150)) # 阴影颜色
widget.setGraphicsEffect(effect_shadow)
# 背景渐变
# def paintEvent(self, event):
# painter = QPainter(self)
# gradient = QLinearGradient(0, 0, self.width(), self.height())
# gradient.setColorAt(0, QColor(89, 217, 212, 128))
# gradient.setColorAt(1, QColor(104, 202, 237, 128))
# gradient.setStart(0, 0)
# gradient.setFinalStop(self.width(), self.height())
# painter.setBrush(gradient)
# painter.drawRect(self.rect())
if __name__ == "__main__":
app = QApplication(sys.argv)
myWin = MyMainForm()
myWin.show()
# myWin.btn_img.clicked.connect(click())
sys.exit(app.exec_())
学习视频
【已完结】PySide6百炼成真,带你系统性入门Qt_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1c84y1N7iL/
【已完结】PySide6百炼成真,带你系统性入门Qt
计算器这个案例就是跟着这个视频里做的!打call!很赞的教程!