python中的GUI实现计算器

目录
  • 一、学习目标:学会利用python的GUI做界面布局
  • 二、学习内容:手写一个简单计算器
    • 1、计算器目标图
    • 2、 计算器计算功能
    • 3、 代码实现与详细说明
  • 三、学习优化:学会优化冗于代码

一、学习目标:学会利用python的GUI做界面布局

  • 手写计算器代码熟悉控件的使用方法
  • 优化计算器代码,解决 获取按钮文本 的方法
  • 了解lambda函数的传参优点和局限
  • 打包生成自己的计算器软件,并独立运行

二、学习内容:手写一个简单计算器

1、计算器目标图

目标计算器设计分为三个部分:

背景部分  :

 根:Tk()

展示部分:上方展示算式,下方展示计算结果:

按钮部分:

2、 计算器计算功能

  • 加减乘除,放在 = ,按钮上
  • 回退,放在 <- 按钮上
  •  清除,放在 MC 按钮上

3、 代码实现与详细说明

外观布局:

首先引入包: from tkinter import *

根据目标图片设计布局按钮:定义计算器类,初始化界面控件。

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')

重点说明:

按钮的command参数,是回调函数。lambda函数是为了可以传参数给回调函数。

lambda匿名函数的使用: command=lambda: self.getNum('3'))

注意这里传的参数是字符串: '3' 。每一个按钮点击想要获取的文本值不同,所以对应的参数各不相同。

从而,也导致初始化界面代码看起来太冗长了。

功能布局:

设置回退 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'))

测试实验与总结:

 测试:

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

小结

  • 1. 按钮的command参数设置的是回调函数,点击按钮后的操作由函数完成。
  • 2.将回调函数设置成匿名函数, lambda函数是可以传参数给回调函数。这个参数是在调用函数的时候才传入,不会在定义的时候保存。
  • 3. 关于控件的类型,控件的属性,控件的放置方式

控件类型,可以通过多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,可设置 行列网格布局 ;

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

关于如何避免同志们乱写算式,使软件奔溃的问题。

本计算器计算功能是通过获取将输入表达式,利用eval()函数来执行python代码字符串的。

那么就要杜绝不合理的输入表达式,不能阻止人家乱点,可以在程序中设置 try...except...else...finally 语句捕捉异常,设置合理的的响应。

三、学习优化:学会优化冗于代码

优化方向:

  • 1、 初始化布局页面代码冗余;
  • 2、 lambda匿名函数包裹回调函数时传参的问题

代码实现:这里主要优化初始化函数,其他函数采用继承。

优化计算器类Calc继承Calculatorback,clear,run,getNum。增加initPage来定义页面控件布局。

# 计算器,优化程序
class Calc(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.labels = ['<-', '(', ')', '÷',
                       '7', '8', '9', '*',
                       '4', '5', '6', '-',
                       '1', '2', '3', '+',
                       'MC', '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_dict = {}
        # 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.initPage()

    def initPage(self):
        X = ['10', '90', '170', '250']
        Y = ['150', '205', '260', '315', '370']
        lengths = len(self.labels)  # 20
        y_ = -1
        # 设置按钮并布局
        for label in self.labels:
            print(label)
            index = self.labels.index(label)
            x_ = index % 4
            if x_ == 0:
                y_ += 1

            if label == '<-':
                button = Button(self.master, text=label, bg='DarkGray', command=self.back)
                button.place(x=X[x_], y=Y[y_], width='60', height='40')
            elif label == '=':
                button = Button(self.master, text=label, bg='DarkGray', command=self.run)
                button.place(x=X[x_], y=Y[y_], width='60', height='40')
            elif label == 'MC':
                button = Button(self.master, text=label, bg='DarkGray', command=self.clear)
                button.place(x=X[x_], y=Y[y_], width='60', height='40')
            else:
                # 因为lambda函数有传参功能,但只有调用的时候才传参,所以数字按钮永远会调用最后一个label值。解决方案是自己洗一个button来保存label值
                button = NumButton(self.master, text=label, bg='DarkGray', fun=self.getNum)
                button.btn.place(x=X[x_], y=Y[y_], width='60', height='40')
            # self.button_dict[label] = button

重点:以上代码,倒数第二行,我采用自定义的NumButton,而不是原有的Butoon。

因为即使匿名函数lambda函数有传参功能,但只有调用的时候才传参,所以for循环到最后,label变量的值永远为列表最后一个 = 等于符号,一度让人无解,只能自定义一个按钮类型 NumButton ,来保存中间值。使按钮们都有自己的文本值,并且command回调的时候能够准确传参。

class NumButton():
    def __init__(self, frame, text, fun, **kwargs):
        # side = kwargs.get('side') if 'side' in kwargs else ()  # 此处没用上
        self.btn = Button(
            frame,
            text=text,
            activeforeground="blue",
            activebackground="pink",
            bg='DarkGray',
            command=lambda: fun(text)
        )

注意:

  • 形式参数 frame, text, fun
  • frame是根部件。
  • text按钮的标签文本,
  • fun函数对象,就是待回调的函数。

测试总结:

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

自定义的NumButton设置了按钮激活时背景和字体的颜色变化,所以有点颜色。Button自己也可以设置的。

测试没有问题,就要开始打包:

1.确定安装pyinstaller包,没有可以在环境下安装: conda install pyinstaller pip install pyinstaller
2. 打包: pyinstaller -F calc.py -w
3. 打包生成可执行exe文件不了解请参考博文。

到此这篇关于python中的GUI实现计算器的文章就介绍到这了,更多相关python的GUI计算器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python中的GUI实现计算器

    目录 一.学习目标:学会利用python的GUI做界面布局 二.学习内容:手写一个简单计算器 1.计算器目标图 2. 计算器计算功能 3. 代码实现与详细说明 三.学习优化:学会优化冗于代码 一.学习目标:学会利用python的GUI做界面布局 手写计算器代码熟悉控件的使用方法 优化计算器代码,解决 获取按钮文本 的方法 了解lambda函数的传参优点和局限 打包生成自己的计算器软件,并独立运行 二.学习内容:手写一个简单计算器 1.计算器目标图 目标计算器设计分为三个部分: 背景部分  :  

  • 谈谈python中GUI的选择

    尽管内容可能有些老,但是没有关系,对于想深入Python开发的工作者,在选择GUI开发包,乃至可视化IDE方面都还有相当的借鉴意义. Python最大的特点就在于她的快速开发功能.作为一种胶水型语言,python几乎可以渗透在我们编程过程中的各个领域.这里我简单介绍一下用 python进行gui开发的一些选择. 1.Tkinter Tkinter似乎是与tcl语言同时发展起来的一种界面库.tkinter是python的配备的标准gui库,也是opensource的产物. Tkinter可用于wi

  • 对python中GUI,Label和Button的实例详解

    如下所示: #coding=utf-8 import Tkinter top=Tkinter.Tk() #400x300:代表初始化时主窗口的大小,300,100分别代表窗口的初始化位置 #x:为小写的x top.geometry('400x300+300+100') #创建一个文本框,里面内容为"hello world" lab=Tkinter.Label(top,text='hello world') #布局方式 lab.pack() #创建一个按钮 button=Tkinter.

  • 使用Python中tkinter库简单gui界面制作及打包成exe的操作方法(二)

    上一篇我们写了怎么将xmind转换成想要的excel格式,这篇再讲一下用Python自带的tkinter库设计一个简单的gui界面,让我们的xmind路径,用例版本执行等都通过这个gui界面来输入,生成我们需要的excel文件. Python要生成gui,库还是比较多的比如wxpython,这个我看了下,感觉比较难懂,毕竟只是设计一个比较简单的gui界面,所以就使用了tkinter库,感觉这个还是比较方便易懂的,大家可以在这里学习tkinter库http://c.biancheng.net/py

  • 七个Python必备的GUI库

    GUI(图形用户界面),顾名思义就是用图形的方式,来显示计算机操作的界面,更加方便且直观. 与之相对应的则是CUI(命令行用户交互),就是常见的Dos命令行操作,需要记忆一些常用的命令,对于普通人而言,操作起来学习难度还是蛮高的. 一个好看又好用的GUI,可以大大提高大家的使用体验,提高效率. 比如你想开发一个计算器,如果只是一个程序输入,输出窗口的话,是没有用户体验的. 所以开发一个图像化的小窗口,就变得很有必要. 今天,小F就给大家介绍七个Python必备的GUI库,每一个都值得学习. 01

  • Python中PyAutoGUI帮助文档(推荐!)

    目录 1.简介 1.1 目的 1.2 例子 1.4 保护措施(Fail-Safes) 2 安装与依赖 3.速查表(小抄,Cheat Sheet) 3.1 常用函数 3.2 保护措施 3.3 鼠标函数 3.4 键盘函数 3.5 消息弹窗函数 3.6 截屏函数 4 常用函数 5 鼠标控制函数 5.1 屏幕与鼠标位置 5.2 鼠标行为 5.3 鼠标拖拽 5.4 缓动/渐变(Tween / Easing)函数 5.5 鼠标单击 5.6 鼠标按下和松开函数 5.7 滚轮滚动函数 6 键盘控制函数 6.1

  • 教你如何用一行Python代码实现GUI图形界面

    目录 1.选择文件夹 2.选择文件 3.选择日期 4.输入文本 5.弹窗无按钮 6.弹窗无标题 7.弹窗只有OK按钮 8.弹窗只有Error按钮(红色) 9.显示通知窗口 10.弹窗选择 11.自定义弹窗 12.实战 GUI(图形用户界面),顾名思义就是用图形的方式,来显示计算机操作的界面,更加方便且直观. 一个好看又好用的GUI,可以大大提高大家的使用体验,提高效率. 比如你想开发一个计算器,如果只是一个程序输入,输出窗口的话,是没有用户体验的. 所以开发一个图形化的小窗口,就变得很有必要.

  • Python中pygame安装方法图文详解

    本文实例讲述了Python中pygame安装方法.分享给大家供大家参考,具体如下: 这里主要描述一下我们怎样来安装pygame 可能很多人像我一样,发现了pygame是个好东东,但是就是不知道怎样使用,或者怎样安装,在百度/google上面搜索了一番后,发现没有一篇 详细描述pygame的安装过程的文章.如果你是其中的一员,那么这篇教程可能会帮助到你. 当然,在学习pygame的时候,需要你要有一定的python基础知识的.如果你已经具备了一定的python基础,那么接下来的内容可能对你来说就很

  • 使用Python中的greenlet包实现并发编程的入门教程

    1   动机 greenlet 包是 Stackless 的副产品,其将微线程称为 "tasklet" .tasklet运行在伪并发中,使用channel进行同步数据交换. 一个"greenlet",是一个更加原始的微线程的概念,但是没有调度,或者叫做协程.这在你需要控制你的代码时很有用.你可以自己构造微线程的 调度器:也可以使用"greenlet"实现高级的控制流.例如可以重新创建构造器:不同于Python的构造器,我们的构造器可以嵌套的调用函

  • Python中函数eval和ast.literal_eval的区别详解

    前言 众所周知在Python中,如果要将字符串型的list,tuple,dict转变成原有的类型呢? 这个时候你自然会想到eval. eval函数在python中做数据类型的转换还是很有用的.它的作用就是把数据还原成它本身或者是能够转化成的数据类型.下面来看看示例代码: string <==> list string <==> tuple string <==> dict 也就是说,使用eval可以实现从元祖,列表,字典型的字符串到元祖,列表,字典的转换,此外,eval

随机推荐