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

作者:八一 时间:2022-07-16 10:42:30 

前言

上机实践课程开始了,嗯,老师来了之后念了下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是定位内容在面板中的位置,如下图

方向示例表格
nwnne
wcentere
swsse

关于面板以及后边的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)实现一个简单计算器

来源:https://segmentfault.com/a/1190000012474725

标签:python3.6,tkinter,简单计算器
0
投稿

猜你喜欢

  • OpenCV 使用imread()函数读取图片的六种正确姿势

    2021-07-22 13:01:28
  • JavaScript Memoization

    2008-05-01 12:48:00
  • 妄想or未来?界面的虚拟现实化

    2010-03-01 12:53:00
  • SQL 查询语句积累

    2024-01-27 06:32:18
  • 利用Go语言实现简单Ping过程的方法

    2024-04-25 13:22:53
  • 在Ubuntu/Linux环境下使用MySQL开放/修改3306端口和开放访问权限

    2024-01-14 00:47:02
  • python连接、操作mongodb数据库的方法实例详解

    2024-01-12 13:44:40
  • 在Python程序和Flask框架中使用SQLAlchemy的教程

    2021-10-28 06:14:21
  • Python编程实现控制cmd命令行显示颜色的方法示例

    2023-07-24 05:39:45
  • Python语言中Tuple的由来分析

    2021-07-01 16:36:11
  • python argparser的具体使用

    2023-07-13 09:25:36
  • 通过java备份恢复mysql数据库的实现代码

    2024-01-25 23:44:58
  • JS中定位 position 的使用实例代码

    2024-05-03 15:05:09
  • SQL数据库实例名称找不到或远程连接失败并显示错误error40的原因及解决办法

    2024-01-27 11:40:18
  • 全面理解javascript的caller,callee,call,apply概念

    2007-12-02 17:44:00
  • Python中常用功能的实现代码分享

    2021-02-25 00:26:08
  • 解决项目pycharm能运行,在终端却无法运行的问题

    2021-11-03 21:05:07
  • Python自动发送邮件的方法实例总结

    2023-05-21 02:53:42
  • Vue实例中生命周期created和mounted的区别详解

    2024-04-29 13:08:15
  • chr(9)、chr(10)、chr(13)、chr(32)与特殊空格

    2009-07-03 15:26:00
  • asp之家 网络编程 m.aspxhome.com