我們在上一次課程中(python窗口編程-2:風格與布局 ),制作了完整的計算器窗口界面,只是那個窗口沒有真正的功能,是點擊任何按鈕都會關閉。這一次,我們加入一些事件處理的功能,讓它成為一個正常工作的窗口程序,并具備與普通的計算器一樣的輸入數字的操作能力。

事件處理的無限循環
為了避免點擊按鈕會關閉窗口,我們引入無限循環的事件處理:
while True: event, values = window.read() if event==sg.WIN_CLOSED: breakwindow.close()
使用這個代碼,替換上次課程最后的兩行代碼。我們會看到,現在只有點擊窗口右上角的“X”才能關閉窗口,點擊其它的按鈕雖然沒有反應,但不會導致窗口的關閉了。
sg.WIN_CLOSED代表關閉窗口的按鈕值,實際是None,但這樣表達增強了代碼的健壯性。如果有一天PySimpleGUI的新升級版決定修改關閉窗口的按鈕值,我們的代碼無須做任何修改(理應如此)。
凡是有無限循環的地方,都必須有退出循環的機制,否則程序無法終止。那將是一個很不友善的用戶體驗。這里的break語句,作用就是退出循環。
break不但用于while循環,也可以用于for循環。當遍歷搜索一個數據時,找到數據并且無須繼續搜索時,就可以用break退出循環。
數字鍵的處理
當按鈕為數字的時候,我們這樣表示
event in [str(i) for i in range(0,10)]:
這里又用到了列表生成式,我們在編程基礎的課程中講過(python語言基礎-10:編程是一種藝術 ),含義是當事件為‘0’到‘9’幾個數字的時候。
需求分析
很多軟件產品的開發,并沒有細致的需求描述,而是提供了一個參考原型。即:這個功能參考XXX進行開發。比如我們的計算器,按下按鈕的反應究竟應該是怎樣,來自對真實計算器的模擬。我們第一步的需求,只實現正常的數字輸入功能。

計算器的操作,對很多朋友來說是很熟悉也很自然的。最好的操作界面設計,就應該是自然的,讓用戶無須培訓,就能自然使用。我們用語言來描述一下。
- 計算器的輸出框,永遠不會是空白,它的默認狀態就是一個0后面跟一個小數點。
- 輸入數字,就開始增加整數的位數,但首位不會是0。
- 輸入小數點,顯示不會立刻改變,但后面再輸入數字,就變成了小數的位,末尾可以是0。
本節課程,只實現前兩個功能(的一部分)。
整數數位邏輯
為了實現功能2,讓我們看一下基本的整數位邏輯。新輸入的數字會改變原有數字的含義。新的數字占據個位,原來的個位變成十位,原來十位變成百位,依此類推。這個操作,在編程中,用一個簡單的模式來表現:
Value= Value* 10+ NewDigit
程序語言,真的是一種語言,一句代碼,就能把這個操作邏輯描述得清清楚楚。能夠看懂并理解程序語言,這就是掌握編程的開始。
內部值與顯示值的分離
我們注意到,計算器的顯示,是數字后面跟著一個小數點。正常的數字轉字符串不是這樣的效果,我們必須人為地在后面添加一個小數點。
ShowStr= str(Value)+'.'
在這種操作邏輯下,將內部計算用的值與顯示的效果分開是好的。它的好處體現在控制了復雜性的規模。編程活動不創造有形的物質,它的價值就在于控制復雜性。
更加明確的說,好的編程者的能力就體現在開發代碼的全過程中始終把復雜性規模維持在自己能夠控制的范圍之內,并以此實現整體看起來相當復雜的功能邏輯。
(這里對比一下,交易的價值就在于控制風險。優秀的交易者,能夠把交易風險限制在自己能夠控制的范圍之內,并以此為基礎承擔一般人整體看起來相當大的風險,從而獲得風險利益。)
控制復雜性規模的一個方法,就是將可以分開的功能盡量分開。我們可以集中注意力思考如何通過按鈕事件對內部值的改變時,可以不考慮顯示的問題。而在處理顯示的時候,只需集中注意力考慮它的靜態狀態,不用考慮它的變化。
(這與打仗的原理是一樣的,在局部集中優勢兵力對敵。)
最后貼一下局部實現的代碼
value= 0while True: event, values = window.read() if event==sg.WIN_CLOSED: break if event == 'C': value= 0 elif event == '±': value= -value elif event in [str(i) for i in range(0,10)]: value= value* 10+ int(event) info= str(value)+'.' info=info[-12:] window['show'].update(info)window.close()
這里還有幾個小的處理邏輯
- C按鈕的處理,直接將內部值設置為0
- ±按鈕的處理,內部值正負切換
- 為了美觀起見,數字的顯示只保留最后的12位
- 改變文本框的顯示,用update函數,它提供了窗口界面的輸出功能。
- 文本框的定位,用了它的名字(key),這里的key與前面課程中講的key,功能含義完全不同,別弄混了。同名不同含義的問題,在自然語言和編程語言中都大量存在,這經常是引起各種混淆和爭論的起因。我們從一開始就應當給予足夠的重視。
課程小結
本節課程,介紹了如何開發一個真正的窗口應用,在窗口中響應輸入,顯示輸出,完全脫離控制臺的黑窗口。并講了數位處理的基本邏輯,這在數學編程中是很常用的。
簡單介紹了通過功能分離來控制編程復雜性的方法,控制復雜性將是貫穿編程的學習和實踐的全過程,后面還會經常講到。
朋友們可以自行嘗試一下如何實現小數,下一次課程中再解說。