当前环境:
windows + python3.7 + tkinter 模块
一、总体规划
1、需要用到的模块有 tkinter
2、tkinter 模块中需要用到的知识点有:
2.1、创建主窗口
2.2、Frame 框架
2.3、Button 控件
2.4、Entry 控件
2.5、绑定变量
2.6、绑定事件(事件触发)
2.7、控件布局(绝对布局)
二、完成后的效果图(没有精修,控件的布局各位可自定义)
目前该简易计算器能实现 “加”、“减”、“乘”、“除”、“取余”、“平方”、“清除显示”、“退出”等基本功能!
简要说明:
2.1、第一个白色边框是用户输入(点击),会在此处显示用户输入的信息,第二个白框(下方的白色边框)是用户计算后的结果显示
2.2、目前没有增加 “()” 的功能, 所以视觉效果并不是很好
三、开始实施
3.1、 创建主窗口
首先我们创建一个主窗口,代码如下:
import tkinter
# 创建一个主窗口
windows = tkinter.Tk()
# 设置窗口标题
windows.title( " 框架显示 ")
# 设置 窗口大小以及初始位置
windows.geometry( "600x400+400+200")
# 窗口大小不允许改变
windows.resizable(0, 0)
######################### 核心区域 ########################
#####################################################################
#进入消息循环
windows.mainloop()
说明:
a、我们需要引入 tkinter 模块 < import tkinter >
b、我们需要创建一个 主窗口 windows (叫啥名都可以)。 后面,我们所有的控件都是摆放在此主窗口上。< windows = tkinter.Tk() >
c、我们可以给主窗口设置一个标题, 通过 title() 方法
d、定义窗口大小已经窗口的默认位置 ----> "600x400+400+200"
解释: 600 表示窗口的长度, 400 表示窗口的宽度。 中间用 英文字母 “x” 连接,
而且不能存在空格, +400, 表示该主窗口出现的位置是距离左边屏幕400, +200,表
示该主窗口出现的位置是距离屏幕上方 200
e、 windows.resizable(0, 0) 表示窗口大小不能改变(如果不写该语句),我么可以通
过鼠标,对我们创建的主窗口进行大小的拉升与缩放。鉴于我们写的是简易计算器,需要对
给各个控件进行布局,所以在此,我们将主窗口设置为固定大小的窗口。
f、 windows.mainloop() 该代码主要是让程序阻塞,不会让程序直接显示完就结束。
要不然我们看不到创建的主窗口,程序一运行,就结束,关闭了!
3.2、使用面向对象的思想去创建其他控件
代码如下:
import tkinter
class CtrlView():
def __init__(self,root ):
self.root = root
# 创建一个 Frame 框架 ,
self.frameBox = tkinter.Frame( root, height = 400 , width = 600 )
self.frameBox.place(x=0, y=0)
# 绑定变量 , 创建一个变量
self.e1 = tkinter.Variable()
self.e2 = tkinter.Variable()
self.textArea = tkinter.Entry(self.frameBox, width=45, textvariable = self.e1 )
self.textArea.place(x=165, y=80 )
self.textArea2 = tkinter.Entry(self.frameBox, width=45, textvariable = self.e2 )
self.textArea2.place(x=165, y=110 )
a、我们创建了一个 类名为 CtrlView() 的类。
b、在构造方法中,我们创建了一个 Frame 框架,Frame 可以想象成一个容器, 我们
首先将 该容器(Frame)放入到 主窗口中(也就是 root (形参,类实例化的时候,需要
将 widows 传递过来 ) ),
self.frameBox = tkinter.Frame( root, height = 400 , width = 600 )
参数说明:
“root”: 表示我们的父窗口, 在此处表示 windows 窗体。
height: 设置 Frame 容器的高度(竖直方向)
width: 设置 Frame 容器的宽度 (水平方向)
【备注】:
还有比较多的参数,后期会专门介绍 tkinter 模块中的所有控件,详细说明
c、给 Frame 容器进行定位(此处我们使用的是,绝对定位) place() 方法
self.frameBox.place(x=0, y=0)
参数说明:
x: 表示距离父窗口的左上角顶点 x 轴的距离
y: 表示距离父窗口的左上角顶点 y 轴的距离
所以,我们这里就是和主窗体 windows 的大小以及起点一致
d、在构造方法中,我们还创建了 Entry 控件
self.textArea = tkinter.Entry(self.frameBox, width=45, textvariable = self.e1 )
解释:在 tkinter 模块中,我们创建一个控件,都是通过 tkinter 这个类进行创建
的, 格式:---> tkinter.控件名( "父窗口“ , *args )。 在此处,我们的父窗口就是 Frame
容器。 width 表示 这个Entry 控件的宽度。 (还有很多参数,不详细说明),
textvariable 表示 我们需要绑定的变量。(因为,我们需要获取到 Entery 控件,也就是
白色框里面的值 )。
e、创建变量 self.e1 = tkinter.Variable()
该变量,主要是用于后面给 Entry 控件设置值和取值
f、给 Entry 控件进行定位 self.textArea.place(x=165, y=80 )
也是绝对定位, 和 Frame 容器定位一样
3.3、创建 Button 控件(例如数字 1-9, +-*÷ 等都是 Button 控件)
思路:
因为,计算器中 按钮 比较多, 所以我们需要创建一个 类方法。每次只要调用这个
方法就可以创建一个 Button 控件,并给其进行定位。
代码如下:
def func(self,str):
# ################################# 逻辑处理部分 ####################
# ####### 点击的是 Quit ---- 退出程序
if str == "Quit":
self.root.quit()
# ####### 点击的是 C---- 清空当前所有输入信息
elif str == "C":
self.textArea.delete(0,len(self.e1.get() ) )
elif str == "=":
try:
self.textArea2.delete( 0, len(self.e2.get() ) )
print(" ******* ----> ==== ", type( self.e1.get() ) , self.e1.get() )
res = self.e1.get()
self.textArea2.insert( "end", eval( res ) )
# time.sleep(1)
self.textArea.delete(0, len(self.e1.get()) )
except SyntaxError as e:
self.textArea2.insert("end", "0 不能作为被除数")
except Exception as e:
print(" 当前按了 = 号", str(e))
# finally:
# self.textArea2.insert("end", "当前结果输入有误")
else:
print('当前点击的按钮是: %s' % str)
self.textArea.insert("end", str)
# 创建按钮
def addButton(self,str,distance_X =0 ,distance_Y = 0 ,widthSize =5 , heightSize = 2 ,color = None ,fontSize = None ):
# 创建一个 button 控件
button = tkinter.Button( self.frameBox, width = widthSize , height = heightSize ,text = str ,bg = color, font = fontSize, command= lambda :self.func(str) )
button.place(x=distance_X, y=distance_Y)
a、我们写了一个 addButton() 的方法
参数说明:
str: 按钮上要显示的字符串 , 如: 1,2,3,……,+,-,*,÷ 等
distance_X:绝对定位时, 距离 X 轴的距离
distance_Y: 绝对定位时, 距离 Y 轴的距离
widthSize:: Button 控件的宽度
heightSize:Button 控件的高度
color:Button 控件的颜色显示, 默认None, 系统默认值
fontSize:Button 控件中文字的大小, 默认None, 系统默认值
b、创建 Button 控件
button = tkinter.Button( self.frameBox, width = widthSize , height = heightSize ,text = str ,bg = color, font = fontSize, command= lambda :self.func(str) )
解释:参数 command 表示绑定的方法, 当点击该 Button 控件时,所触发的
函数,这里我们触发的函数就是 “ func( str )” , 我们将 str 传递给该函数, 所以每次
点击某个按钮时,就能获取到该按钮上的值。 例如,当我们点击按钮数字 1 时, 该
方法,就能获取到数字 1 。
c、功能方法 func( str )
该功能函数,是主要的逻辑处理部分。
当我们按下, Quit 时,此时计算器应该退出,所以我们执行了 self.root.quit()
方法,该方法是让我们的主窗口(windows窗口) 关闭, 所以程序退出。当我们按下
“=” 号的时候,就应该计算当前的数据。 所以,我们第一步是删除了 Enter 控件中的
数据,例如以前的计算结果信息, self.textArea2.delete( 0, len(self.e2.get() ) )
delete() 方法中的参数是
第一个参数是:起始位置,肯定是从 头开始删除,所以是 0
第二个参数是:结束位置, 但是我们并不知道结束位置的下标, 但是我们能获取
到该 Entey 控件中文字信息, e2.get() 方法, 然后该文字信息的总长度,就是我们结束
位置的下标。
显示结果信息, 我们通过 Entry 控件中的 insert 方法,将 计算结果插入到 Entey
中显示, res = self.e1.get()
self.textArea2.insert( "end", eval( res ) )
其中 res 是从 Entry 控件中绑定的 变量 e, 获取到的信息。 结果为 字符串类型。 我
们可以通过 eval() 方法, 将str 字符串类型的数据,直接进行数学运算,返回的是字符
串所得到的结果。最后插入到 Entry 控件中显示。
而且进行完计算后,我们也需要删除我们输入的计算内容: 如 3 + 4 , 3* 7 等数
据。 因此我们用了相同方法,删除了 Entry 控件中的内容。
3.4、主程序:
首先我们应该导入 类(我们写的类)
然后对类进行实例化
# 创建一个 视图类对象 ctrlView = CtrlView(windows)
创建完类对象后,我们就相当于创建一个 Frame 容器, 2个 Entry 控件
通过类对象创建 Button 控件,并给 Button 按钮进行绝对定位,并传入不同的 字符串
代码如下:
# 创建一个 视图类对象
ctrlView = CtrlView(windows)
####################### 创建数字按钮 ----------
# 创建 10 个数字,并定位布局
# 数字 0
ctrlView.addButton( str = "//" , distance_X = 230 , distance_Y = 350 ,color="cyan")
ctrlView.addButton( str = "0" , distance_X = 280 , distance_Y = 350 ,color="gray")
ctrlView.addButton( str = "." , distance_X = 330 , distance_Y = 350 ,color="cyan" )
# 数字 123
ctrlView.addButton( str = "1" , distance_X = 230 , distance_Y = 300 ,color="gray")
ctrlView.addButton( str = "2" , distance_X = 280 , distance_Y = 300 ,color="gray")
ctrlView.addButton( str = "3" , distance_X = 330 , distance_Y = 300 ,color="gray")
四、效果图
至此,我们就完成了简易 的计算器
五、完整代码
5.1、main 文件
# -*- encoding: utf-8
# @ModuleName: main
# @function
# @Author : Stranger
# @Time: 2021/7/29 12:16
import tkinter
from tkinter import ttk
from ctrlView import CtrlView
# 创建一个主窗口
windows = tkinter.Tk()
# 设置窗口标题
windows.title( " 框架显示 ")
# 设置 窗口大小以及初始位置
windows.geometry( "600x400+400+200")
# 窗口大小不允许改变
windows.resizable(0, 0)
######################### 核心区域 ###################################
# 创建一个 视图类对象
ctrlView = CtrlView(windows)
####################### 创建数字按钮 ----------
# 创建 10 个数字,并定位布局
# 数字 0
ctrlView.addButton( str = "//" , distance_X = 230 , distance_Y = 350 ,color="cyan")
ctrlView.addButton( str = "0" , distance_X = 280 , distance_Y = 350 ,color="gray")
ctrlView.addButton( str = "." , distance_X = 330 , distance_Y = 350 ,color="cyan" )
# 数字 123
ctrlView.addButton( str = "1" , distance_X = 230 , distance_Y = 300 ,color="gray")
ctrlView.addButton( str = "2" , distance_X = 280 , distance_Y = 300 ,color="gray")
ctrlView.addButton( str = "3" , distance_X = 330 , distance_Y = 300 ,color="gray")
# 数字 456
ctrlView.addButton( str = "4" , distance_X = 230 , distance_Y = 250 ,color="gray")
ctrlView.addButton( str = "5" , distance_X = 280 , distance_Y = 250 ,color="gray")
ctrlView.addButton( str = "6" , distance_X = 330 , distance_Y = 250 ,color="gray")
# 数字 789
ctrlView.addButton( str = "7" , distance_X = 230 , distance_Y = 200 ,color="gray")
ctrlView.addButton( str = "8" , distance_X = 280 , distance_Y = 200 ,color="gray")
ctrlView.addButton( str = "9" , distance_X = 330 , distance_Y = 200 ,color="gray")
####################### 创建加减乘除按钮 ----------
ctrlView.addButton( str = "+" , distance_X = 380 , distance_Y = 200 ,color="cyan")
ctrlView.addButton( str = "-" , distance_X = 380 , distance_Y = 250 ,color="cyan")
ctrlView.addButton( str = "*" , distance_X = 380 , distance_Y = 300 ,color="cyan")
ctrlView.addButton( str = "÷" , distance_X = 380 , distance_Y = 350 ,color="cyan")
####################### 创建一个显示框 Label ----------
# ctrlView.addTextArea(distance_X = 120, distance_Y = 10 )
####################### 创建 功能按钮 ----------
ctrlView.addButton( str = "=" , distance_X = 430 , distance_Y = 350 ,color="orange")
ctrlView.addButton( str = "m²" , distance_X = 430 , distance_Y = 300 ,color="orange")
ctrlView.addButton( str = "m³" , distance_X = 430 , distance_Y = 250 ,color="orange")
ctrlView.addButton( str = "1/2" , distance_X = 430 , distance_Y = 200 ,color="orange")
ctrlView.addButton( str = "1/3" , distance_X = 180 , distance_Y = 350 ,color="white")
ctrlView.addButton( str = "2/3" , distance_X = 180 , distance_Y = 300 ,color="white")
ctrlView.addButton( str = "1/4" , distance_X = 180 , distance_Y = 250 ,color="white")
ctrlView.addButton( str = "3/4" , distance_X = 180 , distance_Y = 200 ,color="white")
ctrlView.addButton( str = "C" , distance_X = 180 , distance_Y = 150 ,color="cyan")
ctrlView.addButton( str = "Del" , distance_X = 430 , distance_Y = 150 ,color="cyan")
ctrlView.addButton( str = "%" , distance_X = 230 , distance_Y = 150 ,color="cyan")
ctrlView.addButton( str = "Save" , distance_X = 280 , distance_Y = 150 ,color="cyan")
ctrlView.addButton( str = "Print" , distance_X = 330 , distance_Y = 150 ,color="cyan")
ctrlView.addButton( str = "Quit" , distance_X = 380 , distance_Y = 150 ,color="cyan")
####################### 绑定事件 ----------
################################################################################
#进入消息循环
windows.mainloop()
5.2、ctrlView.py 文件
# -*- encoding: utf-8
# @ModuleName: ctrlView
# @function
# @Author : Stranger
# @Time: 2021/7/29 12:18
import tkinter
import time
class CtrlView():
# 绑定变量 , 创建一个变量
# e = tkinter.Variable()
def __init__(self,root ):
self.root = root
# 创建一个 Frame 框架 ,
self.frameBox = tkinter.Frame( root, height = 400 , width = 600 )
self.frameBox.place(x=0, y=0)
# 绑定变量 , 创建一个变量
self.e1 = tkinter.Variable()
self.e2 = tkinter.Variable()
self.textArea = tkinter.Entry(self.frameBox, width=45, textvariable = self.e1 )
self.textArea.place(x=165, y=80 )
self.textArea2 = tkinter.Entry(self.frameBox, width=45, textvariable = self.e2 )
self.textArea2.place(x=165, y=110 )
def func(self,str):
# ################################# 逻辑处理部分 ####################
# ####### 点击的是 Quit ---- 退出程序
if str == "Quit":
self.root.quit()
# ####### 点击的是 C---- 清空当前所有输入信息
elif str == "C":
self.textArea.delete(0,len(self.e1.get() ) )
elif str == "=":
try:
self.textArea2.delete( 0, len(self.e2.get() ) )
print(" ******* ----> ==== ", type( self.e1.get() ) , self.e1.get() )
res = self.e1.get()
self.textArea2.insert( "end", eval( res ) )
# time.sleep(1)
self.textArea.delete(0, len(self.e1.get()) )
except SyntaxError as e:
self.textArea2.insert("end", "0 不能作为被除数")
except Exception as e:
print(" 当前按了 = 号", str(e))
else:
print('当前点击的按钮是: %s' % str)
self.textArea.insert("end", str)
# 创建按钮
def addButton(self,str,distance_X =0 ,distance_Y = 0 ,widthSize =5 , heightSize = 2 ,color = None ,fontSize = None ):
# 创建一个 button 控件
button = tkinter.Button( self.frameBox, width = widthSize , height = heightSize ,text = str ,bg = color, font = fontSize, command= lambda :self.func(str) )
button.place(x=distance_X, y=distance_Y)
说明:将上面两个文件放入同一个目录,然后运行 main.py 文件即可