当前位置 博文首页 > 如何利用python的tkinter实现一个简单的计算器

    如何利用python的tkinter实现一个简单的计算器

    作者:豪· 时间:2021-07-02 18:45

    目录
    • 1.准备工作
    • 2. 开始
      • 2.1 生成控件
      • 2.2 定义输入和计算函数
      • 2.3 绑定键盘事件
      • 2.4 循环
    • 3.全部代码
      • 4. 结束语

        做一个计算器,这是我想要达成的效果:

        在按下按钮或者按下键盘的时候,第一行输入框会显示输入的内容,第二行显示框则会预览运算结果,如果发生异常,输入内容格式错误,无法计算,则显示框显示“错误”。

        按“=”按钮或按键回车计算结果,结果显示在第一行。

        1.准备工作

        导入库 tkinter

        import tkinter as tk
        

        2. 开始

        定义两个变量:

        equal_is=False      #定义一些变量
        textchange=''
        

        equal_is 用于判断是否已经计算出结果,textchange是用于设置输入框的内容。

        2.1 生成控件

        首先生成窗体:

        root=tk.Tk()        #创建窗体
        root.geometry('250x350')
        root.title('计算器')
        

        为了方便,在这里定义一个函数 create_btn

        def create_btn(text,col,row,cs,rs,pri='',px=(1,1),py=(1,1)):   #函数:生成按钮
            if pri=='':
                t=text
            else:
                t=pri
            a=tk.Button(root,text=text,width=4,command=lambda:(text_print(t)))	#输入内容
            a.grid(column=col,row=row,columnspan=cs,rowspan=rs,padx=px,pady=py,sticky='nswe')
            return(a)
        

        因为有些按钮的输入内容并不等于它的文本内容(比如按钮“×”,输入“*”),因此我们设置一个空的参数 pri ,在 pri 没有被赋值的时候,输入内容则为 text 。

        text_print 是输入内容的函数,这个在后面会定义。

        btn={}                                  #生成按钮
        btn['1']=create_btn('1',0,5,1,1)
        btn['2']=create_btn('2',1,5,1,1)
        btn['3']=create_btn('3',2,5,1,1)
        btn['4']=create_btn('4',0,4,1,1)
        btn['5']=create_btn('5',1,4,1,1)
        btn['6']=create_btn('6',2,4,1,1)
        btn['7']=create_btn('7',0,3,1,1)
        btn['8']=create_btn('8',1,3,1,1)
        btn['9']=create_btn('9',2,3,1,1)
        btn['0']=create_btn('0',0,6,2,1)
        
        btn['.']=create_btn('.',2,6,1,1)
        btn['=']=create_btn('=',4,5,1,2)
        btn['+']=create_btn('+',3,6,1,1)
        btn['-']=create_btn('-',3,5,1,1)
        btn['*']=create_btn('×',3,4,1,1,pri='*')
        btn['/']=create_btn('÷',4,4,1,1,pri='/')
        btn['←']=create_btn('←',1,2,1,1)
        
        btn['C']=create_btn('C',2,2,1,1)
        btn['(']=create_btn('(',3,2,1,1)
        btn[')']=create_btn(')',4,2,1,1)
        btn['**2']=create_btn('x²',3,3,1,1,pri='**2')
        btn['**(-1)']=create_btn('1/x',4,3,1,1,pri='**(-1)')
        

        上面是用 create_btn 函数生成每一个按钮。

        la=tk.Label(root,text='',bg='white',fg='black',font=('宋体',24),anchor='w',relief='flat')  #生成输入框
        la.grid(column=0,row=0,columnspan=5,rowspan=1,sticky='we')
        
        lab=tk.Label(root,bg='white',fg='grey',height=1,font=('宋体',22),anchor='w',relief='flat')    #生成显示框
        lab.grid(column=0,row=1,columnspan=5,rowspan=1,sticky='we')
        

        上面创建两个标签,作为输入框和显示框。

        la 是输入框,lab是显示框。

        然后定义函数 grid_rowconfigure 和 grid_columnconfigure,用于自动填充行和列:

        def grid_rowconfigure(*rows):   #函数填充行。*rows:允许接收多个参数
            for i in rows:
                root.grid_rowconfigure(i,weight=1)
                
        def grid_columnconfigure(*cols):    #函数填充列。*cols:允许接收多个参数
            for i in cols:
                root.grid_columnconfigure(i,weight=1)
        

        在窗体被改变大小时,按钮会自动填充四周,而输入、显示框只填充左右两边(第2,3,4,5,6行会向竖直方向填充,每一列都会向水平方向填充)。

        grid_rowconfigure(2,3,4,5,6)
        grid_columnconfigure(0,1,2,3,4)
        

        2.2 定义输入和计算函数

        定义 text_print 函数,当按钮被点击时输入内容,当按钮“=”被点击的时候计算结果:

        def text_print(x):  #函数按钮输入算式
            global textchange,equal_is	#声明全局变量
            if x!='=':
                if x=='←':
                    a=str(textchange)[0:-1]
                    textchange=a	#退格
                elif x=='C':
                    textchange=''	#清空
                else:
                    textchange=str(textchange)+str(x)	#输入
                la.configure(text=textchange)
                show_is()
                equal_is=False	#判断格式有无错误
            if x=='=':
                text_equal()	#计算结果
        

        show_is 用于判断格式有无错误:

        def show_is():     #显示框内容
            global textchange	#声明全局变量
            if textchange!='':
                try:
                    textshow=eval(textchange)
                except (SyntaxError,TypeError,NameError):
                    lab.configure(text='错误')	#如果出错了,则显示“错误”
                else:
                    lab.configure(text=textshow)	#如果没有出错,则显示结果
            else:
                lab.configure(text='')	#如果输入框为空,那么清空显示框
        

        text_equal 是计算结果的函数:

        def text_equal(event=None):   #函数计算结果并上到输入框
            global textchange,equal_is	#声明全局变量
            if lab['text']!='错误' and equal_is==False:
                textchange=lab['text']	#无格式错误时,计算结果
                la.configure(text=textchange)	#输入框显示结果
                lab.configure(text='')	#清空显示框
                equal_is=True
        

        这里详细说明一下 equal_is 的作用:

        因为计算了结果后显示框会清空,为了防止二次计算导致输入框也跟着清空,我们需要判断是否已经计算过结果,这时就用到变量 equal_is 。

        当输入内容时,equal_is 变为 True,计算结果后,equal_is 变为 False,如果 equal_is == True,则不计算结果。

        2.3 绑定键盘事件

        我设置的键盘按键及其对应输入内容:

        输入内容 对应按键
        0~9 0~9
        + +
        - -
        * *
        / /
        退格 BackSpace
        清空 Delete
        计算结果 Return(Enter键)

        定义一个函数 bind_print,跟 text_print 有点相似,但有些不一样(原谅我技术差,不知道别的方法,只能重新定义一个函数):

        def bind_print(event):  #函数键盘事件输入算式
            global textchange,equal_is
            if event.keysym!='Return':
                if event.keysym=='BackSpace':	#如果按键名等于“BackSpace”(退格键),那么就退格
                    a=str(textchange)[0:-1]
                    textchange=a
                elif event.keysym=='Delete':	#清空
                    textchange=''
                else:
                    textchange=str(textchange)+str(event.char)	#输入按键内容,char不会获得Ctrl,Shift等特殊按键的文本
                la.configure(text=textchange)	#显示内容
                show_is()	#判断是否错误
                equal_is=False
            else:
                text_equal()        
        

        如果按下的是特殊按键,除非是退格和回车,否则都不会有反应,

        按下字母、数字、符号键的时候,输入按键内容。

        接下来就是绑定键盘事件了:

        root.bind('<Key>',bind_print)	#当键盘按下任意键,执行bind_print
        

        这样,界面布置和功能就完成了‘

        2.4 循环

        将主窗体root放入主循环中:

        root.mainloop()
        

        3.全部代码

        import tkinter as tk
        
        def create_btn(text,col,row,cs,rs,pri='',px=(1,1),py=(1,1)):   #函数生成按钮
            if pri=='':
                t=text
            else:
                t=pri
            a=tk.Button(root,text=text,width=4,command=lambda:(text_print(t)))
            a.grid(column=col,row=row,columnspan=cs,rowspan=rs,padx=px,pady=py,sticky='nswe')
            return(a)
        
        def grid_rowconfigure(*rows):   #函数填充行
            for i in rows:
                root.grid_rowconfigure(i,weight=1)
                
        def grid_columnconfigure(*cols):    #函数填充列
            for i in cols:
                root.grid_columnconfigure(i,weight=1)
        
        def bind_print(event):  #函数键盘事件输入算式
            global textchange,equal_is
            if event.keysym!='Return':
                if event.keysym=='BackSpace':
                    a=str(textchange)[0:-1]
                    textchange=a
                elif event.keysym=='Delete':
                    textchange=''
                else:
                    textchange=str(textchange)+str(event.char)
                la.configure(text=textchange)
                show_is()
                equal_is=False
            else:
                text_equal()
        
        def text_print(x):  #函数按钮输入算式
            global textchange,equal_is
            if x!='=':
                if x=='←':
                    a=str(textchange)[0:-1]
                    textchange=a
                elif x=='C':
                    textchange=''
                else:
                    textchange=str(textchange)+str(x)
                la.configure(text=textchange)
                show_is()
                equal_is=False
            if x=='=':
                text_equal()
            
        def text_equal(event=None):   #函数计算结果并上到输入框
            global textchange,equal_is
            if lab['text']!='错误' and equal_is==False:
                textchange=lab['text']
                la.configure(text=textchange)
                lab.configure(text='')
                equal_is=True
        
        def show_is():     #显示框内容
            global textchange
            if textchange!='':
                try:
                    textshow=eval(textchange)
                except (SyntaxError,TypeError,NameError):
                    lab.configure(text='错误')
                else:
                    lab.configure(text=textshow)
            else:
                lab.configure(text='')
        
        root=tk.Tk()        #创建窗体
        root.geometry('250x350')
        root.title('计算器')
        root.bind('<Key>',bind_print)
        
        equal_is=False      #定义一些函数
        textchange=''
        
        la=tk.Label(root,text='',bg='white',fg='black',font=('宋体',24),anchor='w',relief='flat')  #生成输入框
        la.grid(column=0,row=0,columnspan=5,rowspan=1,sticky='we')
        
        lab=tk.Label(root,bg='white',fg='grey',height=1,font=('宋体',22),anchor='w',relief='flat')    #生成显示框
        lab.grid(column=0,row=1,columnspan=5,rowspan=1,sticky='we')
        
        btn={}                                  #生成按钮
        btn['1']=create_btn('1',0,5,1,1)
        btn['2']=create_btn('2',1,5,1,1)
        btn['3']=create_btn('3',2,5,1,1)
        btn['4']=create_btn('4',0,4,1,1)
        btn['5']=create_btn('5',1,4,1,1)
        btn['6']=create_btn('6',2,4,1,1)
        btn['7']=create_btn('7',0,3,1,1)
        btn['8']=create_btn('8',1,3,1,1)
        btn['9']=create_btn('9',2,3,1,1)
        btn['0']=create_btn('0',0,6,2,1)
        
        btn['.']=create_btn('.',2,6,1,1)
        btn['=']=create_btn('=',4,5,1,2)
        btn['+']=create_btn('+',3,6,1,1)
        btn['-']=create_btn('-',3,5,1,1)
        btn['*']=create_btn('×',3,4,1,1,pri='*')
        btn['/']=create_btn('÷',4,4,1,1,pri='/')
        btn['←']=create_btn('←',1,2,1,1)
        
        btn['C']=create_btn('C',2,2,1,1)
        btn['(']=create_btn('(',3,2,1,1)
        btn[')']=create_btn(')',4,2,1,1)
        btn['**2']=create_btn('x²',3,3,1,1,pri='**2')
        btn['**(-1)']=create_btn('1/x',4,3,1,1,pri='**(-1)')
        
        grid_rowconfigure(2,3,4,5,6)
        grid_columnconfigure(0,1,2,3,4)
        
        root.mainloop()
        

        4. 结束语

        本人技术还较差,欢迎向我提出任何的意见。

        jsjbwy