python中的GUI实现计算器

目录
- 一、学习目标:学会利用python的GUI做界面布局
- 二、学习内容:手写一个简单计算器
- 1、计算器目标图
- 2、 计算器计算功能
- 3、 代码实现与详细说明
- 三、学习优化:学会优化冗于代码
一、学习目标:学会利用python的GUI做界面布局
- 手写计算器代码熟悉控件的使用方法
- 优化计算器代码,解决 获取按钮文本 的方法
- 了解
lambda
函数的传参优点和局限 - 打包生成自己的计算器软件,并独立运行
二、学习内容:手写一个简单计算器
1、计算器目标图
目标计算器设计分为三个部分:
背景部分 :
根:Tk()
展示部分:上方展示算式,下方展示计算结果:
按钮部分:
2、 计算器计算功能
- 加减乘除,放在 = ,按钮上
- 回退,放在 <- 按钮上
- 清除,放在 MC 按钮上
3、 代码实现与详细说明
外观布局:
首先引入包: from tkinter import *
根据目标图片设计布局按钮:定义计算器类,初始化界面控件。
?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172class
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'
))
测试实验与总结:
测试:
?1234if
__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继承Calculator
的back
,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函数对象,就是待回调的函数。
测试总结:
?12345if
__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计算器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:- python中的GUI实现计算器
- python之PyAutoGui教你做个自动脚本计算器的方法
- python 实现简单的计算器(gui界面)
- python GUI计算器的实现
- python GUI模拟实现计算器
- 基于wxpython开发的简单gui计算器实例
相关内容
学习写字楼新选择6000元主流配置
学习写字楼新选择6000元主流配置,,这种配置需要考虑双核心的办...
excel怎么用乘法函数
excel怎么用乘法函数,乘法,函数,哪个,excel乘法函数怎么用?1、...
3500元超额值学生娱乐结构的优化配置
3500元超额值学生娱乐结构的优化配置,,作为一个DIY的主流用户...
优化PostgreSQL中的批量更新性能
优化PostgreSQL中的批量更新性能,数据,表格,在Ubuntu 12.04上...
excel中乘法函数是什么?
excel中乘法函数是什么?,乘法,函数,什么,打开表格,在C1单元格中...
足球彩票的快乐总体偏好价值目标颜色过滤软件免
足球彩票的快乐总体偏好价值目标颜色过滤软件免费试用,,快乐彩...
标准差excel用什么函数?
标准差excel用什么函数?,函数,标准,什么,在数据单元格的下方输...
512内存的电脑优化|笔记本内存512
512内存的电脑优化|笔记本内存512,,1. 笔记本内存512够用,因为...
Lucene学习之高亮显示
Lucene学习之高亮显示,索引,字符,在搜索引擎中我们经常会看到...
电脑函数不正确|电脑出现函数不正确
电脑函数不正确|电脑出现函数不正确,,1. 电脑出现函数不正确故...
计算器的快捷键|计算器的快捷键是哪个
计算器的快捷键|计算器的快捷键是哪个,,计算器的快捷键是哪个...
这种配置还不知道。它主要用于日常学习和娱乐,偶
这种配置还不知道。它主要用于日常学习和娱乐,偶尔玩游戏。,,CP...
Windows7下固态硬盘的优化技术
Windows7下固态硬盘的优化技术,,当微软开发Windows Vista时,固...
cad计算快捷键|cad的计算器快捷键
cad计算快捷键|cad的计算器快捷键,,cad的计算器快捷键一:常用功...
excel函数公式快捷键|excel公式的快捷键
excel函数公式快捷键|excel公式的快捷键,,1. excel公式的快捷...