重點
1通過循環生成一行
2通過循環生成一列
3【】這個代表一行
4需要大量重復布局的時候可以使用
生成的布局(如果你有> 5個重復元素/行,一定要閱讀)
本節討論了 5 種生成布局的特定技術。它們可以單獨使用,也可以相互結合使用。
- 布局 + 布局串聯
[[A]] + [[B]] = [[A], [B]]
- 同一行上的元素添加
[[A] + [B]] = [[A, B]]
- 列表理解生成一行
[A for x in range(10)] = [A,A,A,A,A...]
- 列表理解生成多行
[[A] for x in range(10)] = [[A],[A],...]
- 用戶定義元素/復合元素
示例 - 連接多行的列表理解 - “待辦事項”列表示例
讓我們創建一個小布局,用於使用 PySimpleGUI 制作待辦事項列表。
蠻力
import PySimpleGUI as sg layout = [ [sg.Text('1. '), sg.In(key=1)], [sg.Text('2. '), sg.In(key=2)], [sg.Text('3. '), sg.In(key=3)], [sg.Text('4. '), sg.In(key=4)], [sg.Text('5. '), sg.In(key=5)], [sg.Button('Save'), sg.Button('Exit')] ] window = sg.Window('To Do List Example', layout) event, values = window.read()
這個腳本的輸出是這個窗口:
花點時間看看代碼和生成的窗口。您是否能夠查看布局並設想屏幕上的窗口?
通過連接行構建
蠻力方法適用於 5 項長的列表,但如果您的待辦事項列表上有 40 項怎么辦。然后呢?好吧,這就是我們轉向“生成”布局的時候,它是由您的代碼生成的布局。用這個布局定義替換上一個示例中的 layout= 內容。
import PySimpleGUI as sg layout = [] for i in range(1,6): layout += [sg.Text(f'{i}. '), sg.In(key=i)], layout += [[sg.Button('Save'), sg.Button('Exit')]] window = sg.Window('To Do List Example', layout) event, values = window.read()
它當然會產生完全相同的窗口。這就是進步.... 從寫出 GUI 的每一行到生成每一行。如果我們想要建議的 48 個項目,請將 range(1,6) 更改為 range(1,48)。每次通過列表時,都會將另一行添加到布局中。
使用列表理解創建多行
但是,我們還沒有完成!
這是Python,我們使用列表來構建一些東西,所以我們應該看看*list comprehensions *. 讓我們將for
循環更改為列表推導。回想一下,我們的for
循環用於將 6 行連接到一個布局中。
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)]
在這里,我們將for
循環移動到列表定義內部(列表理解)
連接多行
我們已經使用列表推導構建了行,現在我們只需要按鈕。通過簡單的添加,它們可以很容易地“固定到最后”。
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)] layout += [[sg.Button('Save'), sg.Button('Exit')]]
任何時候您有 2 個布局,您都可以通過簡單的相加將它們連接起來。確保您的布局是“列表列表”布局。在上面的例子中,我們知道第一行是輸入行的生成布局。最后一行在布局上添加了另一個布局...注意格式為 [ [ ] ]。
這個按鈕定義是一個完整的布局,可以添加到我們的列表理解中
[[sg.Button('Save'), sg.Button('Exit')]]
這是相當可讀的代碼。兩種布局在視覺上排列得很好。
但是,我們不要停止壓縮代碼。如何刪除那個 += 而是將布局更改為單行,+
在兩組行之間只有 a 。
在一行上進行這種連接,我們最終得到了這個為 GUI創建整個布局的語句:
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)] + [[sg.Button('Save'), sg.Button('Exit')]]
最終“待辦事項”計划
這里我們有我們的最終程序......所有4行。
import PySimpleGUI as sg layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)] + [[sg.Button('Save'), sg.Button('Exit')]] window = sg.Window('To Do List Example', layout) event, values = window.read()
如果你真的想把事情搞定,你可以通過將布局移動到對 Window
import PySimpleGUI as sg event, values = sg.Window('To Do List Example', layout=[[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)] + [[sg.Button('Save'), sg.Button('Exit')]]).read()
示例 - 構建行的列表理解 - 表模擬 - 輸入網格
在這個例子中,我們正在使用Input
元素構建一個 4 寬 x 10 高的“桌子”
我們正在尋求的最終結果是這樣的:
HEADER 1 HEADER 2 HEADER 3 HEADER 4
INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT INPUT
代碼完成后,結果將如下所示:
我們將使用列表推導構建每一行,我們將通過使用另一個列表推導連接行來構建表格。這是一個跨越的列表理解和另一個沿着布局向下的列表理解,一行接一行地添加。
構建標題
首先讓我們構建標題。這里有兩個概念需要注意:
import PySimpleGUI as sg headings = ['HEADER 1', 'HEADER 2', 'HEADER 3','HEADER 4'] # the text of the headings header = [[sg.Text(' ')] + [sg.Text(h, size=(14,1)) for h in headings]] # build header layout
這段代碼中有兩點需要注意 1. 構成標題元素的列表理解 2. 添加到前面的空格
讓我們從標題本身開始。
這是生成一行包含標題文本的文本元素的代碼。結果是一個文本元素列表,一行。
[sg.Text(h, size=(14,1)) for h in headings]
然后我們添加一些空格來移動標題,使它們在它們的列上居中。為此,我們只需Text
在該標題列表的前面添加一個元素即可。
header = [[sg.Text(' ')] + [sg.Text(h, size=(14,1)) for h in headings]]
這個header
變量是一個有 1 行的布局,其中有一堆Text
帶有標題的元素。
構建輸入元素
元素以Input
網格形式排列。為此,我們將使用雙重列表推導。一個將構建行,另一個將行添加在一起以形成網格。這是執行此操作的代碼行:
input_rows = [[sg.Input(size=(15,1), pad=(0,0)) for col in range(4)] for row in range(10)]
語句的這一部分構成單行 4 個Input
元素
[sg.Input(size=(15,1), pad=(0,0)) for col in range(4)]
接下來,我們獲取Input
元素列表,並根據行數制作盡可能多的元素,在本例中為 10。我們再次使用 Python 令人敬畏的列表推導將這些行添加到一起。
input_rows = [[sg.Input(size=(15,1), pad=(0,0)) for col in range(4)] for row in range(10)]
第一部分應該看起來很熟悉,因為它只是作為構建單行的內容進行了討論。要制作矩陣,我們只需取那一行並創建 10 個,每個都是一個列表。
把它們放在一起
這是我們的最終程序,它使用簡單的加法將標題添加到輸入矩陣的頂部。為了使其更具吸引力,顏色主題設置為“深棕色 1”。
import PySimpleGUI as sg sg.theme('Dark Brown 1') headings = ['HEADER 1', 'HEADER 2', 'HEADER 3','HEADER 4'] header = [[sg.Text(' ')] + [sg.Text(h, size=(14,1)) for h in headings]] input_rows = [[sg.Input(size=(15,1), pad=(0,0)) for col in range(4)] for row in range(10)] layout = header + input_rows window = sg.Window('Table Simulation', layout, font='Courier 12') event, values = window.read()
用戶定義元素/復合元素
“用戶定義元素”和“復合元素”是包裝在函數定義中的一個或多個 PySimpleGUI 元素。在布局中,它們看起來像是某種類型的自定義元素。
當您在布局中反復使用的元素上設置大量參數時,用戶定義的元素特別有用。
示例 - 計算器應用程序的按鈕網格
假設您正在使用具有以下設置的按鈕制作計算器應用程序:
- 字體 = Helvetica 20
- 大小 = 5,1
- 按鈕顏色=藍底白字
這些按鈕之一的代碼是:
sg.Button('1', button_color=('white', 'blue'), size=(5, 1), font=("Helvetica", 20))
如果您有 6 個按鈕和 5 個按鈕,那么您的布局將有 30 行這樣的文本。
這些按鈕的一行可以寫成:
[sg.Button('1', button_color=('white', 'blue'), size=(5, 1), font=("Helvetica", 20)), sg.Button('2', button_color=('white', 'blue'), size=(5, 1), font=("Helvetica", 20)), sg.Button('3', button_color=('white', 'blue'), size=(5, 1), font=("Helvetica", 20)), sg.Button('log', button_color=('white', 'blue'), size=(5, 1), font=("Helvetica", 20)), sg.Button('ln', button_color=('white', 'blue'), size=(5, 1), font=("Helvetica", 20)), sg.Button('-', button_color=('white', 'blue'), size=(5, 1), font=("Helvetica", 20))],
通過使用用戶定義元素,您可以顯着縮短布局。讓我們調用我們的元素CBtn
。它會這樣寫:
def CBtn(button_text): return sg.Button(button_text, button_color=('white', 'blue'), size=(5, 1), font=("Helvetica", 20))
使用您的新CBtn
元素,您可以將上面的按鈕行重寫為:
[CBtn('1'), CBtn('2'), CBtn('3'), CBtn('log'), CBtn('ln'), CBtn('-')],
查看您不必編寫的大量代碼!每當您發現自己多次復制一個元素時,請使用此構造。
但我們不要止步於此。
由於我們一直在討論列表推導,讓我們使用它們來創建這一行。做到這一點的方法是制作一個跨越行的符號列表,形成一個遍歷該列表的循環。結果是一個如下所示的列表:
[CBtn(t) for t in ('1','2','3', 'log', 'ln', '-')],
該代碼生成的列表與我們手動創建的列表相同:
[CBtn('1'), CBtn('2'), CBtn('3'), CBtn('log'), CBtn('ln'), CBtn('-')],
復合元素
就像一個Button
可以從用戶定義的元素中返回一樣,多個元素也可以。
回到我們之前做的待辦事項列表示例,我們可以定義一個用戶定義的元素來表示一個待辦事項,這次我們要添加一個復選框。此列表中的一行將是:
- 項目#(一個
Text
元素) Checkbox
指示已完成的元素Input
輸入要做什么的元素
我們的 User Element 的定義就是這個ToDoItem
函數。它是由 3 個 PySimpleGUI 元素組合而成的單個用戶元素。
def ToDoItem(num): return [sg.Text(f'{num}. '), sg.CBox(''), sg.In()]
當與我們之前學習的列表理解技術相結合時,這使得創建一個包含 5 個待辦事項的列表變得非常簡單。這是在我們的待辦事項列表中創建 5 個條目所需的代碼。
layout = [ToDoItem(x) for x in range(1,6)]
然后我們可以從字面上添加按鈕
layout = [ToDoItem(x) for x in range(1,6)] + [[sg.Button('Save'), sg.Button('Exit')]]
這是我們的最終程序
import PySimpleGUI as sg def ToDoItem(num): return [sg.Text(f'{num}. '), sg.CBox(''), sg.In()] layout = [ToDoItem(x) for x in range(1,6)] + [[sg.Button('Save'), sg.Button('Exit')]] window = sg.Window('To Do List Example', layout) event, values = window.read()
它創建的窗口如下所示:
2列元素和框架,選項卡“容器”元素
列和框架和選項卡都是“容器元素”並且行為相似。本節重點介紹列,但可以在其他地方應用。
從 2.9 版開始,您將能夠使用 Column Element 進行更復雜的布局。將列視為窗口中的窗口。而且,是的,如果需要,您可以在 Column 中擁有 Column。
與所有“容器元素”一樣,列以與窗口完全相同的方式指定為列表列表。
如果要在單行中指定多個元素,則需要列。
例如,此布局有一個滑塊元素,該元素跨越多行,后跟 7Text
和Input
同一行上的元素。
如果沒有列元素,您將無法創建這樣的布局。但是有了它,您應該能夠緊密匹配僅使用 tkinter 創建的任何布局。
import PySimpleGUI as sg # Demo of how columns work # window has on row 1 a vertical slider followed by a COLUMN with 7 rows # Prior to the Column element, this layout was not possible # Columns layouts look identical to window layouts, they are a list of lists of elements. window = sg.Window('Columns') # blank window # Column layout col = [[sg.Text('col Row 1')], [sg.Text('col Row 2'), sg.Input('col input 1')], [sg.Text('col Row 3'), sg.Input('col input 2')], [sg.Text('col Row 4'), sg.Input('col input 3')], [sg.Text('col Row 5'), sg.Input('col input 4')], [sg.Text('col Row 6'), sg.Input('col input 5')], [sg.Text('col Row 7'), sg.Input('col input 6')]] layout = [[sg.Slider(range=(1,100), default_value=10, orientation='v', size=(8,20)), sg.Column(col)], [sg.In('Last input')], [sg.OK()]] # Display the window and get values window = sg.Window('Compact 1-line window with column', layout) event, values = window.read() window.close() sg.Popup(event, values, line_width=200)
列作為修改元素的一種方式
有時 Columns 用於包含單個 elemnet,但要做到這一點,即使不是不可能,也很難做到這些布局。
通過設置'參數來證明Column
元素的行。Column
justification
您還可以Column
使用 Column 的element_justification
參數來證明 a 中的全部內容。
使用這些參數,可以創建內容居中的窗口。以前這很難做到。
這目前僅在主要 PySimpleGUI 端口中可用。
它們還可以用於以特定方式證明一組元素的合理性。
將元素放置Column
在元素內部Columns
可以創建大量
3分級器元素Sizer
4.3 中的新功能是Sizer
元素。此元素用於幫助創建特定大小的容器。它可以放在這些 PySimpleGUI 項中:
- 柱子
- 框架
- 標簽
- 窗戶
a 的實現Sizer
非常簡單。它返回一個空Column
元素,該元素的填充值設置為傳遞給Sizer
. 因此不是一個類,而是一個類似於預定義按鈕的“快捷功能”。
此功能目前僅在 PySimpleGUI 的 tkinter 端口中可用。需要一個交叉口。
4框架元素(帶標簽的框架,帶標題的框架)
框架與列的工作方式完全相同。您創建布局,然后用於初始化 Frame。與 Column 元素一樣,它是一個“容器元素”,其中包含一個或多個元素。
注意框架布局看起來與窗口布局相同。窗口的工作方式與列和框架完全相同。它們都是“容器元素”——包含其他元素的元素。
這些容器元素可以嵌套任意深度。這是一個非常漂亮的功能,對吧?做了很多工作,所以要感激。遞歸代碼並非易事。
此代碼創建一個帶有 Frame 和 2 個按鈕的窗口。
frame_layout = [
[sg.T('Text inside of a frame')], [sg.CB('Check 1'), sg.CB('Check 2')], ] layout = [ [sg.Frame('My Frame Title', frame_layout, font='Any 12', title_color='blue')], [sg.Submit(), sg.Cancel()] ] window = sg.Window('Frame with buttons', layout, font=("Helvetica", 12))
4選項卡和選項卡組元素
選項卡是 PySimpleGUI“容器元素”的另一個。它能夠“包含”一個布局,就像一個窗口包含一個布局一樣。其他容器元素包括Column
andFrame
元素。
就像窗口和其他容器元素一樣,Tab
元素的布局由任何所需布局中的任何所需元素組合組成。您可以在 Windows 內的 Columns 內的 Tabs 內擁有 Tabs 等。
Tab
布局看起來與 Window 布局完全一樣,即它們是Elements 列表的列表。
將 Tab 元素放入窗口的方式與所有其他元素不同。 您不能將 Tab 直接放入 Window 的布局中。
此外,此時不能使選項卡不可見。他們有一個可見性參數,但調用 update 不會改變它。
選項卡包含在選項卡組中。它們不會被放置到其他布局中。要將選項卡放入窗口,首先將Tab
元素放入TabGroup
元素,然后將TabGroup
元素放入窗口布局。
讓我們以這個 Window 為例:
第二個選項卡的視圖:
tab1_layout = [[sg.T('This is inside tab 1')]] tab2_layout = [[sg.T('This is inside tab 2')], [sg.In(key='in')]]
整個窗口的布局如下所示:
layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout), sg.Tab('Tab 2', tab2_layout)]])], [sg.Button('Read')]]
窗口布局具有 TabGroup,並且在選項卡組中有兩個 Tab 元素。
關於所有這些容器元素和 Windows 布局,需要注意的一件重要事情是……它們都采用“列表列表”作為布局。他們都有一個看起來像這樣的布局[[ ]]
當您正在調試選項卡式窗口時,您將希望將此[[ ]]
構造保留在您的腦海中。很容易忽略一兩個必要的 ['s
如前所述,舊式選項卡僅限於窗口級別。換句話說,選項卡的大小與整個窗口相同。“新型”選項卡不是這種情況。這就是為什么當您發現您的舊代碼不再適用於新的 PySimpleGUI 版本時您不會感到不安的原因。花一點時間來轉換你的代碼是值得的。
看看新標簽有什么可能!
查看選項卡 7 和 8。我們有一個窗口,其中有一列包含選項卡 5 和 6。選項卡 6 上是...選項卡 7 和 8。
從 3.8.0 版開始,並非Tab 和 TabGroup 元素的 API 定義中顯示的所有選項都有效。它們作為占位符存在。
首先我們有選項卡布局定義。它們反映了您在屏幕截圖中看到的內容。選項卡 1 中有 1 個文本元素。選項卡 2 有一個文本和一個輸入元素。
閱讀標簽組
現在,當讀取返回時,選項卡組會返回一個值。它們返回當前選擇的選項卡。如果選擇/更改了該組中的選項卡,還有一個enable_events
可以設置的參數會導致讀取返回。屬於切換到的 Tab 的鍵或標題將作為值返回
x## 窗格元素
3.20 版中的新功能是 Pane Element,這是一個超酷的 tkinter 功能。你不會在 PySimpleGUIQt 中找到這個,只有 PySimpleGUI。很難描述其中之一。將它們視為可以滑動的“沒有標簽的標簽”。
窗格元素的每個“窗格”都必須是列元素。該參數pane_list
是列元素的列表。
如果您嘗試將所有內容聲明為內聯,如本示例中所示,調用可能會看起來有點毛茸茸。
sg.Pane([col5, sg.Column([[sg.Pane([col1, col2, col4], handle_size=15, orientation='v', background_color=None, show_handle=True, visible=True, key='_PANE_', border_width=0, relief=sg.RELIEF_GROOVE),]]),col3 ], orientation='h', background_color=None, size=(160,160), relief=sg.RELIEF_RAISED, border_width=0)
將這些與可見性相結合,形成了一個有趣的界面,整個窗格從視圖中隱藏起來,直到用戶需要。這是產生“動態”窗口的一種方式。
顏色
從 2.5 版開始,您可以更改窗口和元素的背景顏色。
你的窗戶可以從這里開始:
對此......通過一個函數調用......
雖然您可以在逐個元素或窗口級別的基礎上執行此操作,但更簡單的方法是使用theme
調用或set_options
. 這些調用將為創建的所有窗口設置顏色。
請注意,一旦您更改了這些選項,它們就會在程序執行的其余部分中更改。您的所有窗口都將具有該主題,直到您將其更改為其他內容。
此調用設置了許多不同的顏色選項。
SetOptions(background_color='#9FB8AD', text_element_background_color='#9FB8AD', element_background_color='#9FB8AD', scrollbar_color=None, input_elements_background_color='#F7F3EC', progress_meter_color = ('green', 'blue') button_color=('white','#475841'))