实践: 使用tkinter实现的计算器

本文介绍了一个使用Python的Tkinter模块实现的简易计算器应用程序。该计算器支持基本的算术运算,包括加、减、乘、除,并能处理括号和百分比计算。文章详细解释了程序的结构和工作原理,包括界面布局、按钮功能和计算逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用tkinter实现的计算器

#!/usr/bin/env pythonright

-- coding: UTF-8 --

#使用tkinter模块实现一个简单的加减乘除计算器

import tkinter as tk
import functools

#常量
maxLen = 40
operator = ('/','*','-','+') #计算符号


class calcuatorApp(tk.Frame):
	#保存计算式内容(由于计算式长度有可能超过能够表示的最大长度,所以需要另外保存)
	processTextBack = ''

	def __init__(self, master=None):
		super().__init__(master)
		self.processTextBack = ''
		self.grid(padx=25, pady=25,sticky=tk.NSEW)
		self.create_widgets()  #生成窗口上的显示区域和按钮

	def create_widgets(self):
		#app随着外层窗口缩放
		top=self.winfo_toplevel()
		top.rowconfigure(0, weight=1)
		top.columnconfigure(0, weight=1)
		# 7行4列的各个组件随着app的大小缩放
		for i in range(7):      #7行自动缩放
			self.rowconfigure(i, weight=1)
		for i in range(4):      #4列自动缩放
			self.columnconfigure(i, weight=1)
		#按钮上显示的字符
		textForBtn = (('C','(',')','%'),   #%为百分号
					  ('7','8','9','/'),
					  ('4','5','6','*'),
					  ('1','2','3','-'),
					  ('0','.','=','+'))

		#界面上第一行用于输出计算式
		self.process = tk.Label(self,text='',font='courier 15',bg='#DCDCDC',anchor = 'e')
		self.process.grid(row=0, columnspan=4, padx=1, pady=1, ipadx=200, ipady=10, sticky=tk.NSEW)

		#界面上第二行用于输出计算结果
		self.result = tk.Label(self,text='',font='courier 15 bold',bg='#DCDCDC',anchor = 'e')
		self.result.grid(row=1, columnspan=4, padx=1, pady=1, ipadx=200, ipady=10, sticky=tk.NSEW)

		#界面上第三行开始用于显示0-9的数字和计算符号
		for i in range(5):      #5行
			for j in range(4):  #4列
				tempbtn = tk.Button(self,text=textForBtn[i][j],font='courier 15',bg='#DCDCDC')
				#点击=按钮(计算)
				if(textForBtn[i][j] == '='):
					tempbtn['command'] = self.equals
				#点击C按钮(清空)
				elif(textForBtn[i][j] == 'C'):
					tempbtn['command'] = functools.partial(self.inputClear)
				else:
				#其他
					tempbtn['command'] = functools.partial(self.inputText,tempbtn)
				tempbtn.grid(row=i+2, column=j, padx=1, pady=1, ipadx=50, ipady=10, sticky=tk.NSEW)

	# 点击C按钮,清空
	def inputClear(self):
		self.processTextBack=''
		self.process['text']=''
		self.result['text']=''

	# 点击=按钮,进行计算
	def equals(self):
		#获取计算式
		processText = self.processTextBack

		#检查计算式: 计算式长度为空,=无效
		if(len(processText) == 0): 
			return
		#检查计算式: 计算式最后一个为=,=重复无效
		if(processText[-1] == '='): 
			return
		#检查计算式: 计算式最后一个为(,报错
		if(processText[-1] == '('): 
			self.result['text']= 'Input Error'
			return
		#检查计算式:操作数不足报错
		if(processText[-1] in '+-/*'): 
			self.result['text']= 'Input Error'
			return
		#)不足的话,自动补齐
		countLeft = processText.count('(')
		countRight = processText.count(')')
		if(countLeft > 0 and  countLeft > countRight):
			processText += ')' * (countLeft - countRight)
		#计算用的字符串里面百分号%替换成/100  (要保证%的优先级)
		processForEval = processText
		sIndex = 0
		while('%' in processForEval):
                    	#开始查找%,切分成左右两边
                    	Index1 =  processForEval.find('%')
                   		strLeft = processForEval[:Index1]
                    	strRight = processForEval[Index1+1:]
                    	#%的前一位为数字:  操作数% 变成 (操作数/100)
                   		if(strLeft[-1].isdigit()):
                            	#%左边字符串的最后一个操作数
                            	strTmp = self.operandLast(strLeft)
                            	strLeft = strLeft[0:len(strLeft) - len(strTmp)] + '('+ strTmp +'/100)'
                    	else:
                    	#%的前一位为): (操作数1 + 操作数2)%  变成((操作数1 + 操作数2)/100)
                            	indexTmp = strLeft.rfind('(')
                            	if(indexTmp == -1):
                                   		indexTmp = 0
                            	strLeft = strLeft[:indexTmp] + '(' + strLeft[indexTmp:] + '/100)'
                    	processForEval = strLeft + strRight
		#计算
		try:
			result = str(eval(processForEval))
		except:
			result = 'Input Error'
		#表示计算式和结果
		self.processTextBack = processText + '='
		self.process['text']=  processText + '='
		self.result['text']= result

	# 点击=,C以外的其他按钮
	def inputText(self, btn):
		#按钮名称
		btnname = btn['text']
		resultClearFlg = False
		resultText = self.result['text']
		#计算式内容确认
		processText = self.processTextBack
		if(len(processText) > 0 and processText[-1] == '='):  #如果计算式以=结尾,则清空既存计算式和结果
			processText = ''
			resultClearFlg = True
		#根据按钮名称进行相应判定
		chkflg = True
		if(btnname.isdigit()):
			#数字按钮,  前面不能为),%
			if(len(processText) > 0 and  processText[-1] in (')','%') ):
				chkflg = False
		elif( btnname == '.' ):
			#小数点按钮,  前面不能为),%,.
			if(len(processText) > 0 and  processText[-1] in (')','%','.') ):
				chkflg = False
			#一个操作数里面不能出现两个(例如:2.33.5)
			if(chkflg and processText.rfind('.') > -1):
				operand = self.operandLast(processText)
				if('.' in operand):
					chkflg = False
		elif( btnname == '(' ):
			#左括号按钮, 前面只能为空,操作符,(
			if(len(processText)>0 and not (processText[-1] in operator or processText[-1] =='(')):
				chkflg = False
		elif( btnname == ')' ):
			#右括号按钮, 前面只能为数字或者%
			if(len(processText) == 0): #前面空白
				chkflg = False
			elif(not (processText[-1].isdigit() or processText[-1]=='%')):  #前面不为数字,%
				chkflg = False
			else:
				#判定前面是否有对应的(
				if(processText.count('(') <= processText.count(')')):
					chkflg = False
		elif( btnname == '%' ):
			#百分号按钮,前面必须为()包含的计算式或者数字
			if(len(processText) == 0): #前面空白
				chkflg = False
			elif(not(processText[-1].isdigit() or processText[-1]==')')):  #前面必须为()包含的计算式或者数字
				chkflg = False
		else:
			#'/''*''+''-'计算符号
			#前一次计算完毕,下一次从计算符号开始的话,把结果作为计算式的开头
			if(resultClearFlg):
				processText = resultText
			if(len(processText) == 0): #前面空白
				chkflg = False
			elif(processText[-1] in operator or processText[-1]=='('): #前面不能为(和计算符号
				chkflg = False

		#判定为True时候,计算式内容显示
		if (chkflg):
			if( btnname == '.'):
				#前一位不是数字的时候,自动补0
				if (len(processText) == 0 or (len(processText) > 1 and  not(processText[-1].isdigit()))):
					strTmp = processText + '0' +  btnname
				else:
					strTmp = processText + btnname
			else:
				strTmp = processText + btnname
			#长度超出之后左边的截断后显示
			self.processTextBack =  strTmp #长度不截断
			self.process['text'] =  strTmp if len(strTmp) < maxLen else strTmp[-maxLen:]
			if(resultClearFlg):
				self.result['text'] = ''

	#取得计算式的最后一个操作数
	def operandLast(self, text):
		#text长度为0
		if(len(text) == 0):
			return ''
		#最后一个计算符的位置
		position = max([text.rfind(item) for item in operator])
		#最后一个字符为计算符
		if(position == len(text) -1 ):
			return ''
		#没有找到计算符,整个作为一个操作数
		if(position == -1):
			return text
		else:
			return text[position+1:]

if __name__ == '__main__':
	#主窗口
	myWindow = tk.Tk()
	myWindow.title('计算器')     #标题
	myWindow.geometry('600x400') #初始尺寸
	myWindow.config(background ='#FFFFF0') #颜色

	#在主窗口创建一个计算器frame
	myCalcuatorApp = calcuatorApp(master=myWindow)
	myCalcuatorApp.master.minsize(600,400) #最小尺寸
	myCalcuatorApp.master.maxsize(900,600) #最大尺寸
	myCalcuatorApp.config(background ='#FFFFF0') #颜色

	#消息循环
	myWindow.mainloop()

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值