一般來說除了menu(功能表)之外,使用Tk來製作視窗元件都需要經過兩個步驟:第一步是使用button、label之類的命令先建立視窗元件,然後再使用像pack、grid之類幾合管理命令把新建立的視窗元件排放在視窗上。這一篇文件主要在說明Tk的三個幾合管理命令,只要弄懂它們就可以自由的排放出各種視窗元件的佈局了。
16.1 place
place命令可以說是最直覺的幾合管理命令,因為它在排放視窗元件時是採用x軸、y軸、長及寬,當作參數來排放它們。注意哦!! 位置及長寬的單位都是畫素。例如:這個例子讓.btn放在root視窗內,而且坐標是 (10,30),長寬各是100畫素。其中坐標(0,0)指的是父視窗元件的左上角。它的執行畫面如下:
圖 16-1
在上面的例子中我們使用了畫素來表示座標及長寬的絕對值。事實上place也允許你使用相對值來設定這些參數,如下面的例子:
用-rel開頭的參數表示要使用相對值來設定視窗元件,它們都是相對於父視窗元件。簡單的說就是使用百分比的意思,例如:-relwidth 0.4 就表示寬度要設定為父視窗元件的0.4倍寬。-relx 0.5就表示為x軸的坐標是父視窗元件寬度的一半。如果採用了這種相對值的方法,你會發現子視窗元件會隨者它的父視窗元件放大縮小,而且位置也會相對移動。所以這個例子執行起來像這樣:
圖 16-2
另外,Tcl也允許你混用絕對值及相對值的參數,如果是這種情況的話,place會把絕對值和相對值加起來,例如:
這樣的話.btn的寬度將會是父視窗元件的一半再加100個畫素。
接下來是一些比較不常用的參數,如果有興趣的話請自己試試
-anchor where | 這個參數可以強制視窗元件黏住父視窗元件的某一邊。where的值可以是n、ne、e、se、s、sw、w、nw, 或center。其中的n、e、w、s分別表示北、東、西、南。 |
-bordermode mode | 這個參數可以用來指定視窗元件排放時與父視窗元件邊框的關系(父視窗也許會有邊框,而邊框線也會有寬度)。如果mode指定為inside,表示坐標的(0,0)是在父視窗元件的框線內開始算。如果mode是outside,表示坐標的(0,0)是在父視窗元件的框線外開始算。最後一個模式是ignore,因為官方文件說這個參數不會用到,所以...別理它。 |
-in master | 我們知道Tk是由視窗元件的path來決定父視窗元件是誰,如果你想要打破這個規則,可以使用這個參數來強制指定master作為父視窗元件。 |
如果你排放完視窗元件後想要改變它們的設定值,可以使用place configure命令。例如,下面的程式每按一下Move按鈕它就會自己向右移10畫素。我們使用全域變數::x來存儲按鈕目前的x軸座標,然後每按下一次按鈕就把::x加上10。特別注意到程式的第4行,我們用place configure來重新設定按鈕的-x參數讓按鈕的x座標會反應::x的現在值。另外place configure可以一次指定多個參數,Tk並沒有限定你一次只能更變一個值。
接下來我們要看看怎麼樣把已經排放出來的視窗元件給拿下來。請看下面的例子,當我們按下forget按鈕,place forget就會把已經排放在畫面上的視窗元件拿下來,也就是變為還沒排放的狀態。當然想要重新排放只要再執行place一次命令就可以了。
最後再介紹一個比較有機會用到的功能。place slaves可以用來取得某個父視窗元件內包含了哪些的子視窗元件。例如下面的例子,會以清單的方式印出root視窗元件內的子項目。
16.2 pack
pack提供了由上到下、由下到上、由左至右、由右至左的排放功能。依個人的使用經驗,它比place更常使用,更順手,所以請儘可能熟悉它吧!! 好我們來看第一個例子。在上面的例子裡,我們透過pack的-side選項來指定btn1~btn3要由「左至右」排放。-side的值除了left之外,你還可以指定為right由「右至左」、top由「上至下」、 bottom由「下至上」來排放視窗元件。這個例子的執行畫面如下:
圖 16-3
如果把-side指定為top的話,執行起來會變成這樣子,btn1~btn3由上至下的排放:
圖 16-4
請你再執行一次上面的例子,然後試著拉大和縮小root視窗,你應該會發現一件事:btn1~btn3並不會跟著root視窗改變大小。如果你想要讓btn1~btn3其中一個或它們的全部都跟著root視窗縮放,那你就需要使用-expand及-fill的選項了。-expand可以用來設定視窗元件是否要佔滿父視窗元件的「剩餘空間」,-fill可以用來指定視窗元件本身是否要填滿剩餘空間。那什麼是剩餘空間? 簡單的說就是沒有被視窗元件佔用的空間。我們用下面的例子來說明-expand的用途:
這個例子我們只先設定了-expand,看看排放起來會有什麼效果。-expand設定為1表示要佔滿剩餘空間,設定為0表示不要佔滿。圖16-5是把-expand設定為0的執行畫面,圖16-6是把-expand設定為1的執行畫面,你應該會發現剩餘空間被平均分給btn1~btn3了。
圖 16-5 把-expand設為0
圖 16-6 把-expand設為1
如果你想要只讓btn1~btn3其中之一佔滿剩餘空間,那就要把pack命令拆成3行來寫了,像下面的程式,只讓btn2佔滿剩餘空間。所以btn1及btn3被推到邊邊了。
執行畫面如下:
圖 16-7 把-expand設為1
剩餘空間的觀念在後面的pack及grid命令也會用到,請一定要清礎它的觀念。接下來我們要指定-fill選項了,指定它的話可以讓視窗元件的本身填滿剩餘空間。請看下面的例子:
注意程式的第5~6行。-fill可以指定的值有none、x、y及both。指定none表示不要填補,指定x表示要填滿x軸,指定y表示要填滿y軸,指定both表示要x及y軸要同時填滿。所以執行起來會變這樣:btn2把xy兩軸都填滿了,btn3只填滿了y軸,而btn1因為沒有指定-fill所以沒有填任一軸:
圖 16-8 指定-fill選項
再來看一個比較有感覺的例子:
這次我們把btn1~btn3都加上了-expand的選項,所以它們會均分剩餘空間。這樣-fill的效果就更容易看出來了。btn1指定了-fill x所以它槙滿了x軸,btn2指定了-fill both所以它的xy軸都填滿了,最後btn3指定了-fill y所以填滿了y軸。
圖 16-9
以下是pack命令可以接受的其它選項,它們都很容易了解有興趣的話請自己試試。
-after other | -after選項用來指定視窗元件要排放在other之後。 |
-anchor anchor | -anchor選項用來指定視窗元件要對齊剩餘空間的哪一個方位。請參考place的-anchor選項。 |
-before other | -before選項用來指定視窗元件要排放在other之前。 |
-in master | 我們知道Tk是由視窗元件的path來決定父視窗元件是誰,如果你想要打破這個規則,可以使用這個參數來強制指定master作為父視窗元件。 |
-ipadx amount | 這個選項可以讓你在「剩餘空間」及「視窗元件」之間(左邊及右邊)加入大小amount的空間。這樣用-fill x的時候就不會把整x個軸填滿。單位是畫素。 |
-ipady amount | 這個選項可以讓你在「剩餘空間」及「視窗元件」之間(上面及下面)加入大小amount的空間。這樣用-fill y的時候就不會把整y個軸填滿。單位是畫素。 |
-padx amount | 這個選項可以讓你在「剩餘空間」及「剩餘空間」之間(左邊及右邊)加入大小amount的空間。單位是畫素。 |
-pady amount | 這個選項可以讓你在「剩餘空間」及「剩餘空間」之間(上面及下面)加入大小amount的空間。單位是畫素。 |
pack命令也跟place一樣可以用pack configure來重新設定選項值,可以用pack forget把已經排放出來的視窗元件拿下來,或是用pack slaves來取得某個父視窗元件內的子項目。詳細的用法請參考上一小節的place命令。
16.3 grid
grid命令可以說是Tk裡功能最強的幾合管理命令,這意謂著...我們要學比較多的東西。 事實上grid是我用最多的幾合管理命令,因為它的功能實在是好用,而且很容易就可以把視窗元件排得整整齊齊的,非常的建議把它用熟。grid的主要觀念是,父視窗元件上畫有水平和垂直的虛擬格線,這些格線組成很多的小格子,然後我們可以把視窗元件放在這些格子裡。例如我們要產生一個填資料的表單:請注意程式的7~9行,我們用3個grid命令排出了3列,而且每一列有2行,所以它執行起來像這樣子:
圖 16-10
當然我們也可以排成3x2的樣子,像這樣:
執行起來就變成這樣:
圖 16-11
如果你不想要像上面那樣一個grid命令排好多個視窗元件,你也可以用下面的法方一次排一個視窗元件就好。
一次排一個視窗元件的方法,必需要自己指定-row(第幾列)及-column(第幾行)來設定視窗元件被排放的位置。如果沒有指定的話每一個視窗元件都會被當成一列。下面是可能會用到一次排一個視窗元件的時機。我們用程式來製作一個3x3乘法表,程式執行時像下面的圖一樣,使用者每按一下畫面上的按鈕就會輸出計算的結果:
圖 16-12
它的程式碼如下:
這個程式使用了2個foreach迴圈來產生9個按鈕,而且我故意不由第0行第0列開始放,反正不會影響到外觀,就別在意吧!!。請注意到第4行,以前我們都是使用大括號來包含-command後面的程式,在這邊這樣是行不通的,原因是-command後面的程式被執行時,Tcl會把那些程式當成是在「::」頂層的名稱空間下執行。所以在這樣的情況下Tcl會找不到$row及$col變數。一個決解的方法就是像我一樣使用「雙引號包夾」這樣$row及$col的值在執行button命令時就會先被代換出來了,因為值被直接代換出來了,所以就不用擔心在頂層名稱空間會找不到$row及$col了。另一個更好的方法是像下面一樣用list命令,事實上我都是用下面的方法比較多。
以下是grid可以接受的其它選項:
-columnspan n | 一般情況每個視窗元件只會佔用一行一列,指定這個選項可以讓視窗元件佔用n行。 |
-rowspan n | 一般情況每個視窗元件只會佔用一行一列,指定這個選項可以讓視窗元件佔用n列。 |
-sticky style | 這個選項可以用來指定視窗元件要黏住剩餘空間的那一邊,style可以由n、e、w、s等4個方位任意組成。如果指定為ns它的效果就像pack的-fill y一樣,如果指定為we效果就像pack的-fill x一樣。如果指定為news效果就像pack的-fill both一樣。 |
-in master | 我們知道Tk是由視窗元件的path來決定父視窗元件是誰,如果你想要打破這個規則,可以使用這個參數來強制指定master作為父視窗元件。 |
-ipadx amount | 這個選項可以讓你在「剩餘空間」及「視窗元件」之間(左邊及右邊)加入大小amount的空間。單位是畫素。 |
-ipady amount | 這個選項可以讓你在「剩餘空間」及「視窗元件」之間(上面及下面)加入大小amount的空間。單位是畫素。 |
-padx amount | 這個選項可以讓你在「剩餘空間」及「剩餘空間」之間(左邊及右邊)加入大小amount的空間。單位是畫素。 |
-pady amount | 這個選項可以讓你在「剩餘空間」及「剩餘空間」之間(上面及下面)加入大小amount的空間。單位是畫素。 |
之前看到的pack命令可以用-expand來決定哪些視窗元件要佔滿剩餘空間。但,從上面的列表你應該有發現grid裡並沒這樣的選項。沒錯!! grid要用另外的方法來設定,像下面的語法一樣,grid可以一次設定排在某一行的視窗元件都要佔滿剩餘空間。
grid columnconfigure master index -weight 1
其中master是父視窗元件的path,而index是要佔滿剩餘空間的第n行,n必需由0開始算。當然,我們也可以設定某一列都要佔滿剩餘空間:
grid rowconfigure master index -weight 1
下面的例子改寫自上面的3x3乘法表,我們透過columnconfigure及rowconfigure來把位於第2行及第2列的視窗元件都佔滿剩餘空間。
注意哦!! 程式的第4行我幫每一個grid的命令都加上了-sticky news的選項。所以它執行起來像這樣,位於第2行第2列的視窗元件都會跟著放大縮小。
圖 16-13
grid命令也跟place及pack一樣可以用grid configure來重新設定選項值,可以用grid forget把已經排放出來的視窗元件拿下來,或是用grid slaves來取得某個父視窗元件內的子項目。詳細的用法請參考之前的place命令。其它grid還有一些比較少用到的功能,如果你有興想要學深入一點的話,請自行參考Tcl/Tk的官方手冊吧。
★ 最後提醒一點:請不要在某一個父視窗下混用兩種以上的幾合管理命令,不然程式視窗元件可能會顯示不出來哦!!
按右上方的「#」號切換側邊欄