侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

Python  /  管理员 发布于 7年前   331

前言

上机实践课程开始了,嗯,老师来了之后念了下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 tkinterimport osfrom 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 pythonimport tkinterfrom tkinter import *import tkinter.font as tkfontroot=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()


打包

C:\Users\bayi\Desktop\shiyan\progrem(venv) λ pip install pyinstallerC:\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我似乎对美工要求挑剔........

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

总结

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


  • 上一条:
    Python实现自动发送邮件功能
    下一条:
    Python读取Json字典写入Excel表格的方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客