利用Tkinter(python3.6)实现一个简单计算器


Posted in Python onDecember 21, 2017

前言

上机实践课程开始了,嗯,老师来了之后念了下PPT,然后说:开始做吧.........

然后就开始了Python的GUI之路,以前没接触过PYthon的可视化界面(虽然这样很不明智)

但是现在做起来感觉写小工具还挺方便的,当时搜到的第一个库便是Tkinter就直接开始写了

后来发现QT很不错的样子,下个实验就用QT吧.然后关于Tkinter(python3.6)

计算器源码 ennn.....有的命名不规范.......

首先对于python中栈的实现是通过list的方式模拟

pop()出栈,append()入栈

首先我们来看一下常用的TKinter提供的核心小构件类:

小构件类 描述
Button 按钮
Canvas 结构化图形,用于绘制图形,创建图形编辑器以及实现自定义小构件类
Checkbutton 单击复选按钮在值之间切换
Entry 文本域或称文本框
Frame 容器(可包含其他的小构件)
Label 显示文本或图像
Menu 显示下拉菜单和弹出菜单的菜单栏
Menubutton 下拉菜单的菜单按钮
Message 类似于标签显示文本,但能自动将文本放在给定宽高内
Radiobutton 单选按钮
Text 格式化的文本显示,支持内嵌图片和文本,允许用不同风格和属性显示和编辑文本

开始一个窗口

做一个可视化的东西,首先想到的坑定是窗口吧

窗口又有很多构成,比如title,ico,size,bd,菜单等.

import tkinter
import os
from tkinter import *
class Calculator(object):
 """计算器"""
 def __init__(self):
 self.tk=tkinter.Tk() #实例化
 self.tk.title('计算器')
 self.tk.minsize(370,460)
 self.tk.maxsize(400,400)
 #也可以用self.tk.resizable(0, 0)来禁止调节大小
 self.tk.iconbitmap(os.getcwd()+'/favicon.ico')
 def start(self):
 self.tk.mainloop() 
if __name__ == '__main__':
 NewCalculator=Calculator()
 NewCalculator.start()

这里就生成了一个基本的窗口,对于其中的mainloop()的作用

如果我们删除它,窗口会一闪而过,它就是为了防止这种情况

面板显示

做成计算器之后坑定要先是计算结果,这里就需要生成显示面板

当然我们也会很自然地联想到显示内容的字体设置等需求,具体事例在下面代码

....
import tkinter.font as tkfont
....
 #字体设置
 self.EntryFont=tkfont.Font(self.tk,size=13)
 self.ButtonFont=tkfont.Font(self.tk,size=12)
 #面板显示
 self.count=tkinter.StringVar()
 self.count.set('0')
 self.label=tkinter.Label(self.tk,bg='#EEE9E9',bd='3',fg='black',anchor='center',font=self.EntryFont,textvariable=self.count)
 self.label.place(y=10,width=380,height=40)
....

其中tkinter中面板Lable有一些参数,这里用到的基本上也可以满足常见的需求了

其中bg是背景色,fg是前景色,改变内容的颜色,anchor是定位内容在面板中的位置,如下图

方向 示例 表格
nw n ne
w center e
sw s se

关于面板以及后边的Button的定位,可以用很多方式,place可以准确的定位,也可以用pack(),grid()

对于计算器place是更好的,能够准确定位每一个控件

其中字体也可以直接在Lable()加参数,例如font=("Arial,6")

textvariable相当于“监听”的作用,绑定tkinter中的string,就可以用set()的方式方便的改变面板的内容

按钮,输入框设置

按钮,输入框的参数和面板里面的是相似的

self.NumButton=tkinter.Button(master=self.tk,relief=GROOVE,bg='#EE6A50',text=self.ButtonList[0],
 font=self.ButtonFont,command=self.clear)
self.NumButton.place(x=30,y=80,width=70,height=55)
self.shiEntry=Entry(self.baoxianTk,validate='key',validatecommand=(self.checkNum,'%P'),font=self.EntryFont)
self.shiEntry.place(x=190,y=80)

一样的是通过bg等参数设置基础的样式,只不过这里会通过command绑定事件,类似于JQ中的.click

这里的place也是为了能够准确定位才使用的,其中的relief代表着Button的样式

relief=FLAT or GROOVE or RAISED or RIDGE or SOLID or SUNKEN

其中删除输入框的输入内容

text.delete(10) #删除索引值为10的值
text.delete(10, 20) #删除索引值从10到20之前的值
text.insert(0, END) #删除所有值

输入限制

在设计功能的时候我们可能需要用户输入数字等,这里可以进行限制一下

Button参数中validate指定什么时候执行validatecommand绑定的函数,使用%P可以实时获取输入的内容

当validate选项指定为key的时候,有任何的输入操作都会被拦截,这个时候返回True白能量才会输入到Entry

self.checkNum=self.baoxianTk.register(self.validateNum)
self.gerenEntry=Entry(self.baoxianTk,validate='key',validatecommand=(self.checkNum,'%P'),font=self.EntryFont)
self.gerenEntry.place(x=190,y=190)
#验证是否输入数字 
def validateNum(self,content):
 if content.isdigit() and int(content)>=0 or content=="":
 return True
 else:
 return False

validateNum()函数可以根据自己的需求进行更改

启用验证validate选项可以设置的值有:

名称 事件
focus 当 Entry 组件获得或失去焦点的时候验证
focusin 当 Entry 组件获得焦点的时候验证
focusout 当 Entry 组件失去焦点的时候验证
key 当输入框被编辑的时候验证
all 当出现上边任何一种情况的时候验证

拓展符号设计

这个小计算器中我增加了%,/,sqrt三个符号

对于他们的实现我的思路是添加到面板之前检测一下传入的button内容

如果是这三种符号则做出对应的处理

其中需要注意如果是多位数或者带有符号式子

不能直接进行变换,需要判断你要转置的数字的位数,我的具体方式如下

def checkList(self):
 result=0
 locate=-1
 listSum=0
 for length in range(0,len(self.inputlist)):
 if re.findall(r'[-+*/]',str(self.inputlist[length])):
 result=1
 if length>locate:
  locate=length
 else:
 pass
 if result==1:
 for i in range(locate+1,len(self.inputlist)):
 listSum+=int(self.inputlist[i])*(10**(len(self.inputlist)-i-1))
 else:
 for j in range(0,len(self.inputlist)):
 listSum+=int(self.inputlist[j])*(10**(len(self.inputlist)-j-1))
 return listSum,locate
 #添加button
 def addButton(self,button):
 if button==self.ButtonList[18]:
 listSum,locate=self.checkList()
 if locate==-1:
 self.inputlist=[str(round(eval('1/'+str(listSum)),5))]
 else:
 for k in range(locate+1,len(self.inputlist)):
  del self.inputlist[k]
 self.inputlist.append(str(round(eval('1/'+str(listSum)),5)))
 elif button==self.ButtonList[19]:
 pass
 elif button==self.ButtonList[20]:
 pass
 else:
 self.inputlist.append(button)
 self.count.set(self.inputlist)

关于lambda

百度百科:Lambda表达式是Python中一类特殊的定义函数的形式,使用它可以定义一个匿名函数

与其它语言不同,Python的Lambda表达式的函数体只能有唯一的一条语句,也就是返回值表达式语句

搜索更多文章后理解更多,Lambda函数可以说是对按钮起到“call back”的作用

如果我们不使用Lambda进行中间函数的延迟回调,在创建按钮的同时command绑定的函数会被调用

即如下面两句代码的区别,第二句在进行创建时会直接执行knobDown函数

self.NumButton=tkinter.Button(master=self.tk,relief=GROOVE,bg='#BFEFFF',text=self.ButtonList[20],  font=self.ButtonFont,command=lambda:self.knobDown(self.ButtonList[20]))
self.NumButton=tkinter.Button(master=self.tk,relief=GROOVE,bg='#BFEFFF',text=self.ButtonList[20],  font=self.ButtonFont,command=self.knobDown(self.ButtonList[20]))

更详细的解释可以参考文末最后两个文章,还是前辈写得好

关于单选框

本来想实现PPT中给出的示例-房贷计算的拓展,但是一直这个单选框产生BUG就放弃了

下面的示例是从网上摘抄过来的,具体的网址忘了

就是通过variable绑定一个IntVar() ,通过.get()方式可以获取Radiobutton中value的值

#!/usr/bin/env python
import tkinter
from tkinter import *
import tkinter.font as tkfont
root=tkinter.Tk()
val=tkinter.IntVar()
val.set(0)
def func1():
 if val.get() == 0:
 label.configure(text='radio 0')
 else:
 label.configure(text='radio 1')

label = tkinter.Label(root, text='radio 0')
label.pack()
r0 = tkinter.Radiobutton(text = 'radio0', variable = val, value = 0)
r0.pack()
r1 = tkinter.Radiobutton(text = 'radio1', variable = val, value = 1)
r1.pack()
b = tkinter.Button(root, text='button', command=func1)
b.pack()
root.mainloop()

利用Tkinter(python3.6)实现一个简单计算器

打包

C:\Users\bayi\Desktop\shiyan\progrem
(venv) λ pip install pyinstaller
C:\Users\bayi\Desktop\shiyan\progrem
(venv) λ pyinstaller -F -w -i favicon.ico run.py

一开始因为代码中的设置ico图标为下面代码第一行

windows下打包路径识别有问题,把图标换到一个路径短的地方

修改成绝对路径就OK了(下面代码第二行,exe和ico要放在同一个目录下

self.baoxianTk.icobitmap('favicon.ico')
self.baoxianTk.iconbitmap(os.getcwd()+'/favicon.ico')

效果预览

虽然是现学现卖和对于别人的老知识,但是成功之后还是挺有成就感的(and我似乎对美工要求挑剔........

调颜色和样式能挑半天,包括以前的那个爬虫的前端

利用Tkinter(python3.6)实现一个简单计算器

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python中的列表推导浅析
Apr 26 Python
Python用 KNN 进行验证码识别的实现方法
Feb 06 Python
Python3读取Excel数据存入MySQL的方法
May 04 Python
基于python的图片修复程序(实现水印去除)
Jun 04 Python
pyqt5的QComboBox 使用模板的具体方法
Sep 06 Python
详解pandas安装若干异常及解决方案总结
Jan 10 Python
python实现两张图片的像素融合
Feb 23 Python
centos7之Python3.74安装教程
Aug 15 Python
python中dict()的高级用法实现
Nov 13 Python
python实现两个一维列表合并成一个二维列表
Dec 02 Python
python 实时调取摄像头的示例代码
Nov 25 Python
python分分钟绘制精美地图海报
Feb 15 Python
python编写朴素贝叶斯用于文本分类
Dec 21 #Python
python并发2之使用asyncio处理并发
Dec 21 #Python
利用Python暴力破解zip文件口令的方法详解
Dec 21 #Python
Python人脸识别初探
Dec 21 #Python
python中判断文件编码的chardet(实例讲解)
Dec 21 #Python
python 设置文件编码格式的实现方法
Dec 21 #Python
Python+OpenCV人脸检测原理及示例详解
Oct 19 #Python
You might like
php中unlink()、mkdir()、rmdir()等方法的使用介绍
2012/12/21 PHP
新浪SAE搭建PHP项目教程
2015/01/28 PHP
php内嵌函数用法实例
2015/03/20 PHP
php5.4以上版本GBK编码下htmlspecialchars输出为空问题解决方法汇总
2015/04/03 PHP
jMessageBox 基于jQuery的窗口插件
2009/12/09 Javascript
javascript使用activex控件的代码
2011/01/27 Javascript
鼠标经过tr时,改变tr当前背景颜色
2014/01/13 Javascript
jquery统计用户选中的复选框的个数
2014/06/06 Javascript
JavaScript设计模式之工厂方法模式介绍
2014/12/28 Javascript
javascript表格的渲染组件
2015/07/03 Javascript
BootStrap的Datepicker控件使用心得分享
2016/05/25 Javascript
node.js 动态执行脚本
2016/06/02 Javascript
JS扩展类,克隆对象与混合类实例分析
2016/11/26 Javascript
详解AngularJS用Interceptors来统一处理HTTP请求和响应
2017/06/08 Javascript
基于webpack 实用配置方法总结
2017/09/28 Javascript
bootstrap-table.js扩展分页工具栏(增加跳转到xx页)功能
2017/12/28 Javascript
JavaScript生成指定范围随机数和随机序列的方法
2018/05/05 Javascript
vue2.0 element-ui中el-select选择器无法显示选中的内容(解决方法)
2018/08/24 Javascript
学习python 之编写简单乘法运算题
2016/02/27 Python
Python中字符串的常见操作技巧总结
2016/07/28 Python
基于Python的文件类型和字符串详解
2017/12/21 Python
PyTorch读取Cifar数据集并显示图片的实例讲解
2018/07/27 Python
python实现计算器功能
2019/10/31 Python
python实现将字符串中的数字提取出来然后求和
2020/04/02 Python
Django 允许局域网中的机器访问你的主机操作
2020/05/13 Python
eBay美国官网:eBay.com
2020/10/24 全球购物
经典c++面试题六
2012/01/18 面试题
团日活动总结报告
2014/06/25 职场文书
应届大专生求职信
2014/06/26 职场文书
村道德模范事迹材料
2014/08/28 职场文书
用人单位聘用意向书
2015/05/11 职场文书
2015年电教工作总结
2015/05/26 职场文书
2016年校园社会综合治理宣传月活动总结
2016/03/16 职场文书
2019学校运动会开幕词
2019/05/13 职场文书
实体类或对象序列化时,忽略为空属性的操作
2021/06/30 Java/Android
Fluentd搭建日志收集服务
2022/09/23 Servers