[PySimpleGUI界面學習](八)回調函數的模擬以及進度條的演示
- 2020 年 3 月 12 日
- 筆記
<!–more–> # 回顧 在前面幾次教程中我們整體認知了 `PySimpleGUI` 這個工具包的基本使用方法,也見識了其中的一些控件使用。這個工具包主要是簡化界面的編寫,將界面對於用戶輸入的採集自動化完成。 # 回調函數模擬 在傳統的界面編程中,程序員需要對控件的每一個響應編寫一個回調函數,這個意思是指當用戶點擊某個按鈕或是某個控件的狀態改變時,程序需要做出的反應。 事實上,在 `PySimpleGUI` 這個工具包中,並不需要對專門的按鈕去做一個回調函數編寫,但是如果想實現也是一件容易的事情,下面的代碼對這個進行一個簡單的展示。 “`python import PySimpleGUI as sg def button1(): print("按鈕1被點擊") def button2(): print("按鈕2被點擊") layout = [[sg.Text("請點擊一個按鈕")], [sg.Button("1"), sg.Button("2"), sg.Button("退出")]] window = sg.Window("回調函數模擬").Layout(layout) while True: event, values = window.Read() if event == "1": button1() elif event == "2": button2() elif event is None or event=="退出": window.Close() break sg.PopupOK("完成!") “` 執行程序的界面如圖所示: <a href="https://s2.ax1x.com/2020/02/06/1yyPFf.png" class="highslide" onclick="return hs.expand(this,{slideshowGroup:'images'})"><img src="https://s2.ax1x.com/2020/02/06/1yyPFf.png" alt="1yyPFf.png" border="0" /></a> 當用戶分別點擊兩個按鈕時,控制台上將打印出各自按鈕回調函數中所預先定義的語句。如圖所示: <a href="https://s2.ax1x.com/2020/02/06/1yyMkV.png" class="highslide" onclick="return hs.expand(this,{slideshowGroup:'images'})"><img src="https://s2.ax1x.com/2020/02/06/1yyMkV.png" alt="1yyMkV.png" border="0" /></a> # 分析 由於 `PySimpleGUI` 這個工具包本身已經將界面的偵測自動化處理,所以上述的回調函數本身並沒有真正揭示出回調函數對於普通界面編程的意義,但是從這個仿真模擬可以看出,這種比較類似於普通的回調,儘管以現在看方式來看,創建兩個函數去打印兩個語句有多餘的感覺,但是如果從函數模塊化編程的角度來考慮,將特別的功能獨立出來,這種方式卻也有其可取之處。 # 實戰 現在我們還做一個簡單的小例子,再一次來體會一下PySimpleGUI工具包封裝的強大。 在這個小例子中,我們來試驗一種特別的控件————進度條,即用一個簡單的循環就可以將一個進度條創建出來,這種方式是不是特別酷? 代碼如下: “`python import PySimpleGUI as sg for i in range(10000): sg.OneLineProgressMeter('一行進度條的例子', i+1, 10000, 'key') “` 這個神奇的例子將顯示如下截圖: <a href="https://s2.ax1x.com/2020/02/06/1yycnA.png" class="highslide" onclick="return hs.expand(this,{slideshowGroup:'images'})"><img src="https://s2.ax1x.com/2020/02/06/1yycnA.png" alt="1yycnA.png" border="0" /></a> 當然,我們很多時候希望自己能夠來將進度條添加在我們的界面上,那就要用到該庫中的 `ProgressBar` 這個控件,代碼如下: “`python import PySimpleGUI as sg layout = [[sg.Text('一個自定義的進度條例子')], [sg.ProgressBar(10000, orientation='h', size=(20, 20), key='progressbar')], [sg.Button("退出")]] window = sg.Window('自定義進度條').Layout(layout) progress_bar = window.FindElement('progressbar') for i in range(10000): event, values = window.Read(timeout=0) if event == '退出' or event is None: break progress_bar.UpdateBar(i + 1) window.Close() “` 這段代碼演示了自定義進度條是如何工作的,其運行如下圖所示: <a href="https://s2.ax1x.com/2020/02/06/1yybBn.png" class="highslide" onclick="return hs.expand(this,{slideshowGroup:'images'})"><img src="https://s2.ax1x.com/2020/02/06/1yybBn.png" alt="1yybBn.png" border="0" /></a> 從運行來看,當用戶點擊退出按鈕時,即使進度條沒有完成,也會退出。不過從下面一個例子再來看的話,你會發現一個奇怪的事情,代碼如下: “`python import PySimpleGUI as sg layout = [[sg.Text('一個自定義的進度條例子')], [sg.ProgressBar(10000, orientation='h', size=(20, 20), key='progressbar')], [sg.Button("執行"), sg.Button("退出")]] window = sg.Window('自定義進度條').Layout(layout) progress_bar = window.FindElement('progressbar') while True: event, values = window.Read(timeout=10) if event == '退出' or event is None: break elif event == "執行": for i in range(10000): progress_bar.UpdateBar(i+1) window.Close() “` 以上代碼的運行界面如圖: <a href="https://s2.ax1x.com/2020/02/06/1yc0Qe.png" class="highslide" onclick="return hs.expand(this,{slideshowGroup:'images'})"><img src="https://s2.ax1x.com/2020/02/06/1yc0Qe.png" alt="1yc0Qe.png" border="0" /></a> 從運行中可知,當用戶在進度條滾動時無論如何點擊退出按鈕,窗口也無法關閉。這是什麼原因呢?原來這牽扯到另一個問題了,即同一個進程中,當界面在執行某一段代碼時,是不會理會其他行為的,那麼若想同時執行兩個行為怎麼辦呢,這就是以後要講到的線程問題了。