當視窗上的元件愈來愈多時,若全部元件都直接建立在主視窗(win)上,會有兩個問題:一是pack()只能由上下左右四個方向堆疊,元件一多就很難排出「多列、每列又有好幾個元件並排」的畫面;二是元件之間彼此沒有分組,日後要調整某一區塊的版面時,會牽動到其他不相關的元件。
這時候可以先建立「容器(Container)」元件,把邏輯上相關的元件(例如同一列的「姓名」標籤與文字方塊)放進同一個容器內,再將整個容器排版到主視窗,即可達到「分區排版」的效果。ttk模組提供兩種常用容器:
| 元件 | 說明 |
|---|---|
ttk.Frame | 單純的容器,本身沒有任何外觀(沒有邊框、沒有標題),只用來分組、輔助版面配置。 |
ttk.LabelFrame | 帶有標題文字與外框的容器,適合把同一類的欄位框起來並加上群組標題(例如「學生資料」)。 |
建立容器的語法如下:
物件變數 = ttk.Frame(容器物件, [參數1=值1, 參數2=值2, …])
物件變數 = ttk.LabelFrame(容器物件, text='標題文字', [參數1=值1, …])常用參數
| 參數 | 說明 |
|---|---|
text | (僅LabelFrame)設定外框左上角顯示的標題文字。 |
width | 設定容器的寬度。 |
height | 設定容器的高度。 |
padding | 設定容器內緣(容器邊框與內部元件之間)的留白空間。 |
使用方式
容器本身也是一個元件,因此建立好之後,一樣要呼叫pack()或grid()把它放進父容器(例如主視窗)中;容器「裡面」的元件,則是把該容器變數當作父物件建立,再各自呼叫pack()/grid()排版:
frame = ttk.LabelFrame(win, text='學生資料')
frame.pack(fill='x', padx=10, pady=5) # 把 frame 放進主視窗
row0 = ttk.Frame(frame) # 在 frame 容器裡再建立一個 Frame
row0.pack(fill='x', padx=5, pady=3)
ttk.Label(row0, text='姓名:', width=8).pack(side='left') # 元件建立在 row0 裡如上寫法,row0的父物件是frame而不是win,所以row0只會影響frame內的版面配置,不會影響frame外的其他元件;透過「容器包容器」的方式,可以把複雜的畫面拆解成一列一列、一區一區來管理,各區塊互不干擾。
[簡例] 使用LabelFrame建立一個「聯絡資訊」群組框,框內用Frame分成兩列,第一列放姓名與電話,第二列放地址。(檔名:labelframe01.py)
程式碼:
labelframe01.pyimport tkinter as tk from tkinter import ttk win = tk.Tk() win.title('容器元件範例') win.geometry('320x150') group = ttk.LabelFrame(win, text='聯絡資訊') group.pack(fill='x', padx=10, pady=10) row1 = ttk.Frame(group) row1.pack(fill='x', padx=5, pady=3) ttk.Label(row1, text='姓名:').pack(side='left') ttk.Entry(row1, width=12).pack(side='left', padx=5) ttk.Label(row1, text='電話:').pack(side='left') ttk.Entry(row1, width=12).pack(side='left', padx=5) row2 = ttk.Frame(group) row2.pack(fill='x', padx=5, pady=3) ttk.Label(row2, text='地址:').pack(side='left') ttk.Entry(row2, width=30).pack(side='left', padx=5) win.mainloop()
[結果]
(可自行執行程式碼查看畫面:「聯絡資訊」外框內分成兩列輸入欄位。)
說明
- 第
8~9行:建立group這個LabelFrame容器,標題文字為「聯絡資訊」,並用pack(fill='x', ...)把整個群組框放進主視窗。- 第
11~16行:在group容器裡建立row1這個Frame,並在row1裡並排「姓名」與「電話」欄位;row1的pack()只影響它在group裡的位置,不影響group本身在主視窗中的位置。- 第
18~21行:同樣在group容器裡再建立row2,放入「地址」欄位,與row1各自獨立、由上而下排列。
在 student_crud.py 的應用
student_crud.py的_build_form()方法就是用同樣的手法建立表單:外層用一個ttk.LabelFrame(text='學生資料')把整個表單框起來,內部再用三個ttk.Frame(row0、row1、row2)分別放姓名/性別/生日、Email/電話、地址三列欄位,每一列元件都用side='left'由左至右排列,彼此互不影響。
相關主題與延伸閱讀
- 0. 章節索引:本章全部筆記的學習地圖與快速查找。
- 1. tkinter 套件:
tkinter套件的整體介紹與元件總覽。 - 11. ttk 主題元件套件:
Frame與LabelFrame皆屬於ttk模組的主題化元件。 - 3. 視窗版面配置:容器元件本身仍須以
pack()/grid()排版,是本篇的先備知識。 - 13. Combobox 下拉式選單元件:
student_crud.py的表單容器內即包含Combobox欄位。 - 14. Treeview 清單(表格)元件:
student_crud.py中容器與表格元件常一起搭配組成完整畫面。