自定義窗口 API 調用(您的第一個窗口)
總結一下:我遇到的坑,
比如拿輸入框的內容的時候可以直接通過value[key]
幾種窗口模式就是什么時候用timeout這個參數
關閉窗口可以的一邊形式
if event in ('EXIT', None):
break
這是這個 GUI 編程的有趣部分。為了真正充分利用 API,您應該使用支持自動完成或顯示函數定義的 IDE。這將使定制變得更加順暢。
關於自定義窗口的第一部分是針對典型的、阻塞的、非持久性窗口的。我的意思是,當您“顯示”窗口時,該函數將不會返回,直到用戶單擊按鈕或使用 X 關閉窗口。
存在另外兩種類型的窗口。1. 持久窗口——Window.read()
方法返回,窗口繼續可見。這對於諸如聊天窗口或計時器之類的應用程序或任何在屏幕上保持活動一段時間的應用程序都非常有用。2. 異步窗口——最棘手的。必須非常小心。例如 MP3 播放器或狀態儀表板。異步窗口會定期更新(刷新)。timeout
你可以很容易地發現它們,因為它們在調用 read 時會有一個參數。event, values = window.read(timeout=100)
立即開始調整您可以使用的每一件小事既不愉快也沒有幫助。做一些簡單的窗戶。使用 Cookbook 和演示程序作為學習方式和“起點”。
櫥窗設計師
對於 GUI 編程新手來說,好消息是 PySimpleGUI 有一個窗口設計器。更好的是,窗口設計師無需培訓,無需下載,而且每個人都知道如何使用它。
這是一個手動過程,但如果您按照說明進行操作,只需一分鍾即可完成,結果將是一個漂亮的 GUI。您將采取的步驟是: 1. 在紙上畫出您的 GUI 2. 將您的 GUI 分成幾行 3. 用元素名稱標記每個元素 4. 使用標簽作為偽代碼編寫 Python 代碼
讓我們舉幾個例子。
輸入數字.... 流行的初學者程序通常基於要求用戶輸入某些內容(例如數字)的游戲或邏輯謎題。“高低”答案游戲浮現在腦海中,您嘗試根據高低提示猜測數字。
第 1 步 - 繪制 GUI
第 2 步 - 分成幾行
第 3 步 - 標簽元素
第 4 步 - 編寫代碼 我們正在編寫的代碼是 GUI 本身的布局。本教程只關注編寫窗口代碼,而不是顯示它的東西,獲得結果。
我們在第一行只有一個元素,一些文本。行被寫成一個“元素列表”,所以我們需要 [ ] 來創建一個列表。這是第 1 行的代碼
[ sg.Text('Enter a number') ]
第 2 行有 1 個元素,一個輸入字段。
[ sg.Input() ]
第 3 行有一個確定按鈕
[ sg.OK() ]
現在我們已經定義了 3 行,它們被放入一個代表整個窗口的列表中。
layout = [ [sg.Text('Enter a Number')], [sg.Input()], [sg.OK()] ]
最后我們可以把它們放在一個程序中來顯示我們的窗口。
import PySimpleGUI as sg layout = [[sg.Text('Enter a Number')], [sg.Input()], [sg.OK()] ] window = sg.Window('Enter a number example', layout) event, values = window.read() window.close() sg.Popup(event, values[0])
您的調用read
通常會返回一個字典,但在您訪問它的方式上會“看起來像一個列表”。第一個輸入字段將是條目 0,下一個是 1,等等。稍后您將了解key
允許您使用自己的值來識別元素而不是為您編號的參數。
示例 2 - 獲取文件名
假設您已經編寫了一個對某個輸入文件進行操作的實用程序,並且您准備好使用 GUI 輸入而不是文件名而不是命令行。按照與上一個示例相同的步驟 - 在紙上繪制窗口,將其分成幾行,標記元素。
為這個編寫代碼同樣簡單。有一個棘手的事情是瀏覽文件按鈕。值得慶幸的是,PySimpleGUI 負責將其與旁邊的輸入字段相關聯。結果,代碼看起來幾乎和紙上的窗口一模一樣。
import PySimpleGUI as sg sg.theme('Dark Blue 3') # please make your windows colorful layout = [[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()] ] window = sg.Window('Get filename example', layout) event, values = window.read() window.close() sg.Popup(event, values[0])
繼續閱讀有關顯示窗口並返回結果的調用的詳細說明。
復制這些設計模式!
您的所有 PySimpleGUI 程序都將使用這兩種設計模式中的一種,具體取決於您正在實現的窗口類型。
從版本 4.19.0 開始,常量 WIN_CLOSED 被替換為使用通知None
窗口已關閉的事件。
模式 1 A - “One-shot Window” - 一次讀取一個窗口然后關閉它
如果您不使用“事件循環”(不多次讀取窗口),這將是您將遵循的最常見模式。窗口被讀取並關閉。
窗口中的輸入字段將作為字典返回給您(在語法上它看起來就像一個列表查找)
import PySimpleGUI as sg sg.theme('Dark Blue 3') # please make your windows colorful layout = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')], [sg.InputText(), sg.FileBrowse()], [sg.Submit(), sg.Cancel()]] window = sg.Window('SHA-1 & 256 Hash', layout) event, values = window.read() window.close() source_filename = values[0] # the first input element is values[0]
模式 1 B - “One-shot Window” - 一次讀取一個窗口然后關閉它(壓縮格式)
與模式 1 相同,但以高度緊湊的方式完成。此示例使用close
參數 inwindow.read
作為讀取操作的一部分自動關閉窗口(版本 4.16.0 中的新功能)。這使您能夠編寫將創建、顯示、收集輸入和關閉窗口的單行代碼。真的是很強大的東西!
import PySimpleGUI as sg sg.theme('Dark Blue 3') # please make your windows colorful event, values = sg.Window('SHA-1 & 256 Hash', [[sg.Text('SHA-1 and SHA-256 Hashes for the file')], [sg.InputText(), sg.FileBrowse()], [sg.Submit(), sg.Cancel()]]).read(close=True) source_filename = values[0] # the first input element is values[0]
模式 2 A - 持久窗口(使用事件循環進行多次讀取)
一些更高級的程序在屏幕上保持可見的窗口運行。輸入值被收集,但不是關閉窗口,而是保持可見,作為向用戶輸出信息和收集輸入數據的一種方式。
此代碼將顯示一個窗口並打印值,直到用戶單擊退出按鈕或使用 X 關閉窗口。
import PySimpleGUI as sg sg.theme('Dark Blue 3') # please make your windows colorful layout = [[sg.Text('Persistent window')], [sg.Input()], [sg.Button('Read'), sg.Exit()]] window = sg.Window('Window that stays open', layout) while True: event, values = window.read() if event == sg.WIN_CLOSED or event == 'Exit': break print(event, values) window.close()
模式 2 B - 持久窗口(使用事件循環進行多次讀取 + 更新窗口中的數據)
這是一個稍微復雜但可能更現實的版本,它讀取用戶的輸入並將該輸入顯示為窗口中的文本。您的程序可能會同時執行這兩項活動(輸入和輸出),因此這將為您提供一個很大的起點。
不要擔心所有這些陳述的含義。只需復制它,以便您可以開始使用它,進行一些更改。實驗看看事情是如何工作的。
這個例子介紹了“鍵”的概念。鍵在 PySimpleGUI 中非常重要,因為它們使您能夠使用您想要使用的名稱來識別和使用元素。鍵可以是(幾乎)任何東西,除了None
列表(元組很好)。要訪問在下面的示例中讀取的輸入元素的數據,您將使用values['-IN-']
而不是values[0]
像以前一樣。
import PySimpleGUI as sg sg.theme('Dark Blue 3') # please make your windows colorful layout = [[sg.Text('Your typed chars appear here:'), sg.Text(size=(12,1), key='-OUTPUT-')], [sg.Input(key='-IN-')], [sg.Button('Show'), sg.Button('Exit')]] window = sg.Window('Window Title', layout) while True: # Event Loop event, values = window.read() print(event, values) if event == sg.WIN_CLOSED or event == 'Exit': break if event == 'Show': # change the "output" element to be the value of "input" element window['-OUTPUT-'].update(values['-IN-']) window.close()
Qt 設計器
實際上有一個使用 Qt 的窗口設計器的 PySimpleGUI 窗口設計器。然而,這超出了本文檔的范圍。您可以在這里找到該項目:https://github.com/nngogol/PySimpleGUIDesigner
我希望盡快開始使用它。
Python 中的 GUI 編程應該是什么樣子?至少對於初學者?
雖然一個目標是讓創建 GUI 變得簡單,但另一個同樣重要的目標是以 Python 風格的方式完成它。它是否實現了這些目標還有待商榷,但同樣是一次嘗試。
PySimpleGUI 中自定義窗口的關鍵是將窗口視為 GUI 元素的 ROWS。每一行都被指定為這些元素的列表。把這些行放在一起,你就有了一個窗口。這意味着 GUI 被定義為一系列列表,這是一種查看事物的 Python 方式。
讓我們剖析一下這個小程序
import PySimpleGUI as sg sg.theme('Dark Blue 3') # please make your windows colorful layout = [[sg.Text('Rename files or folders')], [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], [sg.Submit(), sg.Cancel()]] window = sg.Window('Rename Files or Folders', layout) event, values = window.read() window.close() folder_path, file_path = values[0], values[1] # get the data from the values dictionary print(folder_path, file_path)
主題
導入后的第一行代碼是對theme
.
在 2019 年 12 月之前,PySimpleGUI 中特定“主題”的方式是調用change_look_and_feel
. 該調用已被更簡單的函數所取代theme
。
窗口內容(布局)
讓我們同意窗口有 4 行。
第一行只有文字Rename files or folders
第二行有 3 個元素。首先是text Source for Folders
,然后是輸入字段,然后是瀏覽按鈕。
現在讓我們看看 Python 代碼中的這兩行和另外兩行如何:
layout = [[sg.Text('Rename files or folders')], [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], [sg.Submit(), sg.Cancel()]]
看看源代碼如何反映布局?您只需為每一行創建列表,然后將該表提交給 PySimpleGUI 以顯示和獲取值。
那么這些返回值呢?大多數人只是想顯示一個窗口,獲取輸入值並用它們做一些事情。那么,當我只想將窗口的輸入值提供給我時,為什么要將代碼分解為按鈕回調等。
對於返回值,從上到下、從左到右掃描窗口。作為輸入字段的每個字段都將在返回值中占據一個位置。
在我們的示例窗口中,有 2 個字段,因此該窗口的返回值將是一個包含 2 個值的字典。請記住,如果您key
在創建元素時未指定 a,則會為您創建一個。它們是從 0 開始的整數。在這個例子中,我們有 2 個輸入元素。它們可以作為 values[0] 和 values[1] 尋址
“讀取”窗口的值(也顯示窗口)
event, values = window.read()
folder_path, file_path = values[0], values[1]
在一個語句中,我們既顯示窗口又讀取用戶的輸入。在下一行代碼中,返回值字典folder_path
被拆分為單獨的變量和file_path
.
這不是尋找 GUI 的 Python 程序員想要的嗎?一些易於使用的東西來獲得價值並繼續進行程序的其余部分,真正的行動正在發生。當使用 PySimpleGUI 可以在 3 或 4 行代碼中實現相同的布局時,為什么還要編寫 GUI 代碼頁面。4行還是40行?大多數人會選擇4。
返回值
調用有 2 個返回值Window.read()
,一個event
導致Read
返回,values
一個列表或值字典。如果布局中沒有帶鍵的元素,那么它將是一個列表。但是,某些元素(例如某些按鈕)會自動添加一個鍵。 最好在所有輸入類型元素上使用鍵。
兩個返回值
所有 Window Read 調用都返回 2 個值。按照慣例,會寫一個 read 語句:
event, values = window.read()
你不必以這種方式寫你的讀物。您可以根據需要命名變量。但是,如果您想以其他使用 PySimpleGUI 的程序員習慣的方式對它們進行編碼,請使用此語句。
活動
第一個參數event
描述了讀取完成的原因。事件是其中之一:
對於所有 Windows:
- 按鈕點擊
- 使用 X 關閉窗口
對於專門啟用這些的 Windows。請參閱本文檔中的相應部分以了解如何啟用這些以及事件返回值是什么。
- 鍵盤按鍵
- 鼠標滾輪向上/向下
- 已選擇菜單項
- 元素已更改(滑塊、微調器等)
- 單擊了列表項
- 在輸入元素中按下了返回鍵
- 等待事件超時
- 文本被點擊
- 選擇的組合框項目
- 已選擇表格行
- 等等。
大多數情況下,事件將是按鈕單擊或窗口關閉。enable_events=True
當您在創建元素時進行設置時,會發生其他元素特定類型的事件
按鈕點擊事件
默認情況下,按鈕將始終返回單擊事件,或者在實時按鈕的情況下,返回按鈕按下事件。您無需執行任何操作即可啟用按鈕點擊。要禁用事件,請使用其 Update 方法禁用按鈕。
enable_events=True
您可以通過在 Button 調用中設置來啟用額外的“Button Modified”事件。這些事件在某個按鈕“寫入”時觸發,通常是因為該按鈕在另一個按鈕中被列為“目標”。
讀取調用的按鈕值將是 2 個值之一: 1. 按鈕的文本 - 默認 2. 按鈕的鍵 - 如果指定了鍵
如果按鈕在創建時設置了鍵,則無論按鈕上顯示什么文本,都將返回該鍵。如果沒有設置鍵,則返回按鈕文本。如果沒有單擊按鈕,但窗口還是返回了,則事件值是導致事件生成的鍵。例如,如果enable_events
在一個Input
元素上設置了 並且有人在該Input
框中鍵入了一個字符,那么該事件將是輸入框的鍵。
元素事件
當某些元素發生某些事情時,它們能夠生成事件。例如,當滑塊移動,或單擊列表項或單擊表行時。默認情況下不啟用這些事件。要為元素啟用事件,請設置參數enable_events=True
。這與舊click_submits
參數相同。您會發現該click_submits
參數仍在函數定義中。您可以繼續使用它。它們是相同的設置。使用兩個值的“或”。將來,click_submits 將被刪除,因此請將您的代碼遷移到使用enable_events
.
名稱 | 事件 |
---|---|
輸入文本 | 任何改變 |
組合 | 選擇的項目 |
列表框 | 選擇已更改 |
收音機 | 選擇已更改 |
復選框 | 選擇已更改 |
微調器 | 選擇了新項目 |
多行 | 任何改變 |
文本 | 點擊 |
狀態欄 | 點擊 |
圖形 | 點擊 |
圖形 | 拖着 |
圖形 | 拖動結束(鼠標向上) |
選項卡組 | 選項卡點擊 |
滑塊 | 滑塊移動 |
桌子 | 選擇的行 |
樹 | 選定的節點 |
按鈕菜單 | 選擇的菜單項 |
右鍵菜單 | 選擇的菜單項 |
其他活動
為 MenuBar 菜單和 ButtonMenu 菜單選擇的菜單欄菜單項
您將收到 MenuBar 和 ButtonMenu 的鍵。使用該鍵讀取返回值字典中的值。顯示的值將是所選菜單項的全文加鍵。請記住,您可以將鍵放在菜單項上。您將在菜單定義中定義文本和鍵。
右鍵單擊菜單項選擇
與菜單欄和按鈕菜單不同,您將直接收到菜單項文本及其鍵值。您不會進行字典查找來獲取值。它是從 WindowRead() 返回的事件代碼。
Windows - 鍵盤、鼠標滾輪
Windows 能夠返回鍵盤事件。如果它是特殊鍵,它們將作為單個字符或字符串返回。我只能說實驗。鼠標滾輪事件也是字符串。在您的代碼中打印以查看返回的內容。
超時
如果您在讀取中設置了超時參數,則將返回系統 TIMEOUT_KEY。如果您在 Read 調用中指定了自己的超時鍵,則該值將是返回的值。
窗口關閉事件
檢測並正確處理正在關閉的 Windows 是 PySimpleGUI 應用程序的重要組成部分。您會在每個演示程序的每個事件循環中找到一個 if 語句,該語句檢查表明窗口已關閉的事件。
關閉窗口最明顯的方法是單擊窗口右上角的“X”(在 Windows、Linux 上……Mac 不使用“X”但仍有關閉按鈕)。在 Windows 系統上,鍵盤鍵 ALT+F4 將強制窗口關閉。這是不使用鼠標關閉窗口的一種方法。有些程序還可以向窗口發送“關閉”命令。
無論在窗口上如何執行關閉,PySimpleGUI 都會為此關閉返回一個事件。
WIN_CLOSED 事件
當用戶單擊 X 關閉窗口時,將返回常量 WIN_CLOSED (None)。
通常,關閉窗口的檢查發生在window.read()
調用返回之后。原因是在關閉的窗口上操作可能會導致錯誤。檢查關閉是一個“if”語句。
始終在事件循環中包含對關閉窗口的檢查。
The Window Closed If 語句
您可以在文檔和演示程序中找到此 if 語句的 2 種形式。一個是“Pythonic”,另一個更容易被初學者理解。如果窗口同時具有用於指示用戶希望退出的按鈕,則這是您在 PySimpleGUI 材料中最常看到的格式。在此示例中,我使用了“退出”按鈕:
if event == sg.WIN_CLOSED or event == 'Exit': break
同一語句的更“Pythonic”版本是:
if event in (sg.WIN_CLOSED, 'Exit'): break
如果您在文檔中大喊應始終使用第二種形式,請記住許多 PySimpleGUI 用戶是 Python 新手。如果他們看到的第一個 PySimpleGUI 程序示例中包含 if 語句,那么他們甚至在開始旅程之前就會立即迷失方向。所以,決定,你猜對了,變得簡單。帶有“或”的語句更容易理解。
一個完整的例子 - 傳統的窗口關閉檢查
讓我們把這個 if 語句放到上下文中,這樣你就可以看到它的去向以及它是如何與事件循環一起工作的
import PySimpleGUI as sg layout = [[sg.Text('Very basic Window')], [sg.Text('Click X in titlebar or the Exit button')], [sg.Button('Go'), sg.Button('Exit')]] window = sg.Window('Window Title', layout) while True: event, values = window.read() print(event, values) if event == sg.WIN_CLOSED or event == 'Exit': break window.close()
請注意,while 循環之后的行是對window.close()
. 這樣做的原因是退出循環可以有兩種方式。* 單擊“X” * 單擊退出按鈕
如果單擊退出按鈕,窗口仍將打開。養成像這樣明確關閉窗戶的習慣。
如果用戶點擊“X”並關閉窗口,那么它就會被底層框架銷毀。您應該仍然打電話window.close()
,因為可能需要進行清理工作,並且關閉已經關閉的窗口沒有害處。
如果您不關閉窗口,tkinter 有時會生成錯誤/警告。對於其他端口,例如 PySimpleGUIWeb,不關閉窗口可能會導致您的程序繼續在后台運行。這可能會導致您的程序不可見,但會占用 100% 的 CPU 時間。對您的用戶來說不好玩。
窗口關閉確認
在 4.33.0 中enable_close_attempted_event
,向Window
對象添加了一個新參數 。此布爾參數指示您是否希望接收用戶想要關閉窗口的事件,而不是用戶關閉窗口的事件。
要啟用此功能,請使用以下Window
內容創建:
window = sg.Window('Window Title', layout, enable_close_attempted_event=True)
啟用關閉嘗試功能后,當用戶單擊“X”或鍵入 ALT+F4 時,您不會像以前那樣收到 WIN_CLOSED 事件,而是會收到一個事件WINDOW_CLOSE_ATTEMPTED_EVENT
並且窗口將保持打開狀態。
通常此功能用於添加“關閉確認”彈出窗口。流程是這樣的:
- 顯示窗口
- 用戶點擊 X
- 彈出窗口顯示消息“您真的要關閉窗口嗎?”
- 如果確認需要關閉,則關閉窗口。它不是,事件循環繼續,基本上忽略了發生的事件。
一個完整的例子 - 窗口關閉確認 ( enable_close_attempted_event=True
)
回到上面使用的示例,只有 2 處修改。
- 將參數添加
enable_close_attempted_event=True
到調用Window
- 事件循環中的 if 語句已更改為添加確認
import PySimpleGUI as sg layout = [[sg.Text('Very basic Window')], [sg.Text('Click X in titlebar or the Exit button')], [sg.Button('Go'), sg.Button('Exit')]] window = sg.Window('Window Title', layout, enable_close_attempted_event=True) while True: event, values = window.read() print(event, values) if (event == sg.WINDOW_CLOSE_ATTEMPTED_EVENT or event == 'Exit') and sg.popup_yes_no('Do you really want to exit?') == 'Yes': break window.close()
事件循環從這樣的檢查更改:
if event == sg.WIN_CLOSED or event == 'Exit': break
像這樣的人:
if (event == sg.WINDOW_CLOSE_ATTEMPTED_EVENT or event == 'Exit') and sg.popup_yes_no('Do you really want to exit?') == 'Yes': break
讓我們運行最后一個程序,這樣您就可以看到這一切對用戶來說是什么樣的。
在用戶之前退出窗口的這兩種情況下,現在都有一個額外的確認步驟。
演示程序.... PySimpleGUI 程序最好的朋友
與 PySimpleGUI 的所有功能一樣,Demo Programs 是可供您了解參數的最佳資源之一,例如這個接近嘗試的參數。當您遇到以前未使用過的參數或功能時,查找其使用示例的一種方法是使用演示瀏覽器搜索演示程序。您將找到 Cookbook 中描述的演示瀏覽器。
在撰寫本文時,演示程序瀏覽器的名稱為:
Browser_START_HERE_Demo_Programs_Browser.py
如果您輸入本節中描述的參數 -enable_close_attempted_event
您將找到一個使用此參數的演示程序。
此演示向您展示了與文檔本節中使用的代碼類似的代碼。使用這個瀏覽器程序!這將使查找示例變得更加容易!
values
變量 - 以列表形式返回值
Read 調用的第二個參數是 Window 上輸入字段的列表或字典。
默認情況下,返回值是一個值列表,每個輸入字段都有一個條目,但對於除了最簡單的窗口之外的所有窗口,返回值將是一個字典。這是因為您可能會在布局中使用“鍵”。當你這樣做時,它會強制返回值是一個字典。
作為輸入元素的每個元素都將在返回值列表中具有一個值。如果您確定這些值將作為列表返回,那么您可以變得聰明並直接解壓縮到變量中。
event, (filename, folder1, folder2, should_overwrite) = sg.Window('My title', window_rows).read()
或者,更常見的是,您可以單獨解壓縮返回結果。這是首選方法,因為它適用於列表和字典返回值。
event, values = sg.Window('My title', window_rows).read() event, value_list = window.read() value1 = value_list[0] value2 = value_list[1] ...
但是,當您有很多輸入字段時,此方法並不好。如果您在窗口中插入一個新元素,那么您將不得不重新整理您的解包,修改每個語句以引用value_list[x]
.
更常見的方法是通過將鍵放在“重要”元素(您希望從中獲取值並希望與之交互的元素)上,請求您的值作為字典返回
values
變量 - 作為字典返回值
對於那些沒有遇到過 Python 字典的人,不要驚慌!只需復制並粘貼示例代碼並進行修改即可。遵循這個設計模式,你會沒事的。您可能會在此過程中學到一些東西。
對於超過 3 或 4 個字段的窗口,您將需要使用字典來幫助您組織返回值。在幾乎所有(如果不是全部)演示程序中,您都會發現返回值作為字典傳遞。這不是一個很難掌握的概念,語法很容易理解,而且它的代碼可讀性很強。
您將遇到的最常見的窗口讀取語句如下所示:
window = sg.Window("My title", layout).read()
要使用字典,您需要: * 用關鍵字標記您希望在字典中出現的每個輸入元素key
。
如果窗口中的任何元素具有key
,則所有返回值都通過字典返回。如果某些元素沒有鍵,則它們從零開始編號。
讓我們看一下您的第一個基於字典的窗口。
import PySimpleGUI as sg sg.theme('Dark Blue 3') # please make your windows colorful layout = [ [sg.Text('Please enter your Name, Address, Phone')], [sg.Text('Name', size=(15, 1)), sg.InputText('1', key='-NAME-')], [sg.Text('Address', size=(15, 1)), sg.InputText('2', key='-ADDRESS-')], [sg.Text('Phone', size=(15, 1)), sg.InputText('3', key='-PHONE-')], [sg.Submit(), sg.Cancel()] ] window = sg.Window('Simple data entry window', layout) event, values = window.read() window.close() sg.Popup(event, values, values['-NAME-'], values['-ADDRESS-'], values['-PHONE-'])
要獲取輸入字段的值,請使用用作key
值的任何值作為索引值。因此要獲取名稱字段的值,可以寫為
values['-NAME-']
以與列表相同的方式考慮變量值,但是,不要使用 0、1、2 來引用列表中的每個項目,而是使用鍵的值。上面窗口中的 Name 字段由 引用values['-NAME-']
。
您會發現在大多數 PySimpleGUI 窗口中使用的關鍵字段非常多,除非窗口非常簡單。
您將在許多演示程序中看到的一個約定是鍵以全部大寫字母命名,開頭和結尾都帶有下划線。您不必這樣做...您的鍵值可能如下所示: key = '-NAME-'
這種命名約定的原因是當你掃描代碼時,這些關鍵值會跳出來。您立即知道這是一把鑰匙。嘗試掃描上面的代碼,看看這些鍵是否彈出。 key = '-NAME-'
事件循環/回調函數
所有 GUI 都有一個共同點,即“事件循環”。通常 GUI 框架會為您運行事件循環,但有時您需要更大的控制權並會運行您自己的事件循環。在討論嵌入式系統或 Raspberry Pi 時,您經常會聽到術語事件循環。
使用 PySimpleGUI,如果您的窗口在單擊按鈕后仍保持打開狀態,那么您的代碼將有一個事件循環。如果您的程序顯示一個“一次性”窗口,收集數據然后沒有其他 GUI 交互,那么您不需要事件循環。
事件循環沒有什么神秘的......它們是你需要處理的循環......等待它......事件。事件是諸如按鈕單擊、擊鍵、鼠標滾輪向上/向下之類的事情。
這個小程序有一個典型的 PySimpleGUI 事件循環。
PySimpleGUI 事件循環的剖析如下,一般來說。*實際的“循環”部分是一個while True
循環 *“讀取”事件和窗口具有的任何輸入值 *檢查窗口是否關閉或用戶希望退出 *一系列if event ....
語句
這是一個完整的簡短程序來演示這些概念中的每一個。
import PySimpleGUI as sg sg.ChangeLookAndFeel('GreenTan') # ------ Menu Definition ------ # menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']], ['&Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ], ['&Help', '&About...'], ] # ------ Column Definition ------ # column1 = [[sg.Text('Column 1', background_color='lightblue', justification='center', size=(10, 1))], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1')], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2')], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3')]] layout = [ [sg.Menu(menu_def, tearoff=True)], [sg.Text('(Almost) All widgets in one Window!', size=(30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE)], [sg.Text('Here is some text.... and a place to enter text')], [sg.InputText('This is my text')], [sg.Frame(layout=[ [sg.Checkbox('Checkbox', size=(10,1)), sg.Checkbox('My second checkbox!', default=True)], [sg.Radio('My first Radio! ', "RADIO1", default=True, size=(10,1)), sg.Radio('My second Radio!', "RADIO1")]], title='Options',title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='Use these to set flags')], [sg.Multiline(default_text='This is the default Text should you decide not to type anything', size=(35, 3)), sg.Multiline(default_text='A second multi-line', size=(35, 3))], [sg.InputCombo(('Combobox 1', 'Combobox 2'), size=(20, 1)), sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)], [sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))], [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)), sg.Frame('Labelled Group',[[ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25, tick_interval=25), sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75), sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10), sg.Column(column1, background_color='lightblue')]])], [sg.Text('_' * 80)], [sg.Text('Choose A Folder', size=(35, 1))], [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Default Folder'), sg.FolderBrowse()], [sg.Submit(tooltip='Click to submit this form'), sg.Cancel()]] window = sg.Window('Everything bagel', layout, default_element_size=(40, 1), grab_anywhere=False) event, values = window.read() window.close() sg.Popup('Title', 'The results of the window.', 'The button clicked was "{}"'.format(event), 'The values are', values)
這是一個復雜的窗口,具有相當多的自定義大小以使事物排列整齊。這是您只需編寫一次的代碼。查看代碼時,請記住您看到的是列表列表。每行包含一個用於創建窗口的圖形元素列表。如果您看到一對方括號 [ ],那么您就知道您正在閱讀其中一行。GUI 的每一行都將是這些列表之一。
這個窗口對你來說可能看起來“丑陋”,這是因為沒有做出任何努力讓它看起來不錯。它純粹是功能性的。窗口中有 30 個元素。三十個元素。考慮到它的作用,它是神奇的,或者至少令人難以置信的令人印象深刻。為什么?因為在不到 50 行代碼中創建、顯示、收集結果並在另一個窗口中顯示結果。
50 行。如果你能做到的話,你將需要 50 行 tkinter 或 Qt 代碼來編寫窗口的前 3 個元素。
不,讓我們在這里明確一點……這個窗口將使用傳統的 Python GUI 包來處理大量代碼。這是事實,如果你想證明我錯了,那么請務必這樣做。請使用 tkinter、Qt 或 WxPython 編寫此窗口並發送代碼!
請注意,此窗口頂部甚至還有一個菜單欄,很容易錯過。
單擊提交按鈕導致窗口調用返回。對 Popup 的調用導致出現此窗口。
Note, event values can be None
. 的值event
將是按鈕元素創建時顯示的文本或按鈕的鍵。如果用戶使用窗口右上角的“X”關閉窗口,event
則sg.WIN_CLOSED
等於None
。您的代碼 包含對sg.WIN_CLOSED
.
對於“永久窗口”, 始終為您的用戶提供出路。否則,您將得到永遠無法正確關閉的窗口。您可以在每個演示程序中找到實際上是 2 行代碼。當您使用它時,請確保window.close()
在您的事件循環之后調用,以便您的窗口確定關閉。
您可以在結果彈出窗口中看到返回的值是一個字典。窗口中的每個輸入字段都會在返回值列表中生成一項。輸入字段通常返回一個string
. 復選框和單選按鈕返回bool
。根據您的配置方式或您使用的端口,滑塊可能返回浮點數或整數。
如果您的窗口沒有鍵並且沒有“瀏覽”類型的按鈕,那么它將以列表而不是字典的形式返回值。如果可能,PySimpleGUI 會嘗試將值作為列表返回以保持簡單。
請注意,在此示例的返回值列表中,許多鍵是數字。那是因為沒有在任何元素上指定鍵(盡管自動為您創建了一個)。如果您沒有為元素指定鍵,則將按順序分配一個數字。對於您不打算從中修改或讀取值的元素,例如文本元素,您可以跳過添加鍵。對於其他元素,您可能需要添加鍵,以便您可以輕松訪問這些值並對它們執行操作。