Python小试牛刀:GUI(图形界面)实现计算器UI界面(三)

上一篇:Python小试牛刀:GUI(图形界面)实现计算器UI界面(二)-CSDN博客

回顾前两篇文章,第一篇文章主要实现了计算器UI界面如何布局,以及简单概述Python常用的GUI库。第二篇文章主要实现了计算器UI界面按钮组件与事件的交互,而在本片文章则是实现计算器完整功能。

运行结果:

Python小试牛刀:GUI(图形界面)实现计算器UI界面(三)_第1张图片

代码设计

"""
    计算器
"""

# 通配符'*'
__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 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('', initUI)
    UI.showLabel1.config(foreground='gray', background='white')
    UI.showLabel2.config(background='white')

    # 0-9
    UI.zero.bind('', zeroBackground)        # 0
    UI.one.bind('', oneBackground)          # 1
    UI.two.bind('', twoBackground)          # 2
    UI.three.bind('', threeBackground)      # 3
    UI.four.bind('', fourBackground)        # 4
    UI.five.bind('', fiveBackground)        # 5
    UI.six.bind('', sixBackground)          # 6
    UI.seven.bind('', sevenBackground)      # 7
    UI.eight.bind('', eightBackground)      # 8
    UI.nine.bind('', nineBackground)        # 9
    # 特殊字符
    UI.clear.bind('', clearBackground)                      # 删除
    UI.backSpace.bind('', backSpaceBackground)              # 退格
    UI.remainder.bind('', remainderBackground)              # 百分号/求余
    UI.division.bind('', divisionBackground)                # 除号
    UI.multiplication.bind('', multiplicationBackground)    # 乘号
    UI.subtraction.bind('', subtractionBackground)          # 减号
    UI.addition.bind('', additionBackground)                # 加号
    UI.equal.bind('', equalBackground)                      # 等于
    UI.brackets.bind('', bracketsBackground)                # 括号
    UI.dit.bind('', ditBackground)                          # 小数点

    # 按钮按下
    UI.base.bind('', zeroReleaseBackground)     # 0
    UI.zero.bind('', zeroEvent)
    UI.base.bind('', oneReleaseBackground)      # 1
    UI.one.bind('', oneEvent)
    UI.base.bind('', twoReleaseBackground)      # 2
    UI.two.bind('', twoEvent)
    UI.base.bind('', threeReleaseBackground)    # 3
    UI.three.bind('', threeEvent)
    UI.base.bind('', fourReleaseBackground)     # 4
    UI.four.bind('', fourEvent)
    UI.base.bind('', fiveReleaseBackground)     # 5
    UI.five.bind('', fiveEvent)
    UI.base.bind('', sixReleaseBackground)      # 6
    UI.six.bind('', sixEvent)
    UI.base.bind('', sevenReleaseBackground)    # 7
    UI.seven.bind('', sevenEvent)
    UI.base.bind('', eightReleaseBackground)    # 8
    UI.eight.bind('', eightEvent)
    UI.base.bind('', nineReleaseBackground)     # 9
    UI.nine.bind('', nineEvent)

    UI.base.bind('', clearReleaseBackground)    # 删除
    UI.base.bind('', clearReleaseBackground)         # 删除
    UI.base.bind('', clearReleaseBackground)              # 删除
    UI.clear.bind('', clearEvent)
    UI.base.bind('', backSpaceReleaseBackground)  # 退格
    UI.backSpace.bind('', backSpaceEvent)
    UI.base.bind('', remainderReleaseBackground)         # 百分号、求余
    UI.remainder.bind('', remainderEvent)
    UI.base.bind('', divisionReleaseBackground)       # 除号
    UI.division.bind('', divisionEvent)
    UI.base.bind('', multiplicationReleaseBackground)    # 乘号
    UI.base.bind('', multiplicationReleaseBackground)          # 乘号
    UI.multiplication.bind('', multiplicationEvent)
    UI.base.bind('', subtractionReleaseBackground)          # 减号
    UI.subtraction.bind('', subtractionEvent)
    UI.base.bind('', additionReleaseBackground)              # 加号
    UI.base.bind('', additionReleaseBackground)                # 加号
    UI.addition.bind('', additionEvent)
    UI.base.bind('', equalReleaseBackground)               # 等号
    UI.base.bind('', equalReleaseBackground)                # 等号
    UI.equal.bind('', equalEvent)
    UI.base.bind('', bracketsReleaseBackground)                # 左括号
    UI.base.bind('', bracketsReleaseBackground)                # 右括号
    UI.brackets.bind('', bracketsEvent)
    UI.base.bind('', ditReleaseBackground)                 # 小数点
    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):
    global labelShow2, operator, operationData, bracketsFlag
    # 数据初始化
    bracketsFlag = 0
    labelShow2 = ''
    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, 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) == '求余错误':
                return
        except:
            UI.labelData1.set(labelShow1 + '=崩溃')
            UI.labelData2.set('抱歉,小算脑子烧坏了')
            return

    print(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 += 1
        if 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:
            return

    labelShow2 += '.'
    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:
                        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]]))-1
        rightBracketsNum = 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 = 0
            for 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 = '-' + 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/5

你可能感兴趣的:(python,入门案例,python,ui,开发语言)