首頁 > 軟體

Python的GUI程式設計之Pack、Place、Grid的區別說明

2022-06-20 22:02:05

GUI程式設計之 Pack、Place、Grid的區別

本文講述如何使用 tkinter 的佈局管理 (被稱作 layout managers 或 geometry managers). tkinter 有三種佈局管理方式:

  • pack
  • grid
  • place

注意這三種佈局管理在同一個 master window 裡一定不可以混用! 佈局管理有以下功能:

  • 將控制元件放置在螢幕上,包括控制元件的位置及控制元件的大小
  • 將控制元件註冊到本地視窗系統中
  • 管理控制元件在螢幕上的顯示

雖然控制元件自己也可以指定大小和對齊方式等資訊, 但最終的控制元件大小及位置還是由佈局管理決定的.

Pack 佈局管理

pack 是三種佈局管理中最常用的. 另外兩種佈局需要精確指定控制元件具體的顯示位置, 而 pack 佈局可以指定相對位置, 精確的位置會由 pack 系統自動完成. 這也使得 pack 佈局沒有另外兩種佈局方式靈活. 所以 pack 是

簡單應用的首選佈局

fill 控制元件填充方式

設定元件之間的間隙大小

  • ipadx,ipady設定內部間隙
  • padx,pady設定外部間隙
  • side 順次放置控制元件

Place 佈局管理

Place 佈局管理可以顯式的指定控制元件的絕對位置或相對於其他控制元件的位置. 要使用 Place 佈局, 呼叫相應控制元件的 place() 方法就可以了. 所有 tkinter 的標準控制元件都可以呼叫 place()方法.

下面是一個使用 Place 佈局的例子: 為 Label 控制元件設定隨機的背景色, 然後計算各個 Label 的背景色的亮度(灰度值), 如果其亮度小於 120, 則將其前景色(文字顏色, fg屬性)設定為白色, 否則設為黑色. 這樣做是為了避免使背景色和前景色過於接近而導致文字不易閱讀

Grid 佈局管理

Pack 作為首選的佈局管理方式,其運作方式並不是特別易於理解. 已經由 Pack 佈局完成的設計也很難做出改變. Grid 佈局在1996年作為另一種可供選擇的佈局方式被引入. Grid 佈局方式易學易用, 但似乎大家還是習慣用 Pack.

Grid 在很多場景下是最好用的佈局方式.相比而言, Pack 佈局在控制細節方面有些力不從心. Place 佈局雖然可以完全控制控制元件位置, 但這也導致使用 Place 會比其他兩種佈局方式更加複雜.

Grid 把控制元件位置作為一個二維表結構來維護,即按照行列的方式排列控制元件: 控制元件位置由其所在的行號和列號決定. 行號相同而列號不同的幾個控制元件會被彼此上下排列; 列號相同而行號不同的幾個控制元件會被彼此左右排列.

使用 Grid 佈局的過程就是為各個控制元件指定行號和列號的過程. 不需要為每個格子指定大小, Grid 佈局會自動設定一個合適的大小.

GUI中關於打包幾何管理器(Pack)的一些細節

先談談packer佈局系統的工作原理

pack打包的步驟如下:

  • packer最初開始時,擁有整個父元件容器的可用空間(如整個框架或頂層視窗的空間)
  • 隨著元件在某一條邊上被打包,該元件獲得了剩餘空間中要求的一條邊,剩餘空間縮小(預設為頂部那條邊,即TOP)。
  • 經過先前的打包要求,空間縮小,後來的打包要求只能獲得縮小後剩餘空間的一條邊。
  • 元件都分配空間後,expand選項劃分所有的剩餘空間,fill選項和anchor選項在元件分配的空間內拉伸調整元件

由此可見,pack選項執行的順序為side>expand>fill/anchor。

fill與anchor選項必須在元件分配到所在空間,完成打包順序,expand要求後才可使用。

打包順序將對剪下結果產生影響

打包過程中,pack的順序很重要。注意其中因為父視窗縮小而產生的裁切問題:先打包的最後被裁切。(從技術上講,視窗尺寸改變後優惠執行打包步驟。這意味著,在視窗縮小時,將沒有足夠的空間留給最後打包的元件,看上去就像最先打包的元件最後被裁切掉)

觀察以下兩個程式碼因視窗縮小時產生的不同效果:

#我們只關注裁切問題

from tkinter import *

def greeting():
    print('Hello stdout world!...')

win = Frame()
win.pack(expand=YES,fill=BOTH)
Button(win, text='Hello', command=greeting).pack()
Label(win, text='Hello container world').pack(side=TOP)#side選項使該標籤位於頂部
win.mainloop()

可以看到視窗縮小時由於裁切問題而產生結果是這樣的,明顯是label先被擠出去,因為label標籤後被打包

from tkinter import *

def greeting():
    print('Hello stdout world!...')

win = Frame()
win.pack(expand=YES,fill=BOTH)
Label(win, text='Hello container world').pack(side=TOP)#side選項使該標籤位於頂部
Button(win, text='Hello', command=greeting).pack()
win.mainloop()

可以看到視窗縮小時由於裁切問題而產生結果是這樣的,因為Button標籤後被打包。

***因此:打包順序將對剪下結果產生影響***

打包幾何管理器的各個選項細節

  • side:決定獲得剩餘空間的某一側(可選LEFT,RIGHT,TOP,BOTTOM),預設為TOP;
  • expand:拓衝分配所得空間(可選NO,YES),預設為NO;
  • fill:填充分配所得空間(可選Y,X,BOTH),預設為None;
  • anchor:定位元件在分配所得空間中的位置(預設為CENTER;可選N,S,W,E,NW,NE,SW,SE),預設為CENTER。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com