利用Tkinter和eval函式實現複雜計算器
阿新 • • 發佈:2018-12-27
利用Tkinter和eval函式實現複雜計算器
一、架構與思路
A.使用eval函式後,計算器程式較原先版本,程式碼量大幅減少,同時可以支援多個運算元的運算
B.對AC與DEL功能進行修改,通過新增判斷指示,優化原始程式碼,減少出錯率
(1)tkinter建立主介面:
- 設定主要的視窗,定義大小,顯示介面等;
(2)使用Button建立按鈕:
- 數字按鈕:定義0-9數字按鈕,繫結相應邏輯函式;
- 功能按鈕:定義小數點、百分號、AC、del、四則運算等功能按鈕,繫結相應函式;
(3)建立函式
- 數字按鈕函式
- 功能按鈕函式
- 等於按鈕函式:實現最終的表示式轉換與計算,顯示計算結果
介面展示:
程式架構和思路如下:
二、程式碼實現
根據上述思路,利用python實現複雜計算器功能,程式碼如下:
import tkinter
# 建立tkinter主視窗
root = tkinter.Tk()
root.minsize(320,600)
root.title('Calculator')
# 分屏顯示結果,up顯示計算式子,down顯示數字與最終結果
result_down = tkinter.StringVar()
result_down.set('0')
result_up = tkinter.StringVar()
result_up.set('')
# 顯示結果繫結標籤並定位
# bd = borderwidth 線框寬度
label_down = tkinter.Label(root, font=('微軟雅黑',40), bg='#EEE9E9', bd='6', anchor='se', textvariable=result_down)
label_down.place(x=0, y=200, width=320, height=80)
label_up = tkinter.Label(root, font=('微軟雅黑',30), bg='#EEE9E9', bd= '6', anchor='se', textvariable=result_up)
label_up.place(x=0, y=0, width=320, height=200)
# 建立數字按鈕並繫結函式
b7 = tkinter.Button(root, text='7', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('7'))
b7.place(x=0 , y=345, width=80, height=65)
b8 = tkinter.Button(root, text='8', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('8'))
b8.place(x=80, y=345, width=80, height=65)
b9 = tkinter.Button(root, text='9', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('9'))
b9.place(x=160, y=345, width=80, height=65)
b4 = tkinter.Button(root, text='4', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('4'))
b4.place(x=0 , y=410, width=80, height=65)
b5 = tkinter.Button(root, text='5', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('5'))
b5.place(x=80, y=410, width=80, height=65)
b6 = tkinter.Button(root, text='6', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('6'))
b6.place(x=160, y=410, width=80, height=65)
b1 = tkinter.Button(root, text='1', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('1'))
b1.place(x=0 , y=475, width=80, height=65)
b2 = tkinter.Button(root, text='2', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('2'))
b2.place(x=80, y=475, width=80, height=65)
b3 = tkinter.Button(root, text='3', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('3'))
b3.place(x=160, y=475, width=80, height=65)
b0 = tkinter.Button(root, text='0', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda : pressNum('0'))
b0.place(x=80, y=540, width=80, height=65)
# 建立功能按鈕並繫結函式
bAC = tkinter.Button(root, text='AC', font=('微軟雅黑',30), fg='orange', bg='#EEE9E9', bd='1', command=lambda :pressCompute('AC'))
bAC.place(x=0, y=280, width=80, height=65)
bdel = tkinter.Button(root, text='←', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda :pressCompute('del'))
bdel.place(x=80, y=280, width=80, height=65)
bdiv = tkinter.Button(root, text='÷', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda :pressCompute('/'))
bdiv.place(x=160, y=280, width=80, height=65)
btimes = tkinter.Button(root, text='×', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda :pressCompute('*'))
btimes.place(x=240, y=280, width=80, height=65)
bminus = tkinter.Button(root, text='-', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda :pressCompute('-'))
bminus.place(x=240, y=345, width=80, height=65)
bplus = tkinter.Button(root, text='+', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda :pressCompute('+'))
bplus.place(x=240, y=410, width=80, height=65)
bpoint = tkinter.Button(root, text='.', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda :pressCompute('.'))
bpoint.place(x=160, y=540, width=80, height=65)
bpercen = tkinter.Button(root, text='%', font=('微軟雅黑',30), bg='#EEE9E9', bd='1', command=lambda :pressCompute('%'))
bpercen.place(x=0, y=540, width=80, height=65)
bequ = tkinter.Button(root, text='=', font=('微軟雅黑',30), bg='orange', bd='1', command=lambda :pressEqual())
bequ.place(x=240, y=475, width=80, height=130)
# 初始化
# lists用於存放最終計算的式子,含數字與四則運算子(計算過程中並不會顯示)
# isPressFunc用於指示是否按下運算子
lists=[]
isPressFunc = False
isPressDel = False
# 數字按鈕繫結函式,只用於數字標籤的顯示
def pressNum(num):
global lists,isPressFunc
# 如果還未按下運算按鈕,則pass
if isPressFunc == False:
pass
# 如果已經按下,則將之前的結果清零,指示值重設為False
else:
result_down.set('0')
isPressFunc = False
# 將原有數字存為oldnum,如果為0,則新按數字為顯示結果,若不為0,則老“拼接”新為顯示結果
oldnum = result_down.get()
if oldnum == '0':
result_down.set(num)
else:
newnum = oldnum + num
result_down.set(newnum)
# 功能按鈕繫結函式,用於式子的元件與隱形的邏輯
def pressCompute(func):
global lists,isPressFunc,isPressDel
num = result_down.get()
# 如果為刪除,則顯示的數字刪除一位,重新顯示,然後將結果新增的lists中
# 同時,將刪除指示調整為True,以保證刪除後螢幕顯示的數值不在其他函式被重新新增到list中
# 直到遇到其他四則運算子,將指示重置為False,否則equal函式就不能獲取後續的顯示值
if func == 'del':
a = num[0:-1]
result_down.set(a)
num = result_down.get()
#lists.remove(lists.size()-1)
#del lists[-1]
lists.append(num)
isPressDel = True
elif func == 'AC':
lists.clear()
result_down.set('0')
result_up.set('')
isPressDel = False
isPressFunc = False
else:
if isPressDel != True:
lists.append(num)
lists.append(func)
isPressFunc = True
isPressDel = False # 一旦出現四則運算,則之前刪除指示重置為False
# 等號按鈕的繫結函式,使用eval函式進行計算,並將兩個結果分別投到螢幕上
def pressEqual():
global lists,isPressFunc,isPressDel
# 獲取最後一次輸入的數值
num_nd = result_down.get()
# 如果該數值之前被del功能刪除過後(指示值為True),會自動新增進列表,則此時不需要再新增
# 如果是其他功能的話,則需要將該數值新增進列表
if isPressDel != True:
lists.append(num_nd)
# 使用join函式將單獨分離的lists列表合成字串,其中‘’空字串代表用來合成時使用的間隔為空
equation = ''.join(lists)
# 使用eval函式返回傳入字串的表示式的結果。eval()實現list、dict、tuple與str之間的轉化
resultNum = eval(equation)
# 將計算結果投至下顯示屏,計算表示式投至上顯示屏
result_down.set(resultNum)
result_up.set(equation)
# 情況列表
lists.clear()
root.mainloop()