上一篇:Python小试牛刀:GUI(图形界面)实现计算器UI界面(二)-CSDN博客
我坚信好的作品一定要经过不同工匠不断的雕琢。我知道我的项目代码还可以进一步优化(比如等号事件那里等),以及一些BUG进行修复,但我个人比较懒,就让大家勉为其难将就着看吧。倘若大家运行发现一些BUG,以及好的建议,欢迎在评论区发表指正,谢谢!
回顾前两篇文章,第一篇文章主要实现了计算器UI界面如何布局,以及简单概述Python常用的GUI库。第二篇文章主要实现了计算器UI界面按钮组件与事件的交互,而在本篇文章则是实现计算器完整功能。
- """
- 计算器
- """
-
- # 通配符'*'
- __all__ = ['main']
-
-
- # 计算器UI设计
- class CalculatorUI:
-
- import tkinter as tk
- from tkinter import font
-
- base = 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)
-
- # 7
- seven = tk.Button(mainFrame, text='7', width=10, height=2, font=setFont)
- seven.grid(row=2, column=0)
- # 8
- eight = tk.Button(mainFrame, text='8', width=10, height=2, font=setFont)
- eight.grid(row=2, column=1)
- # 9
- nine = 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)
-
- # 4
- four = tk.Button(mainFrame, text='4', width=10, height=2, font=setFont)
- four.grid(row=3, column=0)
- # 5
- five = tk.Button(mainFrame, text='5', width=10, height=2, font=setFont)
- five.grid(row=3, column=1)
- # 6
- six = 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)
-
- # 1
- one = tk.Button(mainFrame, text='1', width=10, height=2, font=setFont)
- one.grid(row=4, column=0)
- # 2
- two = tk.Button(mainFrame, text='2', width=10, height=2, font=setFont)
- two.grid(row=4, column=1)
- # 3
- three = 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)
- # 0
- zero = 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-9
- UI.zero.config(background='#f0f0f0') # 0
- UI.one.config(background='#f0f0f0') # 1
- UI.two.config(background='#f0f0f0') # 2
- UI.three.config(background='#f0f0f0') # 3
- UI.four.config(background='#f0f0f0') # 4
- UI.five.config(background='#f0f0f0') # 5
- UI.six.config(background='#f0f0f0') # 6
- UI.seven.config(background='#f0f0f0') # 7
- UI.eight.config(background='#f0f0f0') # 8
- UI.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 zeroButton_1(event):
- UI.zero.config(background='pink')
- def zeroKeyPress(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 oneButton_1(event):
- UI.one.config(background='pink')
- def oneKeyPress(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 twoButton_1(event):
- UI.two.config(background='pink')
- def twoKeyPress(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 threeButton_1(event):
- UI.three.config(background='pink')
- def threeKeyPress(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 fourButton_1(event):
- UI.four.config(background='pink')
- def fourKeyPress(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 fiveButton_1(event):
- UI.five.config(background='pink')
- def fiveKeyPress(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 sixButton_1(event):
- UI.six.config(background='pink')
- def sixKeyPress(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 sevenButton_1(event):
- UI.seven.config(background='pink')
- def sevenKeyPress(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 eightButton_1(event):
- UI.eight.config(background='pink')
- def eightKeyPress(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 nineButton_1(event):
- UI.nine.config(background='pink')
- def nineKeyPress(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 clearButton_1(event):
- UI.clear.config(background='pink')
- def clearKeyPress(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 backSpaceButton_1(event):
- UI.backSpace.config(background='pink')
- def backSpaceKeyPress(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 remainderButton_1(event):
- UI.remainder.config(background='pink')
- def remainderKeyPress(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 divisionButton_1(event):
- UI.division.config(background='pink')
- def divisionKeyPress(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 multiplicationButton_1(event):
- UI.multiplication.config(background='pink')
- def multiplicationKeyPress(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 subtractionButton_1(event):
- UI.subtraction.config(background='pink')
- def subtractionKeyPress(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 additionButton_1(event):
- UI.addition.config(background='pink')
- def additionKeyPress(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 equalButton_1(event):
- UI.equal.config(background='pink')
- def equalKeyPress(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 bracketsButton_1(event):
- UI.brackets.config(background='pink')
- def bracketsKeyPress(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 ditButton_1(event):
- UI.dit.config(background='pink')
- def ditKeyPress(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('
' , initUI) - UI.showLabel1.config(foreground='gray', background='white')
- UI.showLabel2.config(background='white')
-
- # 0-9
- UI.zero.bind('
' , zeroButton_1) # 0 - UI.one.bind('
' , oneButton_1) # 1 - UI.two.bind('
' , twoButton_1) # 2 - UI.three.bind('
' , threeButton_1) # 3 - UI.four.bind('
' , fourButton_1) # 4 - UI.five.bind('
' , fiveButton_1) # 5 - UI.six.bind('
' , sixButton_1) # 6 - UI.seven.bind('
' , sevenButton_1) # 7 - UI.eight.bind('
' , eightButton_1) # 8 - UI.nine.bind('
' , nineButton_1) # 9 - # 特殊字符
- UI.clear.bind('
' , clearButton_1) # 删除 - UI.backSpace.bind('
' , backSpaceButton_1) # 退格 - UI.remainder.bind('
' , remainderButton_1) # 百分号/求余 - UI.division.bind('
' , divisionButton_1) # 除号 - UI.multiplication.bind('
' , multiplicationButton_1) # 乘号 - UI.subtraction.bind('
' , subtractionButton_1) # 减号 - UI.addition.bind('
' , additionButton_1) # 加号 - UI.equal.bind('
' , equalButton_1) # 等于 - UI.brackets.bind('
' , bracketsButton_1) # 括号 - UI.dit.bind('
' , ditButton_1) # 小数点 -
- # 按钮按下
- UI.base.bind('
' , zeroKeyPress) # 0 - UI.zero.bind('
' , zeroEvent) - UI.base.bind('
' , oneKeyPress) # 1 - UI.one.bind('
' , oneEvent) - UI.base.bind('
' , twoKeyPress) # 2 - UI.two.bind('
' , twoEvent) - UI.base.bind('
' , threeKeyPress) # 3 - UI.three.bind('
' , threeEvent) - UI.base.bind('
' , fourKeyPress) # 4 - UI.four.bind('
' , fourEvent) - UI.base.bind('
' , fiveKeyPress) # 5 - UI.five.bind('
' , fiveEvent) - UI.base.bind('
' , sixKeyPress) # 6 - UI.six.bind('
' , sixEvent) - UI.base.bind('
' , sevenKeyPress) # 7 - UI.seven.bind('
' , sevenEvent) - UI.base.bind('
' , eightKeyPress) # 8 - UI.eight.bind('
' , eightEvent) - UI.base.bind('
' , nineKeyPress) # 9 - UI.nine.bind('
' , nineEvent) -
- UI.base.bind('
' , clearKeyPress) # 删除 - UI.base.bind('
' , clearKeyPress) # 删除 - UI.base.bind('
' , clearKeyPress) # 删除 - UI.clear.bind('
' , clearEvent) - UI.base.bind('
' , backSpaceKeyPress) # 退格 - UI.backSpace.bind('
' , backSpaceEvent) - UI.base.bind('
' , remainderKeyPress) # 百分号、求余 - UI.remainder.bind('
' , remainderEvent) - UI.base.bind('
' , divisionKeyPress) # 除号 - UI.division.bind('
' , divisionEvent) - UI.base.bind('
' , multiplicationKeyPress) # 乘号 - UI.base.bind('
' , multiplicationKeyPress) # 乘号 - UI.multiplication.bind('
' , multiplicationEvent) - UI.base.bind('
' , subtractionKeyPress) # 减号 - UI.subtraction.bind('
' , subtractionEvent) - UI.base.bind('
' , additionKeyPress) # 加号 - UI.base.bind('
' , additionKeyPress) # 加号 - UI.addition.bind('
' , additionEvent) - UI.base.bind('
' , equalKeyPress) # 等号 - UI.base.bind('
' , equalKeyPress) # 等号 - UI.equal.bind('
' , equalEvent) - UI.base.bind('
' , bracketsKeyPress) # 左括号 - UI.base.bind('
' , bracketsKeyPress) # 右括号 - UI.brackets.bind('
' , bracketsEvent) - UI.base.bind('
' , ditKeyPress) # 小数点 - UI.dit.bind('
' , ditEvent) -
-
- # 0 事件
- def zeroEvent(event):
- global labelShow2
- # 数字前面不能是右括号')'
- if ('原来是小瘪三'+labelShow2)[-1] in ')=':
- return
-
- labelShow2 += '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 ')=':
- return
- labelShow2 += '1'
-
- UI.labelData2.set(labelShow2)
- UI.one.config(activeforeground='gray')
-
-
- # 2 事件
- def twoEvent(event):
- global labelShow2
- # 数字前面不能是右括号')'
- if ('什么字符都可以'+labelShow2)[-1] in ')=':
- return
- labelShow2 += '2'
-
- UI.labelData2.set(labelShow2)
- UI.two.config(activeforeground='gray')
-
-
- # 3 事件
- def threeEvent(event):
- global labelShow2
- # 数字前面不能是右括号')'
- if ('不影响代码'+labelShow2)[-1] in ')=':
- return
- labelShow2 += '3'
-
- UI.labelData2.set(labelShow2)
- UI.three.config(activeforeground='gray')
-
-
- # 4 事件
- def fourEvent(event):
- global labelShow2
- # 数字前面不能是右括号')'
- if ('虽然可以封装成函数'+labelShow2)[-1] in ')=':
- return
- labelShow2 += '4'
-
- UI.labelData2.set(labelShow2)
- UI.four.config(activeforeground='gray')
-
- # 5 事件
- def fiveEvent(event):
- global labelShow2
- # 数字前面不能是右括号')'
- if ('但是只有两行代码'+labelShow2)[-1] in ')=':
- return
- labelShow2 += '5'
-
- UI.labelData2.set(labelShow2)
- UI.five.config(activeforeground='gray')
-
-
- # 6 事件
- def sixEvent(event):
- global labelShow2
- # 数字前面不能是右括号')'
- if ('调用函数还是两行代码'+labelShow2)[-1] in ')=':
- return
- labelShow2 += '6'
-
- UI.labelData2.set(labelShow2)
- UI.six.config(activeforeground='gray')
-
-
- # 7 事件
- def sevenEvent(event):
- global labelShow2
- # 数字前面不能是右括号')'
- if ('索性来个自我介绍吧'+labelShow2)[-1] in ')=':
- return
- labelShow2 += '7'
-
- UI.labelData2.set(labelShow2)
- UI.seven.config(activeforeground='gray')
-
-
- # 8 事件
- def eightEvent(event):
- global labelShow2
- # 数字前面不能是右括号')'
- if ('我是周华2022'+labelShow2)[-1] in ')=':
- return
- labelShow2 += '8'
-
- UI.labelData2.set(labelShow2)
- UI.eight.config(activeforeground='gray')
-
-
- # 9 事件
- def nineEvent(event):
- global labelShow2
- # 数字前面不能是右括号')'
- if ('欢迎大家关注!'+labelShow2)[-1] in ')=':
- return
- labelShow2 += '9'
-
- UI.labelData2.set(labelShow2)
- UI.nine.config(activeforeground='gray')
-
-
- # 删除 事件
- def clearEvent(event):
- UI.clear.config(activeforeground='gray')
- global labelShow2, operator, operationData, bracketsFlag
- # 数据初始化
- bracketsFlag = 0
- labelShow2 = ''
- operator = []
- operationData = []
-
- UI.labelData2.set(labelShow2)
-
-
- # 退格 事件
- def backSpaceEvent(event):
- UI.backSpace.config(activeforeground='gray')
- 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)
-
-
- # 求余 事件
- def remainderEvent(event):
- UI.remainder.config(activeforeground='gray')
- 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)
-
-
- # 除法 事件
- def divisionEvent(event):
- UI.division.config(activeforeground='gray')
- 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)
-
-
- # 乘法 事件
- def multiplicationEvent(event):
- UI.multiplication.config(activeforeground='gray')
- 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)
-
-
- # 减法 事件
- def subtractionEvent(event):
- UI.subtraction.config(activeforeground='gray')
- 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)
-
-
- # 加法 事件
- def additionEvent(event):
- UI.addition.config(activeforeground='gray')
- 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)
-
-
- # 等于 事件
- def equalEvent(event):
- UI.equal.config(activeforeground='gray')
- global labelShow2, labelShow1
- labelShow1 = 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 = '-'+num
- else:
- labelShow2 = num
-
- # 复杂运算
- else:
- # 防止报错
- try:
- # 计算式子结果
- if resultEvent(event) == '求余错误' or resultEvent(event) == '除数错误':
- return
- except:
- UI.labelData1.set(labelShow1 + '=崩溃')
- UI.labelData2.set('抱歉,小算脑子烧坏了')
- return
-
- print(operator, operationData)
- labelShow1 += '='+labelShow2 # 显示计算的式子
- UI.labelData1.set(labelShow1)
- UI.labelData2.set(labelShow2)
-
- # 显示结果后删除存储的数据
- if operationData:
- operator.clear()
- operationData.clear()
-
-
- # 括号 事件
- def bracketsEvent(event):
- UI.brackets.config(activeforeground='gray')
- 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 += 1
- if bracketsFlag % 2:
- labelShow2 = labelShow2[:-1:]+'('
- else:
- labelShow2 = labelShow2[:-1:]+')'
-
- UI.labelData2.set(labelShow2)
-
-
- # 小数点 事件
- def ditEvent(event):
- UI.dit.config(activeforeground='gray')
- 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:
- return
-
- labelShow2 += '.'
- UI.labelData2.set(labelShow2)
-
-
- # 计算式子结果
- 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)
-
- # 找到最里层的括号
- 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)
-
- # 化简单个数的括号
- for j in range(2):
- if '(' in bracketsNum[i+j]:
- numSplit = len(bracketsNum[i+j].split('-'))-1
- # 根据负号数,判断数值正负
- if numSplit % 2 and numSplit >= 1:
- bracketsNum[i + j] = '-'+bracketsNum[i+j].strip('()+-')
-
- # 查找除号
- 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:
- continue
- elif '÷' in bracketsOperation:
- continue
- elif '%' 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]]))
- rightBracketsNum = len(re.findall(r'\)', operationData[minBrackets[1]]))
- if len(re.findall(r'\(', operationData[minBrackets[0]])) == len(re.findall(r'\)', operationData[minBrackets[0]]))\
- or len(re.findall(r'\(', operationData[minBrackets[1]])) == len(re.findall(r'\)', operationData[minBrackets[1]])):
- leftBracketsNum = rightBracketsNum = 0
-
- # 删除数据
- 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 >= 1 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 = 0
- for i in bracketsSplit[:-2:]:
- if i == '-':
- num += 1
- # 消除括号
- if leftBracketsNum >= 1 and num:
- if num % 2:
- if string[0] == '+':
- string = '-' + string[1::]
- elif string[0] != '-':
- string = '-' + string
- else:
- 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/6