python语言利用Tkinter实现GUI计算器|(一)计算器基本功能设计

python语言利用Tkinter实现GUI计算器

python语言利用Tkinter实现GUI计算器|(一)计算器基本功能设计
python语言利用Tkinter实现GUI计算器|(二)优化计算器
python语言利用Tkinter实现GUI计算器|(三)pyinstaller打包:带图标计算器


python语言|(一)利用Tkinter实现GUI计算器

学习目标:利用python自带图形界面库tkinter实现用户界面计算器

  1. 熟悉tkinter库的基本用法和控件
  2. 编写计算器代码
  3. 了解获取按钮文本的方法
  4. 了解按钮回调函数
  5. 利用lambda函数的传参优点和局限
  6. 实现计算器软件
    在这里插入图片描述

1. 计算器界面简要设计

  1. 背景部分
    根:Tk()
  2. 展示部分:上方展示算式,下方展示计算结果
  3. 按钮部分
  4. 计算器计算功能:
    1). 加减乘除,放在=,按钮上
    2). 回退,放在<-按钮上
    3). 清除,放在MC按钮上

2. 关于控件的类型,控件的属性,控件的放置方式

控件类型,可以通过dir函数查看:比如dir(tkinter),找到控件

控件:19
'Button','Canvas'画布,'Text'文本,'Checkbutton'复选按钮,'Radiobutton'单选按钮,'Frame'框架,'Message'消息,
'Entry'条目实体,'Label'标签,'LabelFrame'标签框架, 'Listbox'列表框,'Menu'菜单, 'Menubutton'菜单按钮,
'Scale'缩放,'Scrollbar'滚动条,'Toplevel'顶级,'Spinbox'旋转框,'PanedWindow'窗格窗口,'tkMessageBox'消息框

控件属性查看:dir(Button)把用得到的控件都查一遍,就清楚怎么用它们了。
放置方式–集合布局:当定义一个控件,均需要让它布局到窗口上,用到三个函数:pack,grid,place
pack的参数side,可设置上下左右布局;
grid的参数row,column,可设置行列网格布局
place的参数x,y,可设置坐标布局

同一块画布不能混合使用。

3. 计算器实现

3.1. 界面布局

首先引入包:from tkinter import *
根据目标图片设计布局按钮:定义计算器类,初始化界面控件。

创建一个Calculator类,来封装控件和方法。

class Calculator:
    def __init__(self, master):
        self.master = master
        self.master.title("Calculator")
        self.master.resizable(0, 0)  # 设置窗口不可拉伸
        self.master.geometry('320x420')  # 设置主窗口的初始尺寸

        self.result = StringVar()  # 用于显示结果的可变文本
        self.equation = StringVar()  # 显示计算方程
        self.result.set(' ')
        self.equation.set('0')
        # 显示框
        self.show_result_eq = Label(self.master, bg='white', fg='black',
                                    font=('Arail', '16'), bd='0',
                                    textvariable=self.equation, anchor='se')
        self.show_result = Label(self.master, bg='white', fg='black',
                                 font=('Arail', '20'), bd='0',
                                 textvariable=self.result, anchor='se')
        # 按钮
        self.button_back = Button(self.master, text='<-', bg='DarkGray', command=self.back)  # 返回
        self.button_lbracket = Button(self.master, text='(', bg='DarkGray', command=lambda: self.getNum('('))  # 左括号
        self.button_rbracket = Button(self.master, text=')', bg='DarkGray', command=lambda: self.getNum(')'))  # 左括号
        self.button_division = Button(self.master, text='÷', bg='DarkGray', command=lambda: self.getNum('÷'))  # 除号
        # 7 8 9 4 5 6 1 2 3
        self.button_7 = Button(self.master, text='7', bg='DarkGray', command=lambda: self.getNum('7'))  # 7号
        self.button_8 = Button(self.master, text='8', bg='DarkGray', command=lambda: self.getNum('8'))  # 8号
        self.button_9 = Button(self.master, text='9', bg='DarkGray', command=lambda: self.getNum('9'))  # 9号
        self.button_multiplication = Button(self.master, text='*', bg='DarkGray',
                                            command=lambda: self.getNum('*'))  # 乘号
        # 按钮的command参数,是回调函数。lambda函数是为了可以传参数给回调函数
        self.button_4 = Button(self.master, text='4', bg='DarkGray', command=lambda: self.getNum('4'))  # 4号
        self.button_5 = Button(self.master, text='5', bg='DarkGray', command=lambda: self.getNum('5'))  # 5号
        self.button_6 = Button(self.master, text='6', bg='DarkGray', command=lambda: self.getNum('6'))  # 6号
        self.button_minus = Button(self.master, text='-', bg='DarkGray', command=lambda: self.getNum('-'))  # -号

        self.button_1 = Button(self.master, text='1', bg='DarkGray', command=lambda: self.getNum('1'))  # 1号
        self.button_2 = Button(self.master, text='2', bg='DarkGray', command=lambda: self.getNum('2'))  # 2号
        self.button_3 = Button(self.master, text='3', bg='DarkGray', command=lambda: self.getNum('3'))  # 3号
        self.button_plus = Button(self.master, text='+', bg='DarkGray', command=lambda: self.getNum('+'))  # +号
        # 控制按钮 0 .
        self.button_MC = Button(self.master, text='MC', bg='DarkGray', command=self.clear)  # MC
        self.button_0 = Button(self.master, text='0', bg='DarkGray', command=lambda: self.getNum('0'))  # 0
        self.button_dot = Button(self.master, text='.', bg='DarkGray', command=lambda: self.getNum('.'))  # .
        self.button_eq = Button(self.master, text='=', bg='DarkGray', command=self.run)  # =

        # Layout布局
        self.show_result_eq.place(x='10', y='10', width='300', height='50')
        self.show_result.place(x='10', y='60', width='300', height='50')

        self.button_back.place(x='10', y='150', width='60', height='40')
        self.button_lbracket.place(x='90', y='150', width='60', height='40')
        self.button_rbracket.place(x='170', y='150', width='60', height='40')
        self.button_division.place(x='250', y='150', width='60', height='40')
        self.button_7.place(x='10', y='205', width='60', height='40')
        self.button_8.place(x='90', y='205', width='60', height='40')
        self.button_9.place(x='170', y='205', width='60', height='40')
        self.button_multiplication.place(x='250', y='205', width='60', height='40')

        self.button_4.place(x='10', y='260', width='60', height='40')
        self.button_5.place(x='90', y='260', width='60', height='40')
        self.button_6.place(x='170', y='260', width='60', height='40')
        self.button_minus.place(x='250', y='260', width='60', height='40')

        self.button_1.place(x='10', y='315', width='60', height='40')
        self.button_2.place(x='90', y='315', width='60', height='40')
        self.button_3.place(x='170', y='315', width='60', height='40')
        self.button_plus.place(x='250', y='315', width='60', height='40')

        self.button_MC.place(x='10', y='370', width='60', height='40')
        self.button_0.place(x='90', y='370', width='60', height='40')
        self.button_dot.place(x='170', y='370', width='60', height='40')
        self.button_eq.place(x='250', y='370', width='60', height='40')
3.2 触发按钮时的回调函数

重点说明
按钮的command参数,是接收回调函数为参数的变量。
lambda函数是为了可以传参数给回调函数。
lambda匿名函数的使用:command=lambda: self.getNum('3'))
注意这里传的参数是字符串:'3'。每一个按钮点击想要获取的文本值不同,所以对应的参数各不相同。

3.3 Calculator的方法与功能
设置回退`back`,符号获取`getNum`,清除`clear`,计算`run`方法。
    def back(self):
        temp_equ = self.equation.get()
        self.equation.set(temp_equ[:-1])  # 一个一个删

    def getNum(self, arg):
        temp_equ = self.equation.get()  # 输入算式
        temp_result = self.result.get()

        # 判断基本语法错误
        if temp_result != ' ':  # 计算器输入前还没有结果,那么结果区域应该设置为空。
            self.result.set(' ')
        if temp_equ == '0' and (arg not in ['.', '+', '-', '*', '÷']):  # 如果首次输入为0,则紧跟则不能是数字,只是小数点或运算符
            temp_equ = ''
        if len(temp_equ) > 2 and temp_equ[-1] == '0':  # 运算符后面也不能出现0+数字的情形03,09,x
            if (temp_equ[-2] in ['+', '-', '*', '÷']) and (
                    arg in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '(']):
                temp_equ = temp_equ[:-1]
        temp_equ = temp_equ + arg
        self.equation.set(temp_equ)

    def clear(self):
        self.equation.set('0')
        self.result.set(' ')

    def run(self):
        temp_equ = self.equation.get()
        temp_equ = temp_equ.replace('÷', '/')
        if temp_equ[0] in ['+', '-', '*', '÷']:
            temp_equ = '0' + temp_equ
            print(temp_equ)
        try:
            answer = '%.4f' % eval(temp_equ)  # 保留两位小数
            self.result.set(str(answer))
        except (ZeroDivisionError, SyntaxError):  # 其他除0错误,或语法错误返回Error
            self.result.set(str('Error'))
3.4 测试实验

运行:

if __name__ == "__main__":
    root = Tk()
    my_cal = Calculator(root)
    root.mainloop()

在这里插入图片描述
以上实现了用户界面计算器的基本功能;关于用户乱输入和如何过滤掉不合理计算表达式,可参考:优化计算器:过滤用户不合理的输入

3.5 总结
  1. 按钮的command参数设置的是回调函数,点击按钮后的操作由函数完成。
  2. 将回调函数设置成匿名函数, lambda函数是可以传参数给回调函数。这个参数是在调用函数的时候才传入,不会在定义的时候保存。
  • 22
    点赞
  • 184
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柏常青

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值