文章目录

  • 前言
  • 一、最终成果物
  • 二、代码详解
    • 1.基本框架
      • 1.1 主窗口整体布局
      • 1.2 显示板
      • 1.3 按钮
    • 2.内部逻辑
      • 2.1 数字处理
      • 2.2 计算处理
      • 2.3 等号处理
  • 总结

前言

python tkinter 系列,实现计算器基本加减乘除的运算

一、最终成果物

二、代码详解

1.基本框架

参考电脑自带的计算机,除去一些复杂的符号,只考虑简单的加减乘除,设计整体的框架如下:

1.1 主窗口整体布局

1)主窗口固定大小,
2)分为两部分,frm1和frm2,frm1放置显示框,frm2放置按钮码如下:

import tkinter as tk

'''显示板显示输出,代码见1.2部分'''
def printout(result1, result2,frm):
'''按钮显示输出,代码见1.3部分'''
def layout_button(frm):
'''整体布局'''
def layout(root, result1, result2):
    frm1 = tk.Frame(root)  #frm1显示板框体
    frm1.config(width=320, height=100, relief='solid', highlightthickness=2, highlightbackground='red')
    printout(result1, result2, frm1)
    frm1.grid(row=0, column=0)
    frm1.grid_propagate(0)  #固定大小不变

    frm2 = tk.Frame(root)  #frm2按键板框体
    frm2.config(width=320, height=400, bg='#dfe9f4', relief='solid', highlightthickness=2, highlightbackground='blue')
    layout_button(frm2)
    frm2.grid(row=1, column=0)
    frm2.grid_propagate(0)
root = tk.Tk()
root.title("计算器1.0")
root['bg'] = '#dfe9f4'
root.geometry("320x500")

result1 = tk.StringVar()
result1.set('')  #上面显示板,默认显示空
result2 = tk.StringVar()
result2.set(0)  #下面显示板,默认显示0

root.mainloop()

1.2 显示板

新建两个字符变量result1和result2,前者记录上层显示内容,后者记录下层显示内容

'''显示板显示输出'''
def printout(result1, result2,frm):
    label1 = tk.Label(frm, font=('微软雅黑', 20), bg='#EEE9E9', bd='9', fg='#828282', anchor='se', textvariable=result1)
    label1.place(relx=1, rely=0.5, relwidth=1, relheight=0.5, anchor='se')
    label2 = tk.Label(frm, font=('微软雅黑', 20), bg='#EEE9E9', bd='9', fg='#828282', anchor='se', textvariable=result2)
    label2.place(relx=1, rely=1, relwidth=1, relheight=0.5, anchor='se')	#注意放置位置为东南角

1.3 按钮

按键布局位置,参考基本框架部分,布局采用place函数,位置为相对frm2的相位位置(relx,rely)。
数据按键对应数字处理函数press_num(),加减乘除对应计算函数press_compute(),等号对应单独计算结果函数press_equal()。

def layout_button(frm):
btn7 = tk.Button(frm, text='7', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('7'))
btn7.place(relx=0.125, rely=0.125, relwidth=0.23,relheight=0.23,anchor='center')
btn8 = tk.Button(frm, text='8', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('8'))
btn8.place(relx=0.375, rely=0.125, relwidth=0.23,relheight=0.23,anchor='center')
btn9 = tk.Button(frm, text='9',  font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('9'))
btn9.place(relx=0.625, rely=0.125, relwidth=0.23,relheight=0.23,anchor='center')
btn4 = tk.Button(frm, text='4', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('4'))
btn4.place(relx=0.125, rely=0.375, relwidth=0.23,relheight=0.23,anchor='center')
btn5 = tk.Button(frm, text='5',  font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('5'))
btn5.place(relx=0.375, rely=0.375, relwidth=0.23,relheight=0.23,anchor='center')
btn6 = tk.Button(frm, text='6', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('6'))
btn6.place(relx=0.625, rely=0.375, relwidth=0.23,relheight=0.23,anchor='center')
btn1 = tk.Button(frm, text='1', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('1'))
btn1.place(relx=0.125, rely=0.625, relwidth=0.23,relheight=0.23,anchor='center')
btn2 = tk.Button(frm, text='2',  font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('2'))
btn2.place(relx=0.375, rely=0.625, relwidth=0.23,relheight=0.23,anchor='center')
btn3 = tk.Button(frm, text='3', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('3'))
btn3.place(relx=0.625, rely=0.625, relwidth=0.23,relheight=0.23,anchor='center')
btn10 = tk.Button(frm, text='0', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('0'))
btn10.place(relx=0.125, rely=0.875, relwidth=0.23, relheight=0.23, anchor='center')
btn11= tk.Button(frm, text='.', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_num('.'))
btn11.place(relx=0.375, rely=0.875, relwidth=0.23,relheight=0.23,anchor='center')
btn12= tk.Button(frm, text='=', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_equal())
btn12.place(relx=0.625, rely=0.875, relwidth=0.23,relheight=0.23,anchor='center')
btn13= tk.Button(frm, text='+', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_compute('+'))
btn13.place(relx=0.875, rely=0.125, relwidth=0.23,relheight=0.23,anchor='center')
btn13 = tk.Button(frm, text='-', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_compute('-'))
btn13.place(relx=0.875, rely=0.375, relwidth=0.23, relheight=0.23, anchor='center')
btn13 = tk.Button(frm, text='X', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_compute('*'))
btn13.place(relx=0.875, rely=0.625, relwidth=0.23, relheight=0.23, anchor='center')
btn13 = tk.Button(frm, text='÷', font=('微软雅黑', 20), bg='#f1f5fa', command=lambda:press_compute('/'))
btn13.place(relx=0.875, rely=0.875, relwidth=0.23, relheight=0.23, anchor='center')

2.内部逻辑

  1. 变量:
  • 标记位:标记上个按键是什么,
    isintbtn:标记按钮按的数字,默认未按
    isstrbtn :标记按钮按的符号,默认未按
    is_equal_last:标记上个按键是不是等号
  • 保存数据:
    list[]:保存整个计算过程中的按键;
    result1:记录显示板上面内容
    result2:记录显示板下面内容
  1. 按键逻辑
  • 1)按了数字后,如果前一个按键还是数字,组合在一起形成新的数字,并显示在下面显示板;
  • 2)按了符号,下面显示板不显示,保持原数字,但记录result2清空以便记录下个数字;且将之前的过程显示在上面显示板;
  • 3)按了等号后,将结果显示在下面显示板,过程显示在上面显示板;
  1. 特殊情况:
  • 连续按了多次“=”,将前一次等号计算的结果,与最后一次符号和数字重新计算,如5+6,按“=”计算为11,再次按“=”后,计算变为11+6,结果为17。
  • “=”计算出结果,直接按了符号,将结果作为初始的数值计算。

2.1 数字处理

逻辑:如果上次按的按钮是符号或等号,则将result2记为0,重新记数字;如果按的是数字,则在原来的基础上再把新按数字记上;

def press_num(num):
global isintbtn #标记按钮按的数字,默认未按
global isstrbtn #标记按钮按的符号,默认未按
global is_equal_last #标记上一个按键
global last_num #记录上一个数字
global list
if isstrbtn == False:
pass
else:
result2.set(0)
isstrbtn=False #若上次按键为符号,数字重新清零开始计数
if is_equal_last == True:
result2.set(0) #等号同理
oldnum = result2.get()
if oldnum == '0':
result2.set(num)
last_num = num
else:
newnum = oldnum+num
result2.set(newnum)
last_num = newnum	#连续按数字,将数字连起来作为新的数字
is_equal_last = False #标记下上个按键已不是等号

2.2 计算处理

按了符号后,需将之前输入的数字和符号显示到上部分显示板上,同时把之前的数字和符号记录到list表中。

def press_compute(sign):
global isintbtn
global isstrbtn
global is_equal_last
global last_cpt
global list
num = result2.get()
list.append(num)	#把数字记录到列表中
list.append(sign)
isstrbtn = True #把符号记录到列表中
is_equal_last = False
last_cpt = sign
cur_out = ''.join(list)
result1.set(cur_out) #上部分显示板显示之前输入的数字

2.3 等号处理

等号注意,如果正常数字结束的,根据list内容计算出结果,如果是连续按的等号,将list内容更新下,更换为结果+最后一个符号+最后一个数字,再计算结果。

def press_equal():
global isintbtn
global isstrbtn
global is_equal_last
global last_num
global list
if is_equal_last == False:
curnum = result2.get()
list.append(curnum)
computeStr = ''.join(list)
endnum = eval(computeStr)	#使用eval函数将list内容计算出结果
result2.set(endnum)
result1.set(computeStr)	#将计算结果和内容显示在显示板上
is_equal_last = True	#标记此时最后一个按键是等号
list.clear()	#清空list
else:
curnum = result2.get() 	#如果上次按键是等号,记录上次的计算结果
list.append(curnum)
list.append(last_cpt)
list.append(str(last_num))	#将计算结果、最后一次的符号、最后一个数字添加到list中
#print(list)
computeStr = ''.join(list)
endnum = eval(computeStr)
#print(computeStr)
result2.set(endnum)
result1.set(computeStr)
is_equal_last = True
list.clear() 	#按照新的list计算结果并显示

3、整体代码和最终结果
见下一篇:https://blog.csdn.net/u010234441/article/details/111995477

总结

  1. 在设计过程中,会增加一些标记,如上个按键的情况,上个数字、符号,这些都是为了方便整合数字或处理特殊情况。在设计初期,就应该考虑除了正常的按键外,一些非正常的按键程序该如何响应(如连续按等号,等号后直接符号等)。
  2. 初始计算器已完成,对照电脑自带的计算器,还可增加更多符号(%、删除一位,清空按键等),来丰富计算器内容,敬请期待

本文地址:https://blog.csdn.net/u010234441/article/details/111992253