歡迎光臨
每天分享高質量文章

使用 PySimpleGUI 輕鬆為程式和指令碼增加 GUI | Linux 中國

五分鐘建立定製 GUI。
— Mike Barnett


致謝
編譯自 | 
https://opensource.com/article/18/8/pysimplegui
 
 作者 | Mike Barnett
 譯者 | Andy Song (pinewall) ????共計翻譯:36.0 篇 貢獻時間:170 天

五分鐘建立定製 GUI。

對於 .exe 型別的程式檔案,我們可以透過雙擊滑鼠左鍵開啟;但對於 .py 型別的 Python 程式,幾乎不會有人嘗試同樣的操作。對於一個(非程式員型別的)典型使用者,他們雙擊開啟 .exe 檔案時預期彈出一個可以互動的窗體。基於 Tkinter,可以透過標準 Python 安裝standard Python installations的方式提供 GUI,但很多程式都不太可能這樣做。

如果開啟 Python 程式併進入 GUI 介面變得如此容易,以至於真正的初學者也可以掌握,會怎樣呢?會有人感興趣並使用嗎?這個問題不好回答,因為直到今天建立自定義 GUI 佈局仍不是件容易的事情。

在為程式或指令碼增加 GUI 這件事上,似乎存在能力的“錯配”。(缺乏這方面能力的)真正的初學者被迫只能使用命令列方式,而很多(具備這方面能力的)高階程式員卻不願意花時間建立一個 Tkinter GUI。

GUI 框架

Python 的 GUI 框架並不少,其中 Tkinter,wxPython,Qt 和 Kivy 是幾種比較主流的框架。此外,還有不少在上述框架基礎上封裝的簡化框架,例如 EasyGUI,PyGUI 和 Pyforms 等。

但問題在於,對於初學者(這裡是指程式設計經驗不超過 6 個月的使用者)而言,即使是最簡單的主流框架,他們也無從下手;他們也可以選擇封裝過的(簡化)框架,但仍難以甚至無法建立自定義 GUI 佈局layout。即便學會了某種(簡化)框架,也需要編寫連篇累牘的程式碼。

PySimpleGUI[1] 嘗試解決上述 GUI 難題,它提供了一種簡單明瞭、易於理解、方便自定義的 GUI 介面。如果使用 PySimpleGUI,很多複雜的 GUI 也僅需不到 20 行程式碼。

秘訣

PySimpleGUI 極為適合初學者的秘訣在於,它已經包含了絕大多數原本需要使用者編寫的程式碼。PySimpleGUI 會處理按鈕回呼callback,無需使用者編寫程式碼。對於初學者,在幾周內掌握函式的概念已經不容易了,要求其理解回呼函式似乎有些強人所難。

在大部分 GUI 框架中,佈局 GUI 小部件widgets通常需要寫一些程式碼,每個小部件至少 1-2 行。PySimpleGUI 使用了 “auto-packer” 技術,可以自動建立佈局。因而,佈局 GUI 視窗不再需要 pack 或 grid 系統。

(LCTT 譯註:這裡提到的 pack 和 grid 都是 Tkinter 的佈局管理器,另外一種叫做 place 。)

最後,PySimpleGUI 框架編寫中有效地利用了 Python 語言特性,降低使用者程式碼量並簡化 GUI 資料傳回的方式。在窗體form佈局中建立小部件時,小部件會被部署到對應的佈局中,無需額外的程式碼。

GUI 是什麼?

絕大多數 GUI 只完成一件事情:收集使用者資料並傳回。在程式員看來,可以歸納為如下的函式呼叫:

  1. button, values = GUI_Display(gui_layout)

絕大多數 GUI 支援的使用者行為包括滑鼠點選(例如,“確認”,“取消”,“儲存”,“是”和“否”等)和內容輸入。GUI 本質上可以歸結為一行程式碼。

這也正是 PySimpleGUI (的簡單 GUI 樣式)的工作原理。當執行命令顯示 GUI 後,除非點選滑鼠關閉窗體,否則不會執行任何程式碼。

當然還有更複雜的 GUI,其中滑鼠點選後視窗並不關閉;例如,機器人的遠端控制介面,聊天視窗等。這類複雜的窗體也可以用 PySimpleGUI 建立。

快速建立 GUI

PySimpleGUI 什麼時候有用呢?顯然,是你需要 GUI 的時候。僅需不超過 5 分鐘,就可以讓你建立並嘗試 GUI。最便捷的 GUI 建立方式就是從 PySimpleGUI 經典實體[2]中複製一份程式碼。具體操作流程如下:

◈ 找到一個與你需求最接近的 GUI
◈ 從經典實體中複製程式碼
◈ 貼上到 IDE 中並執行

下麵我們看一下書中的第一個經典實體recipe

  1. import PySimpleGUI as sg

  2. # Very basic form.  Return values as a list

  3. form = sg.FlexForm('Simple data entry form')  # begin with a blank form

  4. layout = [

  5.           [sg.Text('Please enter your Name, Address, Phone')],

  6.           [sg.Text('Name', size=(15, 1)), sg.InputText('name')],

  7.           [sg.Text('Address', size=(15, 1)), sg.InputText('address')],

  8.           [sg.Text('Phone', size=(15, 1)), sg.InputText('phone')],

  9.           [sg.Submit(), sg.Cancel()]

  10.          ]

  11. button, values = form.LayoutAndRead(layout)

  12. print(button, values[0], values[1], values[2])

執行後會開啟一個大小適中的窗體。

如果你只是想收集一些字串型別的值,複製上述經典實體中的程式碼,稍作修改即可滿足你的需求。

你甚至可以只用 5 行程式碼建立一個自定義 GUI 佈局。

  1. import PySimpleGUI as sg

  2. form = sg.FlexForm('My first GUI')

  3. layout = [ [sg.Text('Enter your name'), sg.InputText()],

  4.            [sg.OK()] ]

  5. button, (name,) = form.LayoutAndRead(layout)

5 分鐘內建立一個自定義 GUI

在簡單佈局的基礎上,透過修改經典實體中的程式碼,5 分鐘內即可使用 PySimpleGUI 建立自定義佈局。

在 PySimpleGUI 中,小部件widgets被稱為元素elements。元素的名稱與編碼中使用的名稱保持一致。

(LCTT 譯註:Tkinter 中使用小部件這個詞)

核心元素

  1. Text

  2. InputText

  3. Multiline

  4. InputCombo

  5. Listbox

  6. Radio

  7. Checkbox

  8. Spin

  9. Output

  10. SimpleButton

  11. RealtimeButton

  12. ReadFormButton

  13. ProgressBar

  14. Image

  15. Slider

  16. Column

元素簡寫

PySimpleGUI 還包含兩種元素簡寫方式。一種是元素型別名稱簡寫,例如 T 用作 Text 的簡寫;另一種是元素引數被配置了預設值,你可以無需指定所有引數,例如 Submit 按鈕預設的文字就是 “Submit”。

  1. T = Text

  2. Txt = Text

  3. In = InputText

  4. Input = IntputText

  5. Combo = InputCombo

  6. DropDown = InputCombo

  7. Drop = InputCombo

(LCTT 譯註:第一種簡寫就是 Python 類的別名,第二種簡寫是在傳回元素物件的 Python 函式定義時指定了引數的預設值)

按鈕簡寫

一些通用按鈕具有簡寫實現,包括:

  1. FolderBrowse

  2. FileBrowse

  3. FileSaveAs

  4. Save

  5. Submit

  6. OK

  7. Ok LCTT 譯註:這裡 `k` 是小寫)

  8. Cancel

  9. Quit

  10. Exit

  11. Yes

  12. No

此外,還有通用按鈕功能對應的簡寫:

  1. SimpleButton

  2. ReadFormButton

  3. RealtimeButton

(LCTT 譯註:其實就是傳回 Button 類實體的函式)

上面就是 PySimpleGUI 支援的全部元素。如果不在上述串列之中,就不會在你的視窗佈局中生效。

(LCTT 譯註:上述都是 PySimpleGUI 的類名、類別名或傳回實體的函式,自然只能使用串列內的。)

GUI 設計樣式

對於 GUI 程式,建立並展示視窗的呼叫大同小異,差異在於元素的佈局。

設計樣式程式碼與上面的例子基本一致,只是移除了佈局:

  1. import PySimpleGUI as sg

  2. form = sg.FlexForm('Simple data entry form')

  3. # Define your form here (it's a list of lists)

  4. button, values = form.LayoutAndRead(layout)

(LCTT 譯註:這段程式碼無法執行,只是為了說明每個程式都會用到的設計樣式。)

對於絕大多數 GUI,編碼流程如下:

◈ 建立窗體物件
◈ 以“串列的串列”的形式定義 GUI
◈ 展示 GUI 並獲取元素的值

上述流程與 PySimpleGUI 設計樣式部分的程式碼一一對應。

GUI 佈局

要建立自定義 GUI,首先要將窗體分割成多個行,因為窗體是一行一行定義的。然後,在每一行中從左到右依次放置元素。

我們得到的就是一個“串列的串列”,類似如下:

  1. layout = [  [Text('Row 1')],

  2.             [Text('Row 2'), Checkbox('Checkbox 1', OK()), Checkbox('Checkbox 2'), OK()] ]

上述佈局對應的效果如下:

展示 GUI

當你完成佈局、複製完用於建立和展示窗體的程式碼後,下一步就是展示窗體並收集使用者資料。

下麵這行程式碼用於展示窗體並傳回收集的資料:

  1. button, values = form.LayoutAndRead(layout)

窗體傳回的結果由兩部分組成:一部分是被點選按鈕的名稱,另一部分是一個串列,包含所有使用者輸入窗體的值。

在這個例子中,窗體顯示後使用者直接點選 “OK” 按鈕,傳回的結果如下:

  1. button == 'OK'

  2. values == [False, False]

Checkbox 型別元素傳回 True 或 False 型別的值。由於預設處於未選中狀態,兩個元素的值都是 False

顯示元素的值

一旦從 GUI 獲取傳回值,檢查傳回變數中的值是個不錯的想法。與其使用 print 陳述句進行列印,我們不妨堅持使用 GUI 併在一個視窗中輸出這些值。

(LCTT 譯註:考慮使用的是 Python 3 版本,print 應該是函式而不是陳述句。)

在 PySimpleGUI 中,有多種訊息框可供選取。傳遞給訊息框(函式)的資料會被顯示在訊息框中;函式可以接受任意數目的引數,你可以輕鬆的將所有要檢視的變數展示出來。

在 PySimpleGUI 中,最常用的訊息框是 MsgBox。要展示上面例子中的資料,只需編寫一行程式碼:

  1. MsgBox('The GUI returned:', button, values)

整合

好了,你已經瞭解了基礎知識,讓我們建立一個包含盡可能多 PySimpleGUI 元素的窗體吧!此外,為了更好的感觀效果,我們將採用綠色/棕褐色的配色方案。

  1. import PySimpleGUI as sg

  2. sg.ChangeLookAndFeel('GreenTan')

  3. form = sg.FlexForm('Everything bagel', default_element_size=(40, 1))

  4. column1 = [[sg.Text('Column 1', background_color='#d3dfda', justification='center', size=(10,1))],

  5.            [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1')],

  6.            [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2')],

  7.            [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3')]]

  8. layout = [

  9.     [sg.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25))],

  10.     [sg.Text('Here is some text.... and a place to enter text')],

  11.     [sg.InputText('This is my text')],

  12.     [sg.Checkbox('My first checkbox!'), sg.Checkbox('My second checkbox!', default=True)],

  13.     [sg.Radio('My first Radio!     ', "RADIO1", default=True), sg.Radio('My second Radio!', "RADIO1")],

  14.     [sg.Multiline(default_text='This is the default Text should you decide not to type anything', size=(35, 3)),

  15.      sg.Multiline(default_text='A second multi-line', size=(35, 3))],

  16.     [sg.InputCombo(('Combobox 1', 'Combobox 2'), size=(20, 3)),

  17.      sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)],

  18.     [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)),

  19.      sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25),

  20.      sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75),

  21.      sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10),

  22.      sg.Column(column1, background_color='#d3dfda')],

  23.     [sg.Text('_'  * 80)],

  24.     [sg.Text('Choose A Folder', size=(35, 1))],

  25.     [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'),

  26.      sg.InputText('Default Folder'), sg.FolderBrowse()],

  27.     [sg.Submit(), sg.Cancel()]

  28.      ]

  29. button, values = form.LayoutAndRead(layout)

  30. sg.MsgBox(button, values)

看上面要寫不少程式碼,但如果你試著直接使用 Tkinter 框架實現同樣的 GUI,你很快就會發現 PySimpleGUI 版本的程式碼是多麼的簡潔。

程式碼的最後一行開啟了一個訊息框,效果如下:

訊息框函式中的每一個引數的內容都會被列印到單獨的行中。本例的訊息框中包含兩行,其中第二行非常長而且包含串列巢狀。

建議花一點時間將上述結果與 GUI 中的元素一一比對,這樣可以更好的理解這些結果是如何產生的。

為你的程式或指令碼新增 GUI

如果你有一個命令列方式使用的指令碼,新增 GUI 不一定意味著完全放棄該指令碼。一種簡單的方案如下:如果指令碼不需要命令列引數,那麼可以直接使用 GUI 呼叫該指令碼;反之,就按原來的方式執行指令碼。

僅需類似如下的邏輯:

  1. if len(sys.argv) == 1:

  2.         # collect arguments from GUI

  3. else:

  4.     # collect arguements from sys.argv

建立並執行 GUI 最便捷的方式就是從 PySimpleGUI 經典實體[2]中複製一份程式碼並修改。

快來試試吧!給你一直疲於手動執行的指令碼增加一些趣味。只需 5-10 分鐘即可玩轉示例指令碼。你可能發現一個幾乎滿足你需求的經典實體;如果找不到,也很容易自己編寫一個。即使你真的玩不轉,也只是浪費了 5-10 分鐘而已。

資源

安裝方式

支援 Tkinter 的系統就支援 PySimpleGUI,甚至包括樹莓派Raspberry Pi,但你需要使用 Python 3。

  1. pip install PySimpleGUI

檔案

◈ 手冊[3]
◈ 經典實體[2]
◈ GitHub repository[1]

via: https://opensource.com/article/18/8/pysimplegui

作者:Mike Barnett[5] 選題:lujun9972 譯者:pinewall 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

贊(0)

分享創造快樂

© 2024 知識星球   網站地圖