當視窗上的元件愈來愈多時,若全部元件都直接建立在主視窗(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)

[結果]
(可自行執行程式碼查看畫面:「聯絡資訊」外框內分成兩列輸入欄位。)

說明

  1. 8~9行:建立group這個LabelFrame容器,標題文字為「聯絡資訊」,並用pack(fill='x', ...)把整個群組框放進主視窗。
  2. 11~16行:在group容器裡建立row1這個Frame,並在row1裡並排「姓名」與「電話」欄位;row1pack()只影響它在group裡的位置,不影響group本身在主視窗中的位置。
  3. 18~21行:同樣在group容器裡再建立row2,放入「地址」欄位,與row1各自獨立、由上而下排列。

在 student_crud.py 的應用

student_crud.py_build_form()方法就是用同樣的手法建立表單:外層用一個ttk.LabelFrame(text='學生資料')把整個表單框起來,內部再用三個ttk.Framerow0row1row2)分別放姓名/性別/生日、Email/電話、地址三列欄位,每一列元件都用side='left'由左至右排列,彼此互不影響。


相關主題與延伸閱讀