Python制作简易计算器(GUI)---Tkinter

article/2025/10/20 9:22:43

Python制作简易计算器(GUI)---Tkinter

  • Tkinter简介
  • Tkinter 与 PyQt5 的比较
    • Tkinter
    • PyQt5
  • 项目展示
  • 导入模块
  • 函数封装
    • 1. 运算公式的拼接与展示
    • 2. 将显示框的内容删除
    • 3. 使用eval()函数对表达式求值
  • 主逻辑
    • 1. 布局窗口
    • 2. 布局表达式展示区域
    • 3. 布局按钮
  • 代码汇总
  • 实现桌面点击直接启动计算器(无须人为开启Python)

Tkinter简介

tkinter模块是Python标准的TK GUI工具包接口,可以实现一些较为简单GUI的创建。

Tkinter 与 PyQt5 的比较

Tkinter

  1. 麻雀虽小,五脏俱全
  2. TK工具集使用TCL(Tool Command Language)语言开发
  3. 运行相同的程序时,运行速度快于pyqt5
  4. 组件能满足基本使用
  5. 程序界面较简陋
  6. 开发时,使用的语句更短更易懂
  7. Python内置的标准库

PyQt5

  1. Qt框架使用C++开发
  2. 组件丰富
  3. 运行相同的程序时,运行速度慢与tkinter
  4. 使用Qt designer可以在不使用代码的情况下创建一个程序
  5. 界面的观赏性更强
  6. 调试难度更大

项目展示

计算器
可以通过点击桌面快捷方式直接运行,无须人为打开Python。
修改代码保存后,程序也会发生相应的改变。
快捷方式

导入模块

import tkinter as tk
import tkinter.messagebox as mes

注:
要想使用tkinter的弹窗组件,必须导入tkinter.messagebox

函数封装

1. 运算公式的拼接与展示

def operation(num):content = buf_bottom.get()# 使用变量对象buf_bottom的get方法,获取标签内的文字信息buf_bottom.set(content+num)

2. 将显示框的内容删除

def clear():buf_top.set('')# 使用变量对象的set方法将标签内容设置为空字符串buf_bottom.set('')

显示框分上下两部分,之所以这样分,是希望实现这样的一个效果。
分行原因
上面的标签对象用于展示计算过程中使用的表达式,下面的标签则是展示未完成的表达式以及计算结果的展示。

3. 使用eval()函数对表达式求值

这里我们使用eval实现计算结果的获取,eval()是Python的内建函数,它接受一个字符串,将该字符串作为Python代码运行后,返回结果。

def calculate():content = buf_bottom.get()buf_top.set(content + ' = ')try:buf_bottom.set(eval(content))# 将except ZeroDivisionError放在except的前面可以保证except ZeroDivisionError的正常执行# except 包含 except ZeroDivisionErrorexcept ZeroDivisionError:# 处理除数为零的异常情况buf_bottom.set('Infiniti')# 弹出警示窗口mes.showwarning('注意', '请不要使用零作为除数')except:# 处理所有的异常情况# 弹出错误提示窗口mes.showerror('错误', '输入的表达式有误,请重新输入')

在异常处理时要注意顺序,否则可能有些操作永远也执行不了。

主逻辑

1. 布局窗口

if __name__ == '__main__':# 保证下方代码在本文件作为模块导入其他文件时不会执行# 创建主窗口calc = tk.Tk()# 指定程序的宽高WIDTH_R = 283HEIGHT_R = 335# 获取计算机屏幕的宽高WIDTH_W = calc.winfo_screenwidth()HEIGHT_W = calc.winfo_screenheight()# 设置应用名称calc.title('计算器')# 设置应用图标(仅指定ico文件才有效,png等图片无法正常显示)calc.iconbitmap('./calculation.ico')# 设置主窗口背景颜色calc['background'] = '#d9d6c3'# 将程序移动到屏幕中央calc.geometry(f'{WIDTH_R}x{HEIGHT_R}+{(WIDTH_W - WIDTH_R) // 2}+{(HEIGHT_W - HEIGHT_R) // 2}')

注:

calc.geometry(f’{WIDTH_R}x{HEIGHT_R}+{(WIDTH_W - WIDTH_R) // 2}+{(HEIGHT_W - HEIGHT_R) // 2}')

  1. geometry方法接受一个字符串参数,依据它设置程序的宽高以及左上角的xy坐标。
    宽高之间必须 小写的字母x连接 ,其他数据之间则用 + 号连接。
  2. 至于将程序移动到屏幕中间的代码为什么会这样写,改变一下表达式或许你就能够理解

(WIDTH_W - WIDTH_R) // 2 --> WIDTH_W // 2 - WIDTH_R // 2
(HEIGHT_W - HEIGHT_R) // 2 --> HEIGHT_W // 2 - HEIGHT_R // 2

程序中使用的图标在这个链接里:
https://s1.chu0.com/src/img/png/bf/bfc39031c057479aad0e94706d4d26bb.png?imageMogr2/auto-orient/thumbnail/!132x132r/gravity/Center/crop/132x132/quality/85/&e=1735488000&token=1srnZGLKZ0Aqlz6dk7yF4SkiYf4eP-YrEOdM1sob:q3YCeYP0-2kOdXQG7LDXmls337w=

2. 布局表达式展示区域

    # 布局表达式展示区域# 创建变量对象,便于后续获取或更改变量的值buf_top = tk.StringVar()# 如果需要让标签对象的显示内容由一个字符串变量来实现,Label的参数就不能用text,需要使用textvariablebuffer = tk.Label(calc, textvariable=buf_top, bg='#6f6d85', fg='#d3d7d4', height=1, width=10,font=('arial', 14, 'normal'), anchor='se', pady=3, padx=2)# sticky参数可以实现类似pack方法的fill参数, 使标签横向铺满buffer.grid(sticky=tk.W + tk.E, row=0, column=0, columnspan=4)buf_bottom = tk.StringVar()buffer = tk.Label(calc, textvariable=buf_bottom, bg='#6f6d85', fg='#fff', height=1, width=10,font=('arial', 18, 'normal'), anchor='se', pady=3, padx=2)buffer.grid(sticky=tk.W + tk.E, row=1, column=0, columnspan=4)

标签的位置,由参数anchor的属性值决定

anchor参数值及其代表的具体位置


上述图片引用自C语言中文网

标签的位置默认是居中的。
参数值及其代表的方位可能不太好记忆,但只要记住了东西南北四个方位,记忆起来就方便多了。

方位英文表示
East
西West
South
North

3. 布局按钮

   # Ctk.Button(calc, text='C', cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: clear()).grid(row=2, column=0, padx=5, pady=5)# 0tk.Button(calc, text=0, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('0')).grid(row=5, column=1, padx=5, pady=5)# 1tk.Button(calc, text=1, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('1')).grid(row=2, column=1, padx=5, pady=5)# 2tk.Button(calc, text=2, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('2')).grid(row=2, column=2, padx=5, pady=5)# 3tk.Button(calc, text=3, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('3')).grid(row=3, column=0, padx=5, pady=5)# 4tk.Button(calc, text=4, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('4')).grid(row=3, column=1, padx=5, pady=5)# 5tk.Button(calc, text=5, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('5')).grid(row=3, column=2, padx=5, pady=5)# 6tk.Button(calc, text=6, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('6')).grid(row=4, column=0, padx=5, pady=5)# 7tk.Button(calc, text=7, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('7')).grid(row=4, column=1, padx=5, pady=5)# 8tk.Button(calc, text=8, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('8')).grid(row=4, column=2, padx=5, pady=5)# 9tk.Button(calc, text=9, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('9')).grid(row=5, column=0, padx=5, pady=5)# 加号tk.Button(calc, text='+', cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('+')).grid(row=2, column=3, padx=5, pady=5)# 乘号tk.Button(calc, text='*', cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('*')).grid(row=4, column=3, padx=5, pady=5)# 除号tk.Button(calc, text='/', cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('/')).grid(row=3, column=3, padx=5, pady=5)# 等号tk.Button(calc, text='=', cursor='hand2', width=7, height=1, bg='#f2eada', font='arial 22 normal',command= calculate).grid(row=5, column=2, columnspan=2, padx=5, pady=5)# 开启主循环calc.mainloop()

本想先用循环创建一些按钮,但由于点击按钮后,无法判断点击了哪个按钮。
于是:

    # 使用for循环创建0-8的按钮,其余按钮为了布局,得一个一个布置。face = 0for row in range(1, 4):for column in range(3):tk.Button(calc, text=face, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal', command=lambda: number(face)).grid \(row=row, column=column, padx=5, pady=5)face += 1

由于number是一个回调函数,当你点击后才会执行,而此时for循环已经结束(排除你手速足够快的情况),face=9。
因此无论你点哪一个数字按钮,显示的都会是9。
暂时并没有更好的解决方案,如果你知道怎么做,还请不吝赐教。

代码汇总

# 导入模块
import tkinter as tk
import tkinter.messagebox as mes# 运算公式的拼接与展示
def operation(num):content = buf_bottom.get()# 使用变量对象buf_bottom的get方法,获取标签内的文字信息buf_bottom.set(content+num)# 将显示框的内容删除
def clear():buf_top.set('')buf_bottom.set('')# 使用eval()函数对表达式求值
def calculate():content = buf_bottom.get()buf_top.set(content + ' = ')try:buf_bottom.set(eval(content))# 将except ZeroDivisionError放在except的前面可以保证except ZeroDivisionError的正常执行# except 包含 except ZeroDivisionErrorexcept ZeroDivisionError:# 处理除数为零的异常情况# 弹出警示窗口buf_bottom.set('Infiniti')mes.showwarning('注意', '请不要使用零作为除数')except:# 处理所有的异常情况# 弹出错误提示窗口mes.showerror('错误', '输入的表达式有误,请重新输入')if __name__ == '__main__':# 保证下方代码在本文件作为模块导入其他文件时不会执行# 创建主窗口calc = tk.Tk()# 指定程序的宽高WIDTH_R = 283HEIGHT_R = 335# 获取计算机屏幕的宽高WIDTH_W = calc.winfo_screenwidth()HEIGHT_W = calc.winfo_screenheight()# 设置应用名称calc.title('计算器')# 设置应用图标(仅指定ico文件才有效,png等图片无法正常显示)calc.iconbitmap('./calculation.ico')# 设置主窗口背景颜色calc['background'] = '#d9d6c3'# 将程序移动到屏幕中央calc.geometry(f'{WIDTH_R}x{HEIGHT_R}+{(WIDTH_W - WIDTH_R) // 2}+{(HEIGHT_W - HEIGHT_R) // 2}')# 布局表达式展示区域# 创建变量对象,便于后续获取或更改变量的值buf_top = tk.StringVar()# 如果需要让标签对象的显示内容由一个字符串变量来实现,Label的参数就不能用text,需要使用textvariablebuffer = tk.Label(calc, textvariable=buf_top, bg='#6f6d85', fg='#d3d7d4', height=1, width=10,font=('arial', 14, 'normal'), anchor='se', pady=3, padx=2)# sticky参数可以实现类似pack方法的fill参数, 使标签横向铺满buffer.grid(sticky=tk.W + tk.E, row=0, column=0, columnspan=4)buf_bottom = tk.StringVar()buffer = tk.Label(calc, textvariable=buf_bottom, bg='#6f6d85', fg='#fff', height=1, width=10,font=('arial', 18, 'normal'), anchor='se', pady=3, padx=2)buffer.grid(sticky=tk.W + tk.E, row=1, column=0, columnspan=4)# Ctk.Button(calc, text='C', cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: clear()).grid(row=2, column=0, padx=5, pady=5)# 0tk.Button(calc, text=0, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('0')).grid(row=5, column=1, padx=5, pady=5)# 1tk.Button(calc, text=1, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('1')).grid(row=2, column=1, padx=5, pady=5)# 2tk.Button(calc, text=2, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('2')).grid(row=2, column=2, padx=5, pady=5)# 3tk.Button(calc, text=3, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('3')).grid(row=3, column=0, padx=5, pady=5)# 4tk.Button(calc, text=4, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('4')).grid(row=3, column=1, padx=5, pady=5)# 5tk.Button(calc, text=5, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('5')).grid(row=3, column=2, padx=5, pady=5)# 6tk.Button(calc, text=6, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('6')).grid(row=4, column=0, padx=5, pady=5)# 7tk.Button(calc, text=7, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('7')).grid(row=4, column=1, padx=5, pady=5)# 8tk.Button(calc, text=8, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('8')).grid(row=4, column=2, padx=5, pady=5)# 9tk.Button(calc, text=9, cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('9')).grid(row=5, column=0, padx=5, pady=5)# 加号tk.Button(calc, text='+', cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('+')).grid(row=2, column=3, padx=5, pady=5)# 乘号tk.Button(calc, text='*', cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('*')).grid(row=4, column=3, padx=5, pady=5)# 除号tk.Button(calc, text='/', cursor='hand2', width=3, height=1, bg='#f2eada', font='arial 22 normal',command=lambda: operation('/')).grid(row=3, column=3, padx=5, pady=5)# 等号tk.Button(calc, text='=', cursor='hand2', width=7, height=1, bg='#f2eada', font='arial 22 normal',command= calculate).grid(row=5, column=2, columnspan=2, padx=5, pady=5)# 开启主循环calc.mainloop()

实现桌面点击直接启动计算器(无须人为开启Python)

创建了一个GUI程序,如果还每次都要在命令行这样打开:

python calculation.py

怕是一种罪孽。
如果想让程序也能像其他桌面应用一样使用,可以这样做:

  1. 将文件的后缀名由 .py 改为 .pyw
  2. 在命令行中输入:

pythonw calculation.pyw

即可。
此后,即便你重启计算机,也能点击文件直接打卡程序。
相当于你点击.pyw 文件后,系统隐式执行了:

python calculation.py


http://chatgpt.dhexx.cn/article/pyAVtpp5.shtml

相关文章

自制个性计算器

一、布局文件xml的制作。 如图:是布局之后的一个效果图 完全可以自定义自己喜欢的各种类型的图片。 代码如下: 正所谓每一个鲜艳靓丽app背后都有成堆的代码支撑这句话是没有错的。由于没有长截屏软件只能用短截屏了,大家谅解一下&#…

C++简易计算器的实现

定义: 计算器是近代人发明的可以进行数字运算的机器。 也就是说,计算器不等同于算盘,前者能自行运算,后者只能简便计算过程,在古代,人们发明了许多计算工具,如算筹、算盘、计算尺等,随着社会的发展和科技的进步,计算…

制作简易计算器

简易计算器 效果展示图项目要求内容分析涉及函数 效果展示图 项目要求 制作简易计算器,使其能实现简单的加,减,乘,除运算。 1.在两个文本框中分别输入两个数字 2.输入完成后,再次点击加,减,乘&…

C# 制作简易计算器

前言:环境是vs 2022 1、打开vs2022后,右边导航栏选择创建新项目。 2、选择Windows窗体应用(.net Framework) 3、进入配置新项目界面(项目名称和位置可自行修改)点击创建 4、窗体From1即为我们要要编辑的位…

至简设计系列_简易计算器

–作者:小黑同学 本文为明德扬原创及录用文章,转载请注明出处! 1.1 总体设计 1.1.1 概述 计算器是近代人发明的可以进行数字运算的机器。现代的电子计算器能进行数学运算的手持电子机器,拥有集成电路芯片,但结构比电…

如何制作一个简易的计算器

今天,我们来学习如何完成一个简易计算器的功能吧! 一.布局 我们可以在HTML中使用CSS完成计算器的布局。接下来,我们便先来看看我们所要实现的效吧! 上图的计算器中,我们可以通过以下几个步骤完成对计算器的简单布局…

简易版计算器

这次我们来写一个简单的计算器案例 代码部分 HTML部分 首先设置一个基本样式,把我们需要的“计算”按钮,“-*/”四个计算符合,三个文本框准备好(两个用来输入数字进行计算,一个用来接收计算出来的结果),再为三个文…

java拦截器怎么实现

Java拦截器是一种对象拦截器,它可以拦截任何的类、方法和字段。拦截器还可以用于检查类是否已经加载以及对字段的访问权限是否符合规范。下面就让我们来了解一下 java拦截器怎么实现吧。 在 Java中,可以通过重写方法和代码块来实现拦截功能,但…

Java中的过滤器和拦截器

Java中的过滤器和拦截器 一.应用场景 拦截器应用场景 拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括: 登录验证,判断用户是否登录。权限验证&…

拦截器(HandlerInterceptor)

目录 1 什么是拦截器 2 HandlerInterceptor和WebMvcConfigurer 2.1 HandlerInterceptor 2.2 WebMvcConfigurer 3 拦截器实现流程 1 什么是拦截器 拦截器是相对于Spring中来说的,它和过滤器不一样,过滤器的范围更广一些是相对于Tomcat容器来说的。拦…

用 Java 实现拦截器 Interceptor 的拦截功能

Java 里的拦截器是动态拦截 action 调用的对象,它提供了一种机制可以使开发者可以定义在一个 action 执行的前后执行的代码,也可以在一个 action 执行前阻止其执行,同时也提供了一种可以提取 action 中可重用部分的方式。在 AOP(A…

java-拦截器

(1)浏览器发送一个请求会先到Tomcat的web服务器 (2)Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源 (3)如果是静态资源,会直接到Tomcat的项目部署目录下去直接访问 (4)如果是动态资源,就需要交给项目的后台代码进行处理…

JAVA中的拦截器、过滤器

JAVA变成拦截器、过滤器 一、拦截器1、简介说明2、源码及方法说明3、拦截器自定义应用 二、过滤器1、简介说明2、源码及方法说明3、过滤器的自定义应用 三、Springboot中的WebMvcConfigurer1、简介2、主要方法3、添加拦截器 四、区别1、原理2、触发3、其他 一、拦截器 1、简介…

Java开发学习----拦截器(Interceptor)详细解析

一、拦截器概念 讲解拦截器的概念之前,我们先看一张图: (1)浏览器发送一个请求会先到Tomcat的web服务器 (2)Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源 (3)如果是静态资源,会直接到Tomcat的项目部署目录下去直接访…

JAVA三大器之拦截器

1,拦截器的概念 java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action 执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式。…

java之拦截器

java里的拦截器是动态 拦截action的web请求,而过滤器能够进行系统级别的过滤,即能够过滤所有的web请求。从这可以看出拦截器是有一定的局限性的。拦截器是基于jdk实现的动态代理,拦截器是动态拦截action调用的对象, 拦截器可以使得…

Java三大器之拦截器(Interceptor)的实现原理及代码示例

前言:前面2篇博客,我们分析了Java中过滤器和监听器的实现原理,今天我们来看看拦截器。 1,拦截器的概念 java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代…

Java 拦截器

一、引言 既然要用拦截器,首先先得简单了解一下什么是拦截器: 概念:java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行…

VirtualAPK:滴滴 Android 插件化的实践之路

作者简介: 任玉刚,滴滴出行 Android 技术专家,《Android 开发艺术探索》作者,插件化框架 dynamic-load-apk 的发起者,CSDN 移动开发博客专家,曾当选 CSDN 2014、2015年度十大博客之星。热爱技术&#xff0c…

Unity刚体

1、Dynamic:动态类型 受重力和力的影响移动和旋转 Material: 物理材质,在刚体上设置了物理材质,如果子物体有碰撞器但是没有设置材质则会通用刚体的物理材质 如果不设置,将使用在Physics 2D窗口中设置的默认材质(Physi…