Lthero 发表于 2021-3-25 21:11

【中缀转后缀表达式】实现加减乘除计算器



tkinter 实现加减乘除简单计算器,尝试模拟win10 UI

实现计算的核心算法为 中缀表达式 变成后缀表达式 如a+b*c转成abc*+

利用栈实现(数据结构与算法部分)

===========实现计算的核心代码============
    def True_cal(str1):
      stack = []
      final_res = []
      marks = ['+', '-', '*', '/']
      numbers =
      temp_11 = 0
      count = 0
      for i in str1:
            count += 1
            if i in numbers:
                temp_11 = temp_11 * 10 + int(i)
            if i in marks or count == len(str1):
                final_res.append(str(temp_11))
                temp_11 = 0
                if len(stack) != 0:
                  if i == '*' or i == '/':
                        while stack[-1] in ['*', '/']:
                            final_res.append(stack[-1])
                            stack.pop()
                            if len(stack) == 0:
                              break
                        stack.append(i)
                  if i == '+' or i == '-':
                        while stack[-1] in marks:
                            final_res.append(stack[-1])
                            stack.pop()
                            if len(stack) == 0:
                              break
                        stack.append(i)
                else:
                  if i in marks:
                        stack.append(i)
            if i == '(' or i == '(':
                stack.append(i)
            if i == ')' or i == ')':
                while stack[-1] != '(':
                  final_res.append(stack[-1])
                  stack.pop()
                  if len(stack) == 0:
                        break
                stack.pop()
      for i in range(len(stack)):
            final_res.append(stack.pop())
      stack = []
      f_res = 0
      for i in final_res:
            if i not in marks:
                stack.append(i)
            else:
                num_houmian = stack.pop()
                num_qianmian = stack.pop()
                res = str(num_qianmian + i + num_houmian)
                stack.append(str(eval(res)))
            f_res = stack[-1]
      return f_res

===========完整代码===========

from tkinter import *
from tkinter import messagebox, font
from tkinter import Tk, ttk
import tkinter as tk
''

def main():
    root = Tk()
    root.title('简单的四则计算器')
    #root.iconbitmap('i1.ico')
    # 窗体居中
    Width = 600
    Height = 370
    canvas = Canvas(width=Width, height=Height, highlightthickness=0, borderwidth=0)
    canvas.create_rectangle(0, 0, Width, Height, outline='yellow', fill="pink")
    canvas.place(x=0, y=0)
    screenwidth = root.winfo_screenwidth()
    screenheight = root.winfo_screenheight()
    alignstr = '%dx%d+%d+%d' % (Width, Height, (screenwidth - Width) / 2, (screenheight - Height) / 2)
    root.geometry(alignstr)

    root.focus_set()
    root.resizable(width=False, height=False)
    # 输入框
    input_label = tk.Entry(canvas, font=font.Font(size=20, weight='bold'), width=20)# ,height=1, width=15
    input_label.place(x=10, y=45)
    input_label.focus_set()

    sb = tk.Scrollbar(root)
    sb.pack(side="right", fill="y")

    # 结果保存
    lb = Listbox(canvas, height=14, width=25,font=('微软雅黑',12), yscrollcommand=sb.set)
    lb.place(x=350, y=40)

    sb.config(command=lb.yview)
    def helpme():
      # 说明
      win2=Toplevel(root)
      win2.title('说明文档')
      width = 300
      height = 250
      screenwidth = root.winfo_screenwidth()
      screenheight = root.winfo_screenheight()
      alignstr2 = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
      win2.geometry(alignstr2)
      win2.resizable(width=False,height=False)
      win2.focus_set()
      Help=Label(win2,text='可以从键盘输入,可以鼠标点击选择\n\n只支持加减乘除四则运算。\n\n允许使用括号运算符\n\nC 清除显示内容和输入内容\n\nCE 只清除输入内容',font=('微软雅黑',10))
      Help.place(x=40,y=20)

    def about():
      #关于
      win2 = Toplevel(root)
      win2.title('关于')
      width = 200
      height = 200
      screenwidth = root.winfo_screenwidth()
      screenheight = root.winfo_screenheight()
      alignstr2 = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
      win2.geometry(alignstr2)
      win2.resizable(width=False, height=False)
      win2.focus_set()
      Help = Label(win2, text='#lthero\n\n2021年某月某日\n\n喜欢可打赏', font=('微软雅黑',10))
      Help.place(x=50, y=50)

    # 头部菜单
    menu = Menu(root, tearoff=False)
    Cmenu = Menu(menu, tearoff=False)# 新建菜单,删除顶部虚线
    Cmenu.add_command(label='说明', command=helpme)# 将内容添加至菜单
    Cmenu.add_separator()
    Cmenu.add_command(label='关于',command=about)
    menu.add_cascade(label='菜单(点我点我)',menu=Cmenu)# 实例化菜单
    root.config(menu=menu)# 实例化菜单


    # 退出
    def esc():
      root.quit()

    ex = ttk.Button(canvas, text='毁灭吧赶紧的', command=esc)
    ex.place(x=100, y=300)

    # 公式展示
    gongshi_temp=''
    temp = StringVar()
    temp_res = Label(root, textvariable=temp, font=font.Font(size=16, weight='bold'))
    temp_res.place(x=6, y=8)

    def True_cal(str1):
      stack = []
      final_res = []
      marks = ['+', '-', '*', '/']
      numbers =
      temp_11 = 0
      count = 0
      for i in str1:
            count += 1
            if i in numbers:
                temp_11 = temp_11 * 10 + int(i)
            if i in marks or count == len(str1):
                final_res.append(str(temp_11))
                temp_11 = 0
                if len(stack) != 0:
                  if i == '*' or i == '/':
                        while stack[-1] in ['*', '/']:
                            final_res.append(stack[-1])
                            stack.pop()
                            if len(stack) == 0:
                              break
                        stack.append(i)
                  if i == '+' or i == '-':
                        while stack[-1] in marks:
                            final_res.append(stack[-1])
                            stack.pop()
                            if len(stack) == 0:
                              break
                        stack.append(i)
                else:
                  if i in marks:
                        stack.append(i)
            if i == '(' or i == '(':
                stack.append(i)
            if i == ')' or i == ')':
                while stack[-1] != '(':
                  final_res.append(stack[-1])
                  stack.pop()
                  if len(stack) == 0:
                        break
                stack.pop()
      for i in range(len(stack)):
            final_res.append(stack.pop())
      stack = []
      f_res = 0
      for i in final_res:
            if i not in marks:
                stack.append(i)
            else:
                num_houmian = stack.pop()
                num_qianmian = stack.pop()
                res = str(num_qianmian + i + num_houmian)
                stack.append(str(eval(res)))
            f_res = stack[-1]
      return f_res

    first_part = ['']
    second_part = ['0']

    second_part_cheng=['1']
    all_part=['']
    def cal():
      try:
            text_ = temp.get()
            str1=text_+input_label.get()
            #print(str1)
            temp.set(str1)
            res = True_cal(str1)
            input_label.insert(INSERT, res)
            # 清空输入,输出结果
            input_label.delete(0, END)
            input_label.insert(END, res)
            # 保存到记录
            lb.insert(END, str1 + '=')
            lb.insert(END, res)
            input_label.focus_set()
            temp.set('')
      except(ZeroDivisionError, SyntaxError):
            messagebox.showerror('!!!', '输入不规范!!!')
            input_label.focus_set()


    # 清除历史记录
    def clear_history():
      lb.delete(0, END)

    the_button = ttk.Button(root, text='历史记录点我清除,内容可直接复制', command=clear_history).place(x=370, y=5)

    flag=
    # 全部按键
    def start():
      # 重复内容
      def input_0():
            if flag==0:
                input_label.delete(0,END)
                flag=1
            if input_label.get()!='':
                input_label.insert(INSERT, '0')
            input_label.focus_set()
      def input_1():
            if flag == 0:
                input_label.delete(0, END)
                flag = 1
            input_label.insert(INSERT, '1')

      def input_2():
            if flag == 0:
                input_label.delete(0, END)
                flag = 1
            input_label.insert(INSERT, '2')

      def input_3():
            if flag == 0:
                input_label.delete(0, END)
                flag = 1
            input_label.insert(INSERT, '3')

      def input_4():
            if flag == 0:
                input_label.delete(0, END)
                flag = 1
            input_label.insert(INSERT, '4')

      def input_5():
            if flag == 0:
                input_label.delete(0, END)
                flag = 1
            input_label.insert(INSERT, '5')

      def input_6():
            if flag == 0:
                input_label.delete(0, END)
                flag = 1
            input_label.insert(INSERT, '6')

      def input_7():
            if flag == 0:
                input_label.delete(0, END)
                flag = 1
            input_label.insert(INSERT, '7')

      def input_8():
            if flag == 0:
                input_label.delete(0, END)
                flag = 1
            input_label.insert(INSERT, '8')

      def input_9():
            if flag == 0:
                input_label.delete(0, END)
                flag = 1
            input_label.insert(INSERT, '9')

      def input_Point():
            input_label.insert(INSERT, '.')


      def fun_1():
            flag = 0
            first_part = second_part
            second_part = input_label.get()
            input_label.delete(0, END)
            str3 = temp.get() + second_part
            get_res = True_cal(str3)
            text_ = temp.get()
            temp.set(text_ + second_part)
            input_label.insert(END, get_res)
            second_part = get_res
            input_label.focus_set()

      def fun_2():
            flag = 0
            first_part = second_part_cheng
            second_part_cheng = input_label.get()
            input_label.delete(0, END)
            str3 = temp.get() + second_part_cheng
            get_res = True_cal(str3)
            text_ = temp.get()
            temp.set(text_ + second_part_cheng)
            input_label.insert(END, get_res)
            second_part_cheng = get_res
            input_label.focus_set()
      def input_plus():
            input_label.insert(INSERT, '+')
            fun_1()

      def input_minus(*args):
            input_label.insert(INSERT, '-')
            fun_1()

      def input_mul():
            input_label.insert(INSERT, '*')
            fun_2()

      def input_div():
            input_label.insert(INSERT, '/')
            fun_2()

      def input_equal(*args):
            cal()
            flag = 0


      def input_open():
            text_=temp.get()
            temp.set(text_+'(')

      def input_close():
            input_label.insert(INSERT, ')')

      def input_clear():
            input_label.delete(0, END)

      def input_back():
            cop = str(input_label.get())
            input_label.delete(0, END)
            input_label.insert(INSERT, cop)

      def input_all_clear():
            input_label.delete(0, END)
            first_part=''
            second_part='0'
            temp.set('')

      def input_pai():
            if flag==1:
                input_label.delete(0,END)
                flag=0
            input_label.insert(END,'3.14159')

      def input_e():
            if flag==1:
                input_label.delete(0,END)
                flag=0
                flag=0
            input_label.insert(END,'2.71828')

      def ttt():
            messagebox.showinfo('!!!!','    今天是个好日子\n\n'
                                        'today is a good day!')

      col_0 = 30
      row_0 = 100
      row_1 = 130
      col_1 = 85
      row_2 = 160
      col_2 = 140
      row_3 = 190
      col_3 = 195
      col_4 = 250
      row_4 = 220
      B0 = ttk.Button(root, text='0', command=input_0,width=6)
      B0.place(x=col_2, y=row_4)

      B1 = ttk.Button(root, text='1', command=input_1,width=6)
      B1.place(x=col_1, y=row_3)
      B2 = ttk.Button(root, text='2', command=input_2,width=6)
      B2.place(x=col_2, y=row_3)
      B3 = ttk.Button(root, text='3', command=input_3,width=6)
      B3.place(x=col_3, y=row_3)
      B4 = ttk.Button(root, text='4', command=input_4,width=6)
      B4.place(x=col_1, y=row_2)
      B5 = ttk.Button(root, text='5', command=input_5,width=6)
      B5.place(x=col_2, y=row_2)
      B6 = ttk.Button(root, text='6', command=input_6,width=6)
      B6.place(x=col_3, y=row_2)
      B7 = ttk.Button(root, text='7', command=input_7,width=6)
      B7.place(x=col_1, y=row_1)
      B8 = ttk.Button(root, text='8', command=input_8,width=6)
      B8.place(x=col_2, y=row_1)
      B9 = ttk.Button(root, text='9', command=input_9,width=6)
      B9.place(x=col_3, y=row_1)
      BPoint = ttk.Button(root, text='.', command=input_Point,width=6)
      BPoint.place(x=col_3, y=row_4)
      Bplus = ttk.Button(root, text='+', command=input_plus,width=6)
      Bplus.place(x=col_4, y=row_3)
      Bminus = ttk.Button(root, text='-', command=input_minus,width=6)
      Bminus.place(x=col_4, y=row_2)
      root.bind('<KeyPress-KP_Subtract>', input_minus)
      Bmul = ttk.Button(root, text='*', command=input_mul,width=6)
      Bmul.place(x=col_4, y=row_1)
      Bdiv = ttk.Button(root, text='/', command=input_div,width=6)
      Bdiv.place(x=col_4, y=row_0)
      Bequal = ttk.Button(root, text='=', command=input_equal, width=6)
      Bequal.place(x=col_4, y=row_4)
      root.bind('<Return>',input_equal)
      Bclose = ttk.Button(root, text=')', command=input_close, width=6)
      Bclose.place(x=col_1, y=row_4)
      Bclear = ttk.Button(root, text='CE', command=input_clear, width=6)
      Bclear.place(x=col_1, y=row_0)
      Bback = ttk.Button(root, text='<-', command=input_back, width=6)
      Bback.place(x=col_3, y=row_0)
      Ball_clear = ttk.Button(root, text='C', command=input_all_clear, width=6)
      Ball_clear.place(x=col_2, y=row_0)
      Bopen = ttk.Button(root,text='(', command=input_open, width=6)
      Bopen.place(x=col_0, y=row_4)
      Bt1 = ttk.Button(root, text='π', command=input_pai, width=6)
      Bt1 .place(x=col_0, y=row_0)
      Bt2 = ttk.Button(root, text='e', command=input_e, width=6)
      Bt2.place(x=col_0, y=row_1)
      Bt3 = ttk.Button(root, text='n!', command=ttt, width=6)
      Bt3.place(x=col_0, y=row_2)
      Bt4 = ttk.Button(root, text='', command=ttt, width=6)
      Bt4.place(x=col_0, y=row_3)

    start()
    root.mainloop()

if __name__ == '__main__':
    main()




lkocok 发表于 2021-3-25 21:44

收藏学习
页: [1]
查看完整版本: 【中缀转后缀表达式】实现加减乘除计算器