美妆网站开发背景/外链兔
上一篇:Python小试牛刀:GUI(图形界面)实现计算器UI界面(二)-CSDN博客
回顾前两篇文章,第一篇文章主要实现了计算器UI界面如何布局,以及简单概述Python常用的GUI库。第二篇文章主要实现了计算器UI界面按钮组件与事件的交互,而在本片文章则是实现计算器完整功能。
运行结果:
代码设计
"""计算器
"""# 通配符'*'
__all__ = ['main']# 计算器UI设计
class CalculatorUI:import tkinter as tkfrom tkinter import fontbase = tk.Tk() # 新建窗口base.title('计算器') # 设置标题base.geometry("458x400") # 设置窗口像素大小# 全局变量labelData1 = tk.StringVar() # 标签数据labelData2 = tk.StringVar() # 标签数据# 设置字体样式setChineseFont = font.Font(family='Arial', size=20, weight='bold')setFont = font.Font(family='Helvetica', size=12, weight='bold')# 主框架mainFrame = tk.LabelFrame(base, text='标准', borderwidth=2, relief=tk.FLAT, font=setChineseFont)mainFrame.pack(expand=True)# 标签框架labelFrame = tk.Frame(mainFrame, borderwidth=2, relief=tk.GROOVE)labelFrame.grid(columnspan=4)# 标签showLabel1 = tk.Label(labelFrame, textvariable=labelData1, anchor='e', width=26, font=setChineseFont)showLabel1.pack()showLabel2 = tk.Label(labelFrame, textvariable=labelData2, anchor='e', width=26, font=setChineseFont)showLabel2.pack()# 删除按钮clear = tk.Button(mainFrame, text='C', width=10, height=2, font=setFont)clear.grid(row=1, column=0)# 退格按钮backSpace = tk.Button(mainFrame, text='⬅', width=10, height=2, font=setFont)backSpace.grid(row=1, column=1)# 余数(百分号)remainder = tk.Button(mainFrame, text='%', width=10, height=2, font=setFont)remainder.grid(row=1, column=2)# 除号division = tk.Button(mainFrame, text='➗', width=10, height=2, font=setFont)division.grid(row=1, column=3)# 7seven = tk.Button(mainFrame, text='7', width=10, height=2, font=setFont)seven.grid(row=2, column=0)# 8eight = tk.Button(mainFrame, text='8', width=10, height=2, font=setFont)eight.grid(row=2, column=1)# 9nine = tk.Button(mainFrame, text='9', width=10, height=2, font=setFont)nine.grid(row=2, column=2)# 乘号multiplication = tk.Button(mainFrame, text='✖', width=10, height=2, font=setFont)multiplication.grid(row=2, column=3)# 4four = tk.Button(mainFrame, text='4', width=10, height=2, font=setFont)four.grid(row=3, column=0)# 5five = tk.Button(mainFrame, text='5', width=10, height=2, font=setFont)five.grid(row=3, column=1)# 6six = tk.Button(mainFrame, text='6', width=10, height=2, font=setFont)six.grid(row=3, column=2)# 减法subtraction = tk.Button(mainFrame, text='➖', width=10, height=2, font=setFont)subtraction.grid(row=3, column=3)# 1one = tk.Button(mainFrame, text='1', width=10, height=2, font=setFont)one.grid(row=4, column=0)# 2two = tk.Button(mainFrame, text='2', width=10, height=2, font=setFont)two.grid(row=4, column=1)# 3three = tk.Button(mainFrame, text='3', width=10, height=2, font=setFont)three.grid(row=4, column=2)# 加法addition = tk.Button(mainFrame, text='➕', width=10, height=2, font=setFont)addition.grid(row=4, column=3)# 括号brackets = tk.Button(mainFrame, text='( )', width=10, height=2, font=setFont)brackets.grid(row=5, column=0)# 0zero = tk.Button(mainFrame, text='0', width=10, height=2, font=setFont)zero.grid(row=5, column=1)# 小数点.dit = tk.Button(mainFrame, text='.', width=10, height=2, font=setFont)dit.grid(row=5, column=2)# 等于equal = tk.Button(mainFrame, text='=', width=10, height=2, background='#00BFFF', font=setFont)equal.grid(row=5, column=3)# 按钮间距tk.Label(mainFrame, height=3, width=1).grid(row=1, column=4) # 行填充tk.Label(mainFrame, height=3, width=1).grid(row=2, column=4)tk.Label(mainFrame, height=3, width=1).grid(row=3, column=4)tk.Label(mainFrame, height=3, width=1).grid(row=4, column=4)tk.Label(mainFrame, height=3, width=1).grid(row=5, column=4)tk.Label(mainFrame, height=1, width=16).grid(row=6, column=1) # 列填充tk.Label(mainFrame, height=1, width=16).grid(row=6, column=3)# 初始化事件
def initUI(event):# 0-9UI.zero.config(background='#f0f0f0') # 0UI.one.config(background='#f0f0f0') # 1UI.two.config(background='#f0f0f0') # 2UI.three.config(background='#f0f0f0') # 3UI.four.config(background='#f0f0f0') # 4UI.five.config(background='#f0f0f0') # 5UI.six.config(background='#f0f0f0') # 6UI.seven.config(background='#f0f0f0') # 7UI.eight.config(background='#f0f0f0') # 8UI.nine.config(background='#f0f0f0') # 9# 特殊字符UI.clear.config(background='#f0f0f0') # 删除UI.backSpace.config(background='#f0f0f0') # 退格UI.remainder.config(background='#f0f0f0') # 百分号/求余UI.division.config(background='#f0f0f0') # 除号UI.multiplication.config(background='#f0f0f0') # 乘号UI.subtraction.config(background='#f0f0f0') # 减号UI.addition.config(background='#f0f0f0') # 加号UI.equal.config(background='#00BFFF') # 等于UI.brackets.config(background='#f0f0f0') # 括号UI.dit.config(background='#f0f0f0') # 小数点# 鼠标在组件上的焦点事件
# 0-9
# 0
def zeroBackground(event):UI.zero.config(background='pink')
def zeroReleaseBackground(event):UI.zero.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.zero.config(state=tk.NORMAL, background='#f0f0f0')zeroEvent(event)
# 1
def oneBackground(event):UI.one.config(background='pink')
def oneReleaseBackground(event):UI.one.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.one.config(state=tk.NORMAL, background='#f0f0f0')oneEvent(event)
# 2
def twoBackground(event):UI.two.config(background='pink')
def twoReleaseBackground(event):UI.two.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.two.config(state=tk.NORMAL, background='#f0f0f0')twoEvent(event)
# 3
def threeBackground(event):UI.three.config(background='pink')
def threeReleaseBackground(event):UI.three.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.three.config(state=tk.NORMAL, background='#f0f0f0')threeEvent(event)
# 4
def fourBackground(event):UI.four.config(background='pink')
def fourReleaseBackground(event):UI.four.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.four.config(state=tk.NORMAL, background='#f0f0f0')fourEvent(event)
# 5
def fiveBackground(event):UI.five.config(background='pink')
def fiveReleaseBackground(event):UI.five.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.five.config(state=tk.NORMAL, background='#f0f0f0')fiveEvent(event)
# 6
def sixBackground(event):UI.six.config(background='pink')
def sixReleaseBackground(event):UI.six.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.six.config(state=tk.NORMAL, background='#f0f0f0')sixEvent(event)
# 7
def sevenBackground(event):UI.seven.config(background='pink')
def sevenReleaseBackground(event):UI.seven.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.seven.config(state=tk.NORMAL, background='#f0f0f0')sevenEvent(event)
# 8
def eightBackground(event):UI.eight.config(background='pink')
def eightReleaseBackground(event):UI.eight.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.eight.config(state=tk.NORMAL, background='#f0f0f0')eightEvent(event)
# 9
def nineBackground(event):UI.nine.config(background='pink')
def nineReleaseBackground(event):UI.nine.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.nine.config(state=tk.NORMAL, background='#f0f0f0')nineEvent(event)# 特殊字符
# 删除
def clearBackground(event):UI.clear.config(background='pink')
def clearReleaseBackground(event):UI.clear.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.clear.config(state=tk.NORMAL, background='#f0f0f0')clearEvent(event)
# 退格
def backSpaceBackground(event):UI.backSpace.config(background='pink')
def backSpaceReleaseBackground(event):UI.backSpace.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.backSpace.config(state=tk.NORMAL, background='#f0f0f0')backSpaceEvent(event)
# 百分号/求余
def remainderBackground(event):UI.remainder.config(background='pink')
def remainderReleaseBackground(event):UI.remainder.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.remainder.config(state=tk.NORMAL, background='#f0f0f0')remainderEvent(event)
# 除号
def divisionBackground(event):UI.division.config(background='pink')
def divisionReleaseBackground(event):UI.division.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.division.config(state=tk.NORMAL, background='#f0f0f0')divisionEvent(event)
# 乘号
def multiplicationBackground(event):UI.multiplication.config(background='pink')
def multiplicationReleaseBackground(event):UI.multiplication.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.multiplication.config(state=tk.NORMAL, background='#f0f0f0')multiplicationEvent(event)
# 减号
def subtractionBackground(event):UI.subtraction.config(background='pink')
def subtractionReleaseBackground(event):UI.subtraction.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.subtraction.config(state=tk.NORMAL, background='#f0f0f0')subtractionEvent(event)
# 加号
def additionBackground(event):UI.addition.config(background='pink')
def additionReleaseBackground(event):UI.addition.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.addition.config(state=tk.NORMAL, background='#f0f0f0')additionEvent(event)
# 等于
def equalBackground(event):UI.equal.config(background='pink')
def equalReleaseBackground(event):UI.equal.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.equal.config(state=tk.NORMAL, background='#00BFFF')equalEvent(event)
# 括号
def bracketsBackground(event):UI.brackets.config(background='pink')
def bracketsReleaseBackground(event):UI.brackets.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.brackets.config(state=tk.NORMAL, background='#f0f0f0')bracketsEvent(event)
# 小数点
def ditBackground(event):UI.dit.config(background='pink')
def ditReleaseBackground(event):UI.dit.config(state=tk.DISABLED, background='pink')UI.base.update()time.sleep(0.1)UI.dit.config(state=tk.NORMAL, background='#f0f0f0')ditEvent(event)# 组件背景颜色事件触发
def widgetColor():# 初始化UI.base.bind('<Leave>', initUI)UI.showLabel1.config(foreground='gray', background='white')UI.showLabel2.config(background='white')# 0-9UI.zero.bind('<Motion>', zeroBackground) # 0UI.one.bind('<Motion>', oneBackground) # 1UI.two.bind('<Motion>', twoBackground) # 2UI.three.bind('<Motion>', threeBackground) # 3UI.four.bind('<Motion>', fourBackground) # 4UI.five.bind('<Motion>', fiveBackground) # 5UI.six.bind('<Motion>', sixBackground) # 6UI.seven.bind('<Motion>', sevenBackground) # 7UI.eight.bind('<Motion>', eightBackground) # 8UI.nine.bind('<Motion>', nineBackground) # 9# 特殊字符UI.clear.bind('<Motion>', clearBackground) # 删除UI.backSpace.bind('<Motion>', backSpaceBackground) # 退格UI.remainder.bind('<Motion>', remainderBackground) # 百分号/求余UI.division.bind('<Motion>', divisionBackground) # 除号UI.multiplication.bind('<Motion>', multiplicationBackground) # 乘号UI.subtraction.bind('<Motion>', subtractionBackground) # 减号UI.addition.bind('<Motion>', additionBackground) # 加号UI.equal.bind('<Motion>', equalBackground) # 等于UI.brackets.bind('<Motion>', bracketsBackground) # 括号UI.dit.bind('<Motion>', ditBackground) # 小数点# 按钮按下UI.base.bind('<KeyPress-0>', zeroReleaseBackground) # 0UI.zero.bind('<Button-1>', zeroEvent)UI.base.bind('<KeyPress-1>', oneReleaseBackground) # 1UI.one.bind('<Button-1>', oneEvent)UI.base.bind('<KeyPress-2>', twoReleaseBackground) # 2UI.two.bind('<Button-1>', twoEvent)UI.base.bind('<KeyPress-3>', threeReleaseBackground) # 3UI.three.bind('<Button-1>', threeEvent)UI.base.bind('<KeyPress-4>', fourReleaseBackground) # 4UI.four.bind('<Button-1>', fourEvent)UI.base.bind('<KeyPress-5>', fiveReleaseBackground) # 5UI.five.bind('<Button-1>', fiveEvent)UI.base.bind('<KeyPress-6>', sixReleaseBackground) # 6UI.six.bind('<Button-1>', sixEvent)UI.base.bind('<KeyPress-7>', sevenReleaseBackground) # 7UI.seven.bind('<Button-1>', sevenEvent)UI.base.bind('<KeyPress-8>', eightReleaseBackground) # 8UI.eight.bind('<Button-1>', eightEvent)UI.base.bind('<KeyPress-9>', nineReleaseBackground) # 9UI.nine.bind('<Button-1>', nineEvent)UI.base.bind('<KeyPress-Delete>', clearReleaseBackground) # 删除UI.base.bind('<KeyPress-c>', clearReleaseBackground) # 删除UI.base.bind('<Key-C>', clearReleaseBackground) # 删除UI.clear.bind('<Button-1>', clearEvent)UI.base.bind('<KeyPress-BackSpace>', backSpaceReleaseBackground) # 退格UI.backSpace.bind('<Button-1>', backSpaceEvent)UI.base.bind('<Shift-Key-%>', remainderReleaseBackground) # 百分号、求余UI.remainder.bind('<Button-1>', remainderEvent)UI.base.bind('<KeyPress-slash>', divisionReleaseBackground) # 除号UI.division.bind('<Button-1>', divisionEvent)UI.base.bind('<KeyPress-asterisk>', multiplicationReleaseBackground) # 乘号UI.base.bind('<Shift-Key-*>', multiplicationReleaseBackground) # 乘号UI.multiplication.bind('<Button-1>', multiplicationEvent)UI.base.bind('<KeyPress-minus>', subtractionReleaseBackground) # 减号UI.subtraction.bind('<Button-1>', subtractionEvent)UI.base.bind('<KeyPress-plus>', additionReleaseBackground) # 加号UI.base.bind('<Shift-Key-+>', additionReleaseBackground) # 加号UI.addition.bind('<Button-1>', additionEvent)UI.base.bind('<KeyPress-Return>', equalReleaseBackground) # 等号UI.base.bind('<KeyPress-equal>', equalReleaseBackground) # 等号UI.equal.bind('<Button-1>', equalEvent)UI.base.bind('<Shift-Key-(>', bracketsReleaseBackground) # 左括号UI.base.bind('<Shift-Key-)>', bracketsReleaseBackground) # 右括号UI.brackets.bind('<Button-1>', bracketsEvent)UI.base.bind('<KeyPress-period>', ditReleaseBackground) # 小数点UI.dit.bind('<Button-1>', ditEvent)# 0 事件
def zeroEvent(event):global labelShow2# 数字前面不能是右括号')'if ('原来是小瘪三'+labelShow2)[-1] in ')=':returnlabelShow2 += '0'# 补小数点if labelShow2 == '0' or labelShow2[-2] in '(+-×÷':labelShow2 += '.'UI.labelData2.set(labelShow2)UI.zero.config(activeforeground='gray')# 1 事件
def oneEvent(event):global labelShow2# 数字前面不能是右括号')'if ('防止空字符'+labelShow2)[-1] in ')=':returnlabelShow2 += '1'UI.labelData2.set(labelShow2)UI.one.config(activeforeground='gray')# 2 事件
def twoEvent(event):global labelShow2# 数字前面不能是右括号')'if ('什么字符都可以'+labelShow2)[-1] in ')=':returnlabelShow2 += '2'UI.labelData2.set(labelShow2)UI.two.config(activeforeground='gray')# 3 事件
def threeEvent(event):global labelShow2# 数字前面不能是右括号')'if ('不影响代码'+labelShow2)[-1] in ')=':returnlabelShow2 += '3'UI.labelData2.set(labelShow2)UI.three.config(activeforeground='gray')# 4 事件
def fourEvent(event):global labelShow2# 数字前面不能是右括号')'if ('虽然可以封装成函数'+labelShow2)[-1] in ')=':returnlabelShow2 += '4'UI.labelData2.set(labelShow2)UI.four.config(activeforeground='gray')# 5 事件
def fiveEvent(event):global labelShow2# 数字前面不能是右括号')'if ('但是只有两行代码'+labelShow2)[-1] in ')=':returnlabelShow2 += '5'UI.labelData2.set(labelShow2)UI.five.config(activeforeground='gray')# 6 事件
def sixEvent(event):global labelShow2# 数字前面不能是右括号')'if ('调用函数还是两行代码'+labelShow2)[-1] in ')=':returnlabelShow2 += '6'UI.labelData2.set(labelShow2)UI.six.config(activeforeground='gray')# 7 事件
def sevenEvent(event):global labelShow2# 数字前面不能是右括号')'if ('索性来个自我介绍吧'+labelShow2)[-1] in ')=':returnlabelShow2 += '7'UI.labelData2.set(labelShow2)UI.seven.config(activeforeground='gray')# 8 事件
def eightEvent(event):global labelShow2# 数字前面不能是右括号')'if ('我是周华2022'+labelShow2)[-1] in ')=':returnlabelShow2 += '8'UI.labelData2.set(labelShow2)UI.eight.config(activeforeground='gray')# 9 事件
def nineEvent(event):global labelShow2# 数字前面不能是右括号')'if ('欢迎大家关注!'+labelShow2)[-1] in ')=':returnlabelShow2 += '9'UI.labelData2.set(labelShow2)UI.nine.config(activeforeground='gray')# 删除 事件
def clearEvent(event):global labelShow2, operator, operationData, bracketsFlag# 数据初始化bracketsFlag = 0labelShow2 = ''operator = []operationData = []UI.labelData2.set(labelShow2)UI.clear.config(activeforeground='gray')# 退格 事件
def backSpaceEvent(event):global labelShow2# 在数据内退格if not operator:labelShow2 = labelShow2[:-1:]# 运算符退格elif operator and operationData:if labelShow2[-1] in '+-×÷%':operator.pop()operationData.pop()labelShow2 = labelShow2[:-1:]UI.labelData2.set(labelShow2)UI.backSpace.config(activeforeground='gray')# 求余 事件
def remainderEvent(event):global labelShow2# 首个字符不能出现百分号/求余if not labelShow2:return# 百分号前面不能出现运算符,除了右括号')'elif labelShow2[-1] in '+-×÷%(.=':return# 分割数据,获取数值和运算符elif not operator:operationData.append(labelShow2)elif operator:operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])operator.append('%')labelShow2 += '%'print(operator, operationData)UI.labelData2.set(labelShow2)UI.remainder.config(activeforeground='gray')# 除法 事件
def divisionEvent(event):global labelShow2# 首个字符不能出现除号if not labelShow2:return# 除号前面不能出现运算符,除了右括号')'和百分号'%'elif labelShow2[-1] in '+-×÷(.=':return# 分割数据,获取数值和运算符elif not operator:operationData.append(labelShow2)elif operator:if labelShow2[-1] == '%':operationData[-1] += operator.pop()else:operationData.append(labelShow2.split(operationData[-1]+operator[-1])[-1])operator.append('÷')labelShow2 += '÷'print(operator, operationData)UI.labelData2.set(labelShow2)UI.division.config(activeforeground='gray')# 乘法 事件
def multiplicationEvent(event):global labelShow2# 首个字符不能出现乘号if not labelShow2:return# 乘号前面不能出现运算符,除了右括号')'和百分号'%'elif labelShow2[-1] in '+-×÷(.=':return# 分割数据,获取数值和运算符elif not operator:operationData.append(labelShow2)elif operator:if labelShow2[-1] == '%':operationData[-1] += operator.pop()else:operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])operator.append('×')labelShow2 += '×'print(operator, operationData)UI.labelData2.set(labelShow2)UI.multiplication.config(activeforeground='gray')# 减法 事件
def subtractionEvent(event):addFlag = 1 # 添加运算符旗帜global labelShow2# 首字符出现减号,视为负号if not labelShow2:addFlag = 0 # 添加运算符旗帜# 减号前面不能出现运算符,除了括号'()'和百分号'%'elif labelShow2[-1] in '+-×÷.=':return# 分割数据,获取数值和运算符elif not operator and labelShow2[-1] not in '(':operationData.append(labelShow2)# 非首个数据elif operator and operationData:if labelShow2[-1] == '%':operationData[-1] += operator.pop()elif labelShow2[-1] == '(':addFlag = 0 # 添加运算符旗帜else:operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])else:addFlag = 0# 不保存运算符旗帜if addFlag:operator.append('-')print(operator, operationData)labelShow2 += '-'UI.labelData2.set(labelShow2)UI.subtraction.config(activeforeground='gray')# 加法 事件
def additionEvent(event):addFlag = 1 # 添加运算符旗帜global labelShow2# 首字符出现加号,视为正号if not labelShow2:addFlag = 0 # 添加运算符旗帜# 加号前面不能出现运算符,除了括号'()'和百分号'%'elif labelShow2[-1] in '+-×÷.=':return# 分割数据,获取数值和运算符elif not operator and labelShow2[-1] not in '(':operationData.append(labelShow2)# 非首个数据elif operator and operationData:if labelShow2[-1] == '%':operationData[-1] += operator.pop()elif labelShow2[-1] == '(':addFlag = 0 # 添加运算符旗帜else:operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])else:addFlag = 0# 不保存运算符旗帜if addFlag:operator.append('+')print(operator, operationData)labelShow2 += '+' # 添加加号UI.labelData2.set(labelShow2)UI.addition.config(activeforeground='gray')# 等于 事件
def equalEvent(event):global labelShow2, labelShow1labelShow1 = labelShow2 # 显示式子# 首字符不能输入等号if not labelShow2:return# 等号前不能出现的运算符,除了数字、右括号、百分号elif labelShow2[-1] in '+-×÷=.':return# 括号必须成对,elif len(re.findall(r'\(', labelShow2)) != len(re.findall(r'\)', labelShow2)):UI.labelData1.set(labelShow1+'=错误')UI.labelData2.set('括号不完整')return# 等号前面不能是不带括号的正数elif not operator and labelShow2[0] != '+' and not len(re.findall(r'\(', labelShow2)):return# 处理等号前面只有一个数时elif not operator or (labelShow2.strip('()+-')[-1] == '%' and len(operator) == 1 and operator[0] == '%'):subtractionNum = len(re.findall('-', labelShow2)) # 减号数# 查找百分号if labelShow2.strip('()+-')[-1] == '%':num = float(labelShow2.strip('()+-%')) / 100# 奇数负为负,偶数负为正if subtractionNum % 2:labelShow2 = str(-num)else:labelShow2 = str(num)elif labelShow2.strip('()+-')[-1] != '%':num = labelShow2.strip('()+-')# 奇数负为负,偶数负为正if subtractionNum % 2:labelShow2 = '-'+numelse:labelShow2 = num# 复杂运算else:# 防止报错try:# 计算式子结果if resultEvent(event) == '求余错误':returnexcept:UI.labelData1.set(labelShow1 + '=崩溃')UI.labelData2.set('抱歉,小算脑子烧坏了')returnprint(operator, operationData)labelShow1 += '='+labelShow2 # 显示计算的式子UI.labelData1.set(labelShow1)UI.labelData2.set(labelShow2)UI.equal.config(activeforeground='gray')# 显示结果后删除存储的数据if operationData:operator.clear()operationData.clear()# 括号 事件
def bracketsEvent(event):global labelShow2, bracketsFlag# 首字符出现左括号'('if not labelShow2:labelShow2 += '('# 左括号前面不能出现数字和小数点elif labelShow2[-1] in '+-×÷(%':labelShow2 += '('# 右括号前面必须是数字和右括号elif labelShow2[-1] not in '+-×÷%(.=' and len(re.findall(r'\(', labelShow2)) != len(re.findall(r'\)', labelShow2)):labelShow2 += ')'# 括号前面的百分号if ('出来单挑啊'+labelShow2)[-2] == '%':bracketsFlag += 1if bracketsFlag % 2:labelShow2 = labelShow2[:-1:]+'('else:labelShow2 = labelShow2[:-1:]+')'UI.labelData2.set(labelShow2)UI.brackets.config(activeforeground='gray')# 小数点 事件
def ditEvent(event):global labelShow2# 小数点开头或者小数点前面是运算符就补零if not labelShow2 or labelShow2[-1] in '(+-×÷%':labelShow2 += '0'# 小数点前面不能是右括号')'elif labelShow2[-1] in ')=':return# 限制小数点输入(一)elif not operator:if len(re.findall(r'\.', labelShow2)) >= 1:return# 限制小数点输入(二)elif operator and operationData:str = labelShow2.split(operationData[-1]+operator[-1])[-1]if len(re.findall(r'\.', str)) >= 1:returnlabelShow2 += '.'UI.labelData2.set(labelShow2)UI.dit.config(activeforeground='gray')# 计算式子结果
def resultEvent(event):global labelShow1, labelShow2, operator, operationData# 分割最后一个数if labelShow2[-1] == '%':operationData[-1] += operator.pop()else:operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])print(operator, operationData)# 化繁为简,逐个括号化简while True:leftBrackets = [] # 左括号rightBrackets = [] # 右括号minBrackets = [] # 最小括号区间# 查找括号,并存储其索引号for i in range(len(operationData)):if '(' in operationData[i]:leftBrackets.append(i)elif ')' in operationData[i]:rightBrackets.append(i)# 判断式子是否有括号if leftBrackets:sign = ''if operationData[leftBrackets[0]][0] == '-':sign = '-'# 找到最里层的括号for i in range(len(rightBrackets)):# 找到了if leftBrackets[-1] < rightBrackets[i]:left = leftBrackets[-1]right = rightBrackets[i]minBrackets.extend([left, right])break# 无括号式子设置if not minBrackets:minBrackets.extend([0, len(operationData)-1])bracketsNum = operationData[minBrackets[0]:minBrackets[1] + 1:]bracketsOperation = operator[minBrackets[0]:minBrackets[1]:]# 左括号数分割bracketsSplit = ''if re.findall(r'\(', bracketsNum[0]):bracketsSplit = bracketsNum[0].split('(')bracketsNum[0] = bracketsSplit[-1]# 化简括号内的式子while True:# 结束循环条件if not bracketsOperation:break# 排除运算错误(除数不为零、求余需整数)for i in range(len(bracketsOperation)):# 让百分号'%'参与运算for j in range(2):if '%' in bracketsNum[i+j]:bracketsNum[i+j] = str(float(bracketsNum[i+j].strip(')')[:-1:])/100)# 查找除号if bracketsOperation[i] == '÷':# 判断除数是否为零if float(bracketsNum[i+1].strip(')')) == 0:UI.labelData1.set(labelShow1 + '=错误')UI.labelData2.set('除数不能为零')return '除数错误'# 查找求余号elif bracketsOperation[i] == '%':# 判断两个数是否为整数for j in range(2):if re.findall(r'\.', bracketsNum[i+j]):UI.labelData1.set(labelShow1 + '=错误')UI.labelData2.set('求余必须为整数')return '求余错误'# 查找乘除求余(优先级高)if bracketsOperation[i] in '×÷%':# 计算两数之积if bracketsOperation[i] == '×':result = float(bracketsNum[i]) * float(bracketsNum[i+1].strip(')'))# 计算两数之商elif bracketsOperation[i] == '÷':result = float(bracketsNum[i]) / float(bracketsNum[i+1].strip(')'))# 计算两数之余elif bracketsOperation[i] == '%':result = float(bracketsNum[i]) % float(bracketsNum[i+1].strip(')'))# 修改括号区间的数据,并进入下一次循环查找bracketsNum.pop(i)bracketsNum.pop(i)bracketsOperation.pop(i)bracketsNum.insert(i, str(result))break# 查找加减(优先级低)elif bracketsOperation[i] in '+-':if '×' in bracketsOperation:continueelif '÷' in bracketsOperation:continueelif '%' in bracketsOperation:continue# 计算两数之和if bracketsOperation[i] == '+':result = float(bracketsNum[i]) + float(bracketsNum[i + 1].strip(')'))# 计算两数之差elif bracketsOperation[i] == '-':result = float(bracketsNum[i]) - float(bracketsNum[i + 1].strip(')'))# 修改括号区间的数据,并进入下一次循环查找bracketsNum.pop(i)bracketsNum.pop(i)bracketsOperation.pop(i)bracketsNum.insert(i, str(result))break# 替换数据之前要补括号leftBracketsNum = len(re.findall(r'\(', operationData[minBrackets[0]]))-1rightBracketsNum = len(re.findall(r'\)', operationData[minBrackets[1]]))-1# 删除数据for i in range(minBrackets[0], minBrackets[1]+1):operationData.pop(minBrackets[0])for i in range(minBrackets[0], minBrackets[1]):operator.pop(minBrackets[0])# 化简一个括号后,根据左括号前正负号改变数值正负号if leftBracketsNum >= 0 and bracketsSplit[-2] == '-':if bracketsNum[0][0] == '-':bracketsNum[0] = bracketsNum[0][1::]else:bracketsNum[0] = '-' + bracketsNum[0]# 合并分割的左括号leftBracketsStr = ''if leftBracketsNum > rightBracketsNum:for i in range(len(bracketsSplit)-2):leftBracketsStr += bracketsSplit[i]+'('bracketsNum[0] = leftBracketsStr + bracketsNum[0]# 补左括号,并插入计算结果数据if leftBracketsNum > rightBracketsNum:operationData.insert(minBrackets[0], f"{bracketsNum[0]}")# 补右括号,并插入计算结果数据elif rightBracketsNum > leftBracketsNum:operationData.insert(minBrackets[0], f"{bracketsNum[0]}{')' * (rightBracketsNum-leftBracketsNum)}")# 删除两边多余的括号,并插入计算结果数据elif leftBracketsNum == rightBracketsNum:string = bracketsNum[0]# 计算左括号的负号数num = 0for i in bracketsSplit[:-2:]:if i == '-':num += 1# 消除括号if leftBracketsNum >= 0 and num:if num % 2:if string[0] == '+':string = '-' + string[1::]elif string[0] != '-':string = '-' + stringelse:if string[0] == '+':string = string[1::]operationData.insert(minBrackets[0], string)# 结束条件循环条件if not operator:labelShow2 = operationData[0]if ('one piece'+operationData[0])[-2::] == '.0':labelShow2 = operationData[0][:-2:]return# 全局变量
import tkinter as tk
import time, re
UI = CalculatorUI() # 计算器UI设计
operator = [] # 运算符
operationData = [] # 运算数据
labelShow1 = '' # 标签内容1
labelShow2 = '' # 标签内容2
bracketsFlag = 0 # 计数旗帜# 主函数
def main():widgetColor() # 组件背景颜色改变UI.base.mainloop() # 保持窗口运行# 代码测试
if __name__ == '__main__':main()
else:print(f'导入{__name__}模块')
作者:周华
创作日期:2023/11/5
相关文章:

Python小试牛刀:GUI(图形界面)实现计算器UI界面(三)
上一篇:Python小试牛刀:GUI(图形界面)实现计算器UI界面(二)-CSDN博客 回顾前两篇文章,第一篇文章主要实现了计算器UI界面如何布局,以及简单概述Python常用的GUI库。第二篇文章主要实现了计算器UI界面按钮组…...

王道计算机网络
一、计算机网络概述 (一)计算机网络基本概念 计算机网络的定义、组成与功能 定义:以能够相互共享资源的方式互连起来的自治计算机系统的集合。 目的:资源共享, 组成单元:自治、互不影响的计算机 网络协议 从不同角度计算机网络…...

【漏洞复现】IIS_7.o7.5解析漏洞
感谢互联网提供分享知识与智慧,在法治的社会里,请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证 1.5、修复建议 1.1、漏洞描述 漏洞原理: cgi.fix_path1 1.png/.php该…...

Java 高效生成按指定间隔连续递增的列表(int,double)
简介 Java 按照指定间隔生成连续递增的List 列表(引入Stream 类和流操作来提高效率): 1. 生成递增的List< Integer> Testpublic void test009(){int start 1;int interval 2;int count 10;List<Integer> list IntStream.ite…...

C++ reference
cppreference.com 《现代C语言核心特性解析》 这是一本 C 进阶图书,全书分为 42 章,深入探讨了从 C11 到 C20 引入的核心特性。 本书不仅通过大量的实例代码讲解特性的概念和语法,还从编译器的角度分析特性的实现原理,让读者…...

关于网站安全的一些讨论
互联网的普及和发展为企业和个人提供了巨大的机会,但同时也伴随着网络安全威胁的增加。网站被攻击是一个常见的问题,可能导致数据泄露、服务中断和声誉受损。在本文中,我们将探讨与网络安全紧密相关的因素,分析为什么网站容易受到…...

unity 截图
unity 截图适用于各分辨率 float scr;void Start(){scr Screen.width /2160.00f;//2160是我做程序时的分辨率 Screen.width为打包后机器的分辨率}/// <summary>/// 区域截图/// </summary>/// <param name"rectT"></param>/// <param …...

浏览器无图模式省流量经验
【备注】本文适合于那些用自购上网卡(非单位报销)、流量费花的心痛、平日里抠抠搜搜的diaosi人群!流量自由人群请关闭退出! 近日图年包流量费便宜,从某东平台上买了一个号称新款usb上网卡,只用了2天时间&a…...

【Hive】分区表和分桶表相关知识点介绍
Hive中的分区表和分桶表是两种用于优化数据查询和管理的技术。它们可以提高查询性能、减少数据扫描量并提供更精细的数据组织方式。 分区表(Partitioned Table) Hive的分区表将数据按照一个或多个列的值进行逻辑分区。每个分区都是一个独立的子目录,其中包含符合该分区条件…...

CLIP Surgery论文阅读
CLIP Surgery for Better Explainability with Enhancement in Open-Vocabulary Tasks(CVPR2023) M norm ( resize ( reshape ( F i ˉ ∥ F i ‾ ∥ 2 ⋅ ( F t ∥ F t ‾ ∥ 2 ) ⊤ ) ) ) M\operatorname{norm}\left(\operatorname{resize}\…...

Luancher和unityLibrary都有build.gradle有什么不同
在 Unity 项目中,通常会包含两个主要的 Module: Launcher Module: 这是 Android 项目的主要 Module,包含 UnityPlayerActivity,并负责启动 Unity 游戏。 unityLibrary Module: 这是 Unity 导出的 Android 工程,其中包…...

【Unity】2D角色跳跃控制器
最近加了学校的Nova独游社,本文是社团出的二面题,后续有时间优化下可能会做成一个二维冒险小游戏。本文主要涉及相关代码,参考教程:《勇士传说》横版动作类游戏开发教程 效果演示 【Unity】2D角色跳跃模拟器 主要实现功能…...

Gradle vs Maven
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。面向Java应用为主。当前其支持的语言限于Java、Groovy、Kotlin和Scala,计划未来将支持更多的…...

Linux认证 | RHCA是什么等级的证书?考到工资能有多少?
RHCA就是红帽认证架构师,RHCA是红帽公司在红帽认证工程师(RHCE)和红帽认证技师(RHCT)认证推出之后又一个最新的顶级认证,在业界也是最受欢迎的、最成熟的linux认证。 那么RHCA是什么等级的证书?…...

SQLite System.Data.SQLite和sqlite-net-pcl之间的区别
System.Data.SQLite System.Data.SQLite是一个.NET数据提供程序,用于操作SQLite数据库。它是在SQLite C语言库之上构建的,提供了以.NET方式访问SQLite数据库的功能。System.Data.SQLite提供了ADO.NET接口,可以与其他关系型数据库一样使用Com…...

【Leetcode】【消失的数字】【C语言】
方法一:按位异或(找单身狗) 我们知道:按位异或^操作原则:相同为零,相异为一 所以 0^aa a ^a0 a ^bb ^a int missingNumber(int* nums, int numsSize){ int i 0; int tem1 0,tem20; for (i 0;i < nu…...

在Linux中安装宝塔面板
在公网为x.x.x.x的服务器上安装宝塔面板 安装宝塔面板 第一步,下载安装宝塔面板。 命令:cd /usr/local/src wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh 注意:需要等几分钟来下载宝塔面…...

数据结构 - 全貌总结
目录 一. 前言 二. 分类 三. 常见的线性和非线性结构 一. 前言 数据结构是计算机存储、组织数据的方式。一种好的数据结构可以带来更高的运行或者存储效率。数据在内存中是呈线性排列的,但是我们可以使用指针等道具,构造出类似“树形”等复杂结构。 数…...

淘宝API商品详情接口丨关键词搜索接口丨用户评论接口丨淘宝销量接口
淘宝API商品详情接口,关键词搜索接口,用户评论接口,淘宝销量接口如下: 淘宝/天猫获得淘宝商品详情 API 返回值说明 item_get-获得淘宝商品详情 1.公共参数 名称类型必须描述keyString是调用key(必须以GET方式拼接在…...

Android开机动画启动流程
首语 在Android设备开机启动时,会展示Android开机动画,用于增加用户体验和展示设备品牌等信息。它也是Android系统启动的一部分。开机动画是由bootanimation负责的,因此首先先了解下bootanimation是如何启动的。 bootanimation 启动脚本分析…...

react_13
React Router //-dom代表给浏览器应用使用的 npm install react-router-dom 目前版本是 "react-router-dom": "^6.18.0" 使用 新建文件 src/router/MyRouter.tsx import { Navigate, RouteObject, useRoutes } from "react-router-dom"; imp…...

vscode git提交
...

LangChain+LLM实战---实用Prompt工程讲解
原文:Practical Prompt Engineering 注:本文中,提示和prompt几乎是等效的。 这是一篇非常全面介绍Prompt的文章,包括prompt作用于大模型的一些内在机制,和prompt可以如何对大模型进行“微调”。讲清楚了我们常常听到的…...

虚拟机备份中的CBT技术
虚拟机备份的CBT( Changed Block Tracking)模式是一种备份模式,它能够识别和跟踪自上次备份后虚拟机中被修改过的块,这些修改会被存放到日志文件中。在启用CBT模式之后,备份软件会利用这个功能进行增量备份。 启用CBT…...

云服务器哪家便宜靠谱 | 简单了解亚马逊云科技发展史
云服务器哪家便宜又靠谱呢?为什么说亚马逊云科技在这道题答案的第一行,一篇故事告诉你。 1994年,杰夫贝索斯在西雅图创建了亚马逊,最初只是一个在线书店。 1997年,亚马逊在纳斯达克交易所上市,成为一家公…...

【LeetCode】每日一题 2023_11_6 最大单词长度乘积
文章目录 刷题前唠嗑题目:最大单词长度乘积题目描述代码与解题思路偷看大佬题解 结语 刷题前唠嗑 LeetCode? 启动!!! 题目:最大单词长度乘积 题目链接:318. 最大单词长度乘积 题目描述 代码与解题思路…...

【小白专用】PHP中的JSON转换操作指南 23.11.06
一、JSON的基础知识 1.1JSON数据格式 JSON数据格式是一组键值对的集合,通过逗号分隔。键值对由“键”和“值”组成,中间使用冒号分隔。JSON数据格式可以嵌套,而且可以使用数组 二、PHP中的JSON函数 JSON的操作需要使用编程语言进行处理&am…...

Web3游戏的十字路口:沿用传统IP还是另起炉灶?
人们经常问我对 Web3 游戏有什么看法。因此,我想以书面形式概述一下我目前的想法。 让我先澄清一下:我不是专家。这不是一篇深入探讨游戏世界精细指标如 MAU 或 D14 等的全面分析。请把这看作是我根据个人交流和研究,这反映我在游戏领域关注…...

【系统架构设计】架构核心知识:4 系统可靠性分析与设计
目录 1 可靠性 2 系统可靠性 2.1 可靠性指标 2.2 可靠性计算 2.2.1 串联系统 2.2.2 并联系统</...

什么是站群服务器的优点?
什么是站群服务器的优点? 1. 主要作用 在网站数量增多的今天,对于站群服务器的需求自然也会变得越来越多,那么,它的主要作用都是什么呢?站群服务器,就好像它的名字一样,是一个群体,…...