目录
3.2 使用grid布局管理器来定位和调整Entry小部件的大小。
计算器是我们日常生活中都会用到的一个应用程序。如果你正在学习python编程,Calculator是一个既简单又有用的项目。今天,我们将使用Tkinter构建一个Python计算器,步骤简单易懂。
Python提供了各种实用程序来设计GUI(图形用户界面),其中最常用的一个实用程序是Tkinter。它是构建GUI应用程序的最快和最简单的方法之一。此外,Tkinter是跨平台的,因此相同的代码可以在macOS, Windows和Linux上运行。
如下是计算器预览:
1 导入必要的模块
from tkinter import *
import ast
from math import factorial
tkinter
:用于创建GUI应用程序。ast
:用于安全地评估表达式。factorial
:计算阶乘的数学函数。
2 创建主窗口并设置标题
root = Tk()
root.title('基于python tkinter的计算器')
root.mainloop()
如上代码为设置主窗口的标题,标题为“基于python tkinter的计算器” ,运行代码后窗口如下:
3 加入计算器按钮
#adding the input field
display = Entry(root)
display.grid(row=1,columnspan=6,sticky=N+E+W+S)
#Code to add buttons to the Calculator
Button(root,text="1",command = lambda :get_variables(1)).grid(row=2,column=0, sticky=N+S+E+W)
Button(root,text=" 2",command = lambda :get_variables(2)).grid(row=2,column=1, sticky=N+S+E+W)
Button(root,text=" 3",command = lambda :get_variables(3)).grid(row=2,column=2, sticky=N+S+E+W)
Button(root,text="4",command = lambda :get_variables(4)).grid(row=3,column=0, sticky=N+S+E+W)
Button(root,text=" 5",command = lambda :get_variables(5)).grid(row=3,column=1, sticky=N+S+E+W)
Button(root,text=" 6",command = lambda :get_variables(6)).grid(row=3,column=2, sticky=N+S+E+W)
Button(root,text="7",command = lambda :get_variables(7)).grid(row=4,column=0, sticky=N+S+E+W)
Button(root,text=" 8",command = lambda :get_variables(8)).grid(row=4,column=1, sticky=N+S+E+W)
Button(root,text=" 9",command = lambda :get_variables(9)).grid(row=4,column=2, sticky=N+S+E+W)
#adding other buttons to the calculator
Button(root,text="AC",command=lambda :clear_all()).grid(row=5,column=0, sticky=N+S+E+W)
Button(root,text=" 0",command = lambda :get_variables(0)).grid(row=5,column=1, sticky=N+S+E+W)
Button(root,text=" .",command=lambda :get_variables(".")).grid(row=5, column=2, sticky=N+S+E+W)
Button(root,text="+",command= lambda :get_operation("+")).grid(row=2,column=3, sticky=N+S+E+W)
Button(root,text="-",command= lambda :get_operation("-")).grid(row=3,column=3, sticky=N+S+E+W)
Button(root,text="*",command= lambda :get_operation("*")).grid(row=4,column=3, sticky=N+S+E+W)
Button(root,text="/",command= lambda :get_operation("/")).grid(row=5,column=3, sticky=N+S+E+W)
# adding new operations
Button(root,text="pi",command= lambda :get_operation("*3.14")).grid(row=2,column=4, sticky=N+S+E+W)
Button(root,text="%",command= lambda :get_operation("%")).grid(row=3,column=4, sticky=N+S+E+W)
Button(root,text="(",command= lambda :get_operation("(")).grid(row=4,column=4, sticky=N+S+E+W)
Button(root,text="exp",command= lambda :get_operation("**")).grid(row=5,column=4, sticky=N+S+E+W)
Button(root,text="<-",command= lambda :undo()).grid(row=2,column=5, sticky=N+S+E+W)
Button(root,text="x!", command= lambda: fact()).grid(row=3,column=5, sticky=N+S+E+W)
Button(root,text=")",command= lambda :get_operation(")")).grid(row=4,column=5, sticky=N+S+E+W)
Button(root,text="^2",command= lambda :get_operation("**2")).grid(row=5,column=5, sticky=N+S+E+W)
Button(root,text="^2",command= lambda :get_operation("**2")).grid(row=5,column=5, sticky=N+S+E+W)
Button(root,text="=",command= lambda :calculate()).grid(columnspan=6, sticky=N+S+E+W)
3.1 创建Entry
小部件文本输入区域
Entry
小部件通常用于让用户输入单行文本。这里的root
是指主窗口对象。
3.2 使用grid
布局管理器来定位和调整Entry
小部件的大小。
row=1
: 指定Entry
小部件应放置在第1行。columnspan=6
: 表示Entry
小部件应该跨越6列。这意味着它将占据从它的起始列开始的连续6列的空间。sticky=N+E+W+S
: 这个选项指定了小部件如何扩展以填充其单元格。这里的字母代表方向:N
: 北(顶部)E
: 东(右侧)W
: 西(左侧)S
: 南(底部)
sticky=N+E+W+S
表示小部件将在所有四个方向上扩展,如果它所在的单元格允许的话。这意味着它将尽可能地扩展以填充整个单元格。
3.3 创建按钮,并将其添加到GUI界面上
创建Button
小部件,包括数字、操作运算符,如按钮“1”,当按钮被点击时,它会调用一个匿名函数(lambda函数),该函数又调用get_variables
函数(后文有函数实现),并传入参数1
4 函数实现
4.1 get_variables()函数实现
数字0-9和小数点使用get_variables函数获取输入文本到输入文本框中,如下是函数实现:
#It keeps the track of current position on the input text field
i = 0
# Receives the digit as parameter and display it on the input field
def get_variables(num):
global i
display.insert(i,num)
i+=1
- i= 0:初始化变量
i
用于跟踪输入框中的光标位置 - def get_variables(num):定义了一个名为
get_variables
的函数,接受一个参数num
- global i:声明了变量
i
是全局变量。在函数内部使用全局变量时,需要使用global
关键字来表明你正在使用的是全局作用域中的变量 - display.insert(i,num):插入文本到输入框,将参数
num
插入到GUI应用程序的输入框(Entry
小部件)中。display
是之前定义的Entry
小部件的实例,insert
方法用于在指定位置插入文本。这里的i
表示插入位置,num
是要插入的文本
4.2 get_operation()函数实现
# Function which takes operator as input and displays it on the input field
def get_operation(operator):
global i
length = len(operator)
display.insert(i,operator)
i+=length
“+”、“-”、“*”、“/”、括号、平方等运算符使用get_operation函数来获取按钮文本,由于这些运算符长度不一,因此使用了len()函数来计算运算符长度,i+=length用来计算记录下一个字符或数字应该插入的位置。
4.3 calculate()函数实现
def calculate():
entire_string = display.get()
try:
a = ast.parse(entire_string, mode="eval")
result = eval(compile(a, "", mode="eval"))
clear_all()
display.insert(0,result)
except Exception:
clear_all()
display.insert(0,"Error")
4.3.1 获取输入
display.get()获取了GUI应用程序中输入框(Entry
小部件)中的文本内容,并将其存储在变量 entire_string
中
4.3.2 计算表达式
ast.parse(entire_string, mode="eval")
: 这行代码使用Python的ast
模块将字符串表达式转换为抽象语法树(Abstract Syntax Tree, AST)。mode="eval"
表示解析的目的只是为了评估表达式的值。compile(a, "", mode="eval")
: 使用compile
函数将AST编译为可执行的代码对象。mode="eval"
表示编译后的代码将用于评估表达式的值。eval(compile(a, "", mode="eval"))
: 使用eval
函数来计算编译后的代码对象的值,并将结果存储在变量result
中。
4.3.3 清除输入框
调用了 clear_all()
函数(后文有实现),用于清空输入框中的内容
4.3.4 显示结果或错误
如果计算成功,将结果显示在输入框的最前面。
如果计算过程中发生异常(例如,输入的表达式无效或包含语法错误),则清除输入框的内容,并显示字符串 "Error"。
4.4 clear_all()函数实现
#Function to clear the input field
def clear_all():
display.delete(0,END)
使用 delete
方法清空了 Entry
小部件中的内容。
0
: 表示从输入框的第一个字符开始删除。END
: 表示删除到输入框的末尾。
4.5 undo()函数实现
undo()函数用于实现GUI应用程序中的撤销功能,即删除输入框(Entry
小部件)中的最后一个字符。代码如下:
#Function which works like backspace
def undo():
entire_string = display.get()
if len(entire_string):
new_string = entire_string[:-1]
clear_all()
display.insert(0,new_string)
else:
clear_all()
display.insert(0,"Error")
4.5.1 获取输入框内容
entire_string = display.get():获取了GUI应用程序中输入框(Entry
小部件)中的文本内容,并将其存储在变量 entire_string
中
4.5.2 检查输入框是否为空
if len(entire_string):检查输入框是否包含任何文本。如果输入框不为空(即 entire_string
的长度大于0),则执行撤销操作;否则,输入框为空,显示错误信息。
4.5.3 撤销操作
如果输入框不为空:
new_string = entire_string[:-1]
: 创建一个新的字符串new_string
,包含entire_string
中的所有字符,除了最后一个字符。clear_all()
: 调用clear_all
函数来清空输入框的内容。display.insert(0, new_string)
: 将新字符串new_string
插入到输入框的开头位置。
4.5.4 显示错误信息
如果输入框为空,则执行以下操作:
clear_all()
: 清空输入框的内容。display.insert(0, "Error")
: 将字符串 "Error" 插入到输入框的开头位置。
4.6 fact()函数实现
fact()函数用于计算用户在GUI应用程序的输入框中输入的数字的阶乘,代码如下:
#Function to calculate the factorial and display it
def fact():
entire_string = display.get()
try:
result = factorial(int(entire_string))
clear_all()
display.insert(0,result)
except Exception:
clear_all()
display.insert(0,"Error")
5 编译
使用python解释器进行编译,编译指令如下:
D:/Anaconda/python.exe g:/learning/python/projects/calculator/dataflair-python-calculator/dataflair-python-calculator.py
注意替换自身电脑python解释器路径和.py文件路径。
编译后输出如下计算器界面:
6 拓展---打包为可执行文件
6.1 安装 PyInstaller
pip install pyinstaller
6.2 进入.py文件目录
cd G:\learning\python\projects\calculator\dataflair-python-calculator
注意如上路径替换为.py文件的实际路径。
6.3 创建可执行文件
pyinstaller --onefile your_script.py
其中 your_script.py
是您的 Python 脚本文件名。--onefile
参数告诉 PyInstaller 将所有依赖项合并到一个单独的可执行文件中。
6.4 找到并双击可执行文件
可执行文件将位于 dist
目录下。可以将该目录下的文件复制到任何位置,并且可以在没有安装 Python解释器的情况下运行它。
双击dataflair-python-calculator.exe可执行文件,运行界面如下:
7 完整代码
#Importing the necessary modules
from tkinter import *
# import parser
import ast
from math import factorial
root = Tk()
root.title('基于python tkinter的计算器')
#It keeps the track of current position on the input text field
i = 0
# Receives the digit as parameter and display it on the input field
def get_variables(num):
global i
display.insert(i,num)
i+=1
# Calculate function scans the string to evaluates and display it
# def calculate():
# entire_string = display.get()
# try:
# a = ast.parse(entire_string).compile()
# result = eval(a)
# clear_all()
# display.insert(0,result)
# except Exception:
# clear_all()
# display.insert(0,"Error")
def calculate():
entire_string = display.get()
try:
a = ast.parse(entire_string, mode="eval")
result = eval(compile(a, "", mode="eval"))
clear_all()
display.insert(0,result)
except Exception:
clear_all()
display.insert(0,"Error")
# Function which takes operator as input and displays it on the input field
def get_operation(operator):
global i
length = len(operator)
display.insert(i,operator)
i+=length
#Function to clear the input field
def clear_all():
display.delete(0,END)
#Function which works like backspace
def undo():
entire_string = display.get()
if len(entire_string):
new_string = entire_string[:-1]
clear_all()
display.insert(0,new_string)
else:
clear_all()
display.insert(0,"Error")
#Function to calculate the factorial and display it
def fact():
entire_string = display.get()
try:
result = factorial(int(entire_string))
clear_all()
display.insert(0,result)
except Exception:
clear_all()
display.insert(0,"Error")
#--------------------------------------UI Design ---------------------------------------------
#adding the input field
display = Entry(root)
display.grid(row=1,columnspan=6,sticky=N+E+W+S)
#Code to add buttons to the Calculator
Button(root,text="1",command = lambda :get_variables(1)).grid(row=2,column=0, sticky=N+S+E+W)
Button(root,text=" 2",command = lambda :get_variables(2)).grid(row=2,column=1, sticky=N+S+E+W)
Button(root,text=" 3",command = lambda :get_variables(3)).grid(row=2,column=2, sticky=N+S+E+W)
Button(root,text="4",command = lambda :get_variables(4)).grid(row=3,column=0, sticky=N+S+E+W)
Button(root,text=" 5",command = lambda :get_variables(5)).grid(row=3,column=1, sticky=N+S+E+W)
Button(root,text=" 6",command = lambda :get_variables(6)).grid(row=3,column=2, sticky=N+S+E+W)
Button(root,text="7",command = lambda :get_variables(7)).grid(row=4,column=0, sticky=N+S+E+W)
Button(root,text=" 8",command = lambda :get_variables(8)).grid(row=4,column=1, sticky=N+S+E+W)
Button(root,text=" 9",command = lambda :get_variables(9)).grid(row=4,column=2, sticky=N+S+E+W)
#adding other buttons to the calculator
Button(root,text="AC",command=lambda :clear_all()).grid(row=5,column=0, sticky=N+S+E+W)
Button(root,text=" 0",command = lambda :get_variables(0)).grid(row=5,column=1, sticky=N+S+E+W)
Button(root,text=" .",command=lambda :get_variables(".")).grid(row=5, column=2, sticky=N+S+E+W)
Button(root,text="+",command= lambda :get_operation("+")).grid(row=2,column=3, sticky=N+S+E+W)
Button(root,text="-",command= lambda :get_operation("-")).grid(row=3,column=3, sticky=N+S+E+W)
Button(root,text="*",command= lambda :get_operation("*")).grid(row=4,column=3, sticky=N+S+E+W)
Button(root,text="/",command= lambda :get_operation("/")).grid(row=5,column=3, sticky=N+S+E+W)
# adding new operations
Button(root,text="pi",command= lambda :get_operation("*3.14")).grid(row=2,column=4, sticky=N+S+E+W)
Button(root,text="%",command= lambda :get_operation("%")).grid(row=3,column=4, sticky=N+S+E+W)
Button(root,text="(",command= lambda :get_operation("(")).grid(row=4,column=4, sticky=N+S+E+W)
Button(root,text="exp",command= lambda :get_operation("**")).grid(row=5,column=4, sticky=N+S+E+W)
Button(root,text="<-",command= lambda :undo()).grid(row=2,column=5, sticky=N+S+E+W)
Button(root,text="x!", command= lambda: fact()).grid(row=3,column=5, sticky=N+S+E+W)
Button(root,text=")",command= lambda :get_operation(")")).grid(row=4,column=5, sticky=N+S+E+W)
Button(root,text="^2",command= lambda :get_operation("**2")).grid(row=5,column=5, sticky=N+S+E+W)
Button(root,text="=",command= lambda :calculate()).grid(columnspan=6, sticky=N+S+E+W)
root.mainloop()
源码及打包后的可执行文件下载:https://download.csdn.net/download/sb2220/89665703
以上实战项目参考:https://data-flair.training/blogs/python-calculator-project/
END!!!