GUI 計算機
延續上一個 tkinter 專題,這次做一台計算機:一格一格的數字和運算符號按鈕,按了顯示在螢幕上,按「=」算出結果,另外還有清除和退格。這個專題會用到 tkinter 的格線排版、巢狀迴圈搭配 enumerate(),以及上一頁的 functools.partial。
把它存成 gui_calc.py 執行:
import functoolsimport tkinter as tk
def button_clicked(button_text): if button_text == "C": entry.delete(0, tk.END) return
current_text = entry.get()
if button_text == "<-": entry.delete(len(current_text) - 1, tk.END) return
if button_text == "=": entry.delete(0, tk.END)
try: result = eval(current_text) except Exception: entry.insert(tk.END, "計算錯誤") else: entry.insert(tk.END, result)
return
entry.insert(tk.END, button_text)
font = ("Arial", 16)
window = tk.Tk()window.title("GUI 計算機")
entry = tk.Entry(window, width=20, font=font)entry.grid(row=0, column=0, columnspan=4)
button_grid = [ ["7", "8", "9", "/"], ["4", "5", "6", "*"], ["1", "2", "3", "-"], ["0", ".", "=", "+"], ["C", "<-"],]
for row, button_row in enumerate(button_grid, 1): for col, button_text in enumerate(button_row): button = tk.Button( window, text=button_text, width=5, height=2, font=font, command=functools.partial(button_clicked, button_text), ) button.grid(row=row, column=col)
window.mainloop()版面:grid 和 button_grid
Section titled “版面:grid 和 button_grid”這次用 grid(row=, column=) 而不是 pack。它把視窗切成一格一格,你指定每個元件放在第幾列、第幾欄,很適合排計算機這種格子狀的版面。
entry.grid(row=0, column=0, columnspan=4):螢幕放在第 0 列,columnspan=4讓它橫跨四欄。button_grid是一個二維串列,直接照計算機的樣子把每一列的按鈕文字排好。最後一列只有兩顆,grid不會介意。- 外層
for row, button_row in enumerate(button_grid, 1)走過每一列,enumerate從 1 開始數,因為第 0 列給螢幕用了。內層for col, button_text in enumerate(button_row)走過這一列的每顆按鈕,欄從 0 開始。 - 每顆按鈕都用
functools.partial(button_clicked, button_text)綁上自己的文字,道理和上一頁一樣:command要的是不帶引數的函式,partial幫我們把button_text先塞進去。
font = ("Arial", 16) 把字型設定放在一個變數,螢幕和每顆按鈕共用,要改字型或大小只要改一個地方。
按鈕被按下:button_clicked
Section titled “按鈕被按下:button_clicked”所有按鈕都呼叫同一個函式 button_clicked,靠 button_text 分辨是哪一顆。函式用一連串的提早 return 先處理三顆特殊按鈕,最後才是一般的數字和符號:
C(清除):entry.delete(0, tk.END)把螢幕從第 0 個字元刪到最後,也就是全部清空,然後return。<-(退格):先用entry.get()拿到目前的字串,entry.delete(len(current_text) - 1, tk.END)從最後一個字元的位置刪到結尾,剛好刪掉一個字,然後return。=(計算):先把螢幕清空,再用eval(current_text)把螢幕上的算式字串(例如"3+4*2")當成 Python 運算式算出答案。這裡用了錯誤處理那章的try/except/else:算式打錯(例如3++)會出錯,except接住後在螢幕顯示「計算錯誤」;沒出錯才走else,把結果填回螢幕。兩條路最後都return。- 其他按鈕:數字和運算符號都一樣,
entry.insert(tk.END, button_text)把它接在螢幕文字的最後面。
注意 current_text = entry.get() 放在第一個 return 之後、<- 和 = 的判斷之前:C 用不到目前的文字,所以不必先拿;後面兩顆都要用,就在它們前面拿一次。
關於 eval
Section titled “關於 eval”eval 很方便,但也要小心。它會執行字串裡的任何 Python 程式,只適合像這樣自己掌控輸入的小練習,別拿它去算來路不明的字串。這台計算機的輸入只能來自按鈕,所以是安全的。
v0.9.1 (c924b5b)