GridBagLayout格線包布局管理器
格線包布局管理是最複雜和靈活的布局管理,在下面偶會作詳細的介紹。
與格線布局管理器不同的是,格線包布局管理器允許容器中各個組件的大小各不相同,還允許組件跨越多個格線,也允許組件之間相互部分重疊。
格線包布局理解為格線單元布局更合理,因為一個容器被劃分為若干個格線單元,而每個組件放置在一個或多個格線單元中。
要注意的是,格線包布局不能指定一個容器的格線單元的大小其格線單元的劃分是通過weightx和weighty參數來設定的,但也不是直接指定其格線單元的大小。當把一個組件放置在格線單元中時,組件所占據的位置和大小是由一組與他們相關聯的約束來決定的。這些約束是由GridBagConstraints類型的對象來設定的,關於GridBagConstraints類型,後面會做專門的介紹。
使用格線包布局的一般步驟
1、創建一個GridBagLayout格線包布局對象,並使其成為當前容器的布局管理器。
2、創建一個GridBagConstraints類型的約束對象,然後使用該對象設定各種約束條件,注意這裡設定的約束條件並沒有針對某一組件,要使某一組件具有設定的約束,需要使用第3步驟的方法。
3、然後使用GridBagLayout格線包布局中的setConstraints(Component com, GridBagConstraints cons)方法將GridBagConstraints類型對象設定的約束添加到被設定的組件中,這樣該組件就具有了GridBagConstraints設定的約束。其中setConstraints()的第一個參數是將要添加的組件,第二個參數是GridBagConstraints類型的約束對象。
4、最後將設定了約束的組件添加到容器中。
使用格線包布局的第二種方法
1、使GridBagLayout布局成為當前容器的布局管理器,這裡也可以不用創建GridBagLayout對象。
2、創建一個GridBagConstraints類型的約束對象,然後使用該對象設定約束條件。注意這裡設定的約束條件並沒有針對某一組件,要使某一組件具有設定的約束,需要使用第3步驟的方法。
3、然後使用add(Component com, Object cons)方法將組件和約束同時添加進容器中,這樣添加進容器的組件就具有了第2步的約束。注意其中的add(Component com, Object cons);第一個參數是將要添加的組件,第二個參數是要添加的GridBagConstraints類型的約束對象。
GridBagConstraints類型的約束參數:
double weightx和double weighty參數(默認值為0)
這是兩個非常重要的參數,該參數直接影響到怎樣設定格線單元的大小,因此常握好該參數就可以對格線包布局套用自如。
該參數對x方向和y方向指定一個加權值。這個加權值直接影響到格線單元的大小,比如weightx的值分別為10,20,30,則在容器的x方向也就是列的方向,按一定的比例(比如1:2:3其具體算法請參看java檔案)分配三個格線單元,其中加權值越大格線單元就越大,可以看出值的大小是沒有關係的,加權值的作用是讓容器以設定的值的比例在橫向和縱向分配格線,且在容器的大小改變時這個比例不改變。
如果weightx只設定了一個值,而組件卻不只一個以上,則被設定了的這個組件的格線單元的大小為容器在x方向的大小減去那兩個組件的最小尺寸就是該組件的格線單元大小。默認情況下組件的最小尺寸是比較小的。
如果兩個參數都為0(默認值),則組件會被顯示在容器的中央,不管容器是放大還是縮小組件都只會顯示在容器的中央。
由上所述,在使用格線包布局時首先應先使用weightx和weighty來劃分格線單元(不是直接劃分,而是按一定比例來劃分),格線單元劃分出來後,組件放置在格線單元中的位置和大小就由後面介紹的約束來決定。
一定要注意的是設定權值後要使當前的設定生效應使用setConstraints()函式一次,如果連續設定多個同一方向的權值,則只有最後一次設定的權值有效,比如出現同時兩行都設定了x方向的權值,則以最後一行設定的x方向的權值為標準來劃分格線單元。
因此在使用GridBagLayout格線包布局管理器之前應先設定好格線單元,即要把容器劃分為幾行幾列的格線單元,每行每列在容器中的寬度和高度比例,每個組件應在哪個格線單元。
int fill 參數( 默認值為GridBagConstraints.NONE)
fill參數指定組件填充格線的方式,當某組件的格線單元大於組件的大小時被使用,一般情況下組件是以最小的方式被顯示的,如果不使用fill參數,則有可能組件占不完整個格線單元,也就是說組件占據的空間比劃分的格線單元小,這時組件將顯示在格線單元中的某個位置(具體在什麼位置由格線包中的參數來設定)。其可取的值如下:
GridBagConstraints.NONE默認值,不改變組件的大小。
GridBagConstraints.HORIZONTAL使組件足夠大,以填充其格線單元的水平方向,但不改變高度,其值等於整數2。
GridBagConstraints.VERTICAL使組件足夠大,以填充其格線單元的垂直方向,但不改變寬度,其值等於整數3。
GridBagConstraints.BOTH使組件足夠大,以填充其整個格線單元,其值等於整數1。
int gridwidth 和int gridheight 參數( 默認值為1)
該參數指定組件占據多少個格線單元,gridwidth指定組件占據多少個格線單元的寬度,gridheight指定組件占據多少個格線單元的高度。兩個參數的默認值都為1。其中值GridBagConstraints.REMAINDER表示當前組件在其行或列上為最後一個組件,也就是說如果是行上的最後一個組件的話,那么下一個組件將會被添加到容器中的下一行,如果在行上不指定該值(同時也不指定gridx和gridy參數),那么無論添加多少個組件都是在同一行上,同樣如果在列上不指定該值(同時也不指定gridx和gridy參數)則無論添加多少行組件,都無法把容器填滿。值GridBagConstraints.RELATIVE表示當前組件在其行或列上為倒數第二個組件。
示例:
import java.awt.*;
public class Program
{public static void main(String[] args)
{ Frame ff = new Frame();
GridBagLayout gr = new GridBagLayout();
GridBagConstraints gc = new GridBagConstraints(); //創建一個名為gc的約束對象
ff.setLayout(gr); //將容器ff的布局設為GridBagLayout
//創建一組按鈕組件
Button bb1 = new Button("bb1"); Button bb2 = new Button("bb2"); Button bb3 = new Button("bb3");
Button bb4 = new Button("bb4"); Button bb5 = new Button("bb5"); Button bb6 = new Button("bb6");
Button bb7 = new Button("bb7"); Button bb8 = new Button("bb8");
gc.fill = GridBagConstraints.BOTH;//設定約束的fill參數,該參數表示當組件的大小小於格線單元的大小時在水平和垂直方向都填充,
gc.weightx =11; //設定x方向的加權值為11。
gc.weighty = 11;//設定y方向的加權值為11。
gr.setConstraints(bb1, gc); //將以上gc所設定的約束套用到按鈕組件bb1
gc.weightx = 22;//設定x方向的加權值為22,如果不設定weightx則以下的組件都將自動套用上面所設定的weightx值11。
gr.setConstraints(bb2, gc); //將以上所設定的約束套用到按鈕組件bb2。
//gc.weighty=111; //注意如果不注釋掉該行,則以後使用gc約束的按鈕組件在y方向的加權值將為111,而在前面設定的y方向的加權值11將失去作用。
gc.weightx =33;
gc.gridwidth = GridBagConstraints.REMAINDER;//設定gridwidth參數的值為REMAINDER這樣在後面使用該約束的組件將是該行的最後一個組件。
gr.setConstraints(bb3, gc); //第一行添加了三個按鈕組件bb1,bb2,bb3,且這3個按鈕的寬度按weightx設定的值11,22,33按比例設定寬度
GridBagConstraints gc1 = new GridBagConstraints();//創建第二個約束gc1
gc1.fill = GridBagConstraints.BOTH;
gc1.weighty = 22; //將第2行的y方向加權值設為22
gr.setConstraints(bb4, gc1);
gr.setConstraints(bb5, gc1);
gc1.gridwidth = GridBagConstraints.REMAINDER;
gr.setConstraints(bb6, gc1); //第二行添加了三個按鈕組件bb4,bb5,bb6
gc1.weighty =33;
gc1.gridwidth = GridBagConstraints.REMAINDER;
gr.setConstraints(bb7, gc1);//第三行添加了一個按鈕組件bb7
gc1.weighty=0;
gr.setConstraints(bb8, gc1); //第四行添加了一個按鈕組件bb8,bb8並沒有添加到bb7的後面,因為bb8使用了bb7前面的gridwidth參數設定的值,所以bb8也是單獨的一行。
ff.setSize(500, 300);
ff.add(bb1); ff.add(bb2);ff.add(bb3); ff.add(bb4); ff.add(bb5); ff.add(bb6); ff.add(bb7); ff.add(bb8);
ff.setVisible(true);} }
運行結果見下圖
int gridx 和int gridy 參數( 默認值為GridBagConstraints.RELATIVE)
該參數表示組件被添加到容器中的X或者Y坐標處,坐標以格線單元為單位,也就是說不管格線單元有多大,一個格線單元就是1X1的大小,也就是說如果把gridx和gridy都設為1,那么該組件會被顯示到第二行的行二列上。其中值GridBagConstraints.RELATIVE(默認值)表示當前組件緊跟在上一個組件的後面。
int ipadx 和int ipady 參數( 默認值為0)
ipadx和ipady也被稱為內部填充,該參數用以設定組件的最小尺寸,如果參數值為正值則組件的最小尺寸將比原始最小尺寸大,如果為負值,則組件的最小尺寸將會變得比原始的最小尺寸小。該參數也可以理解為直接為組件指定大小,這個設定的大小就是組件的最小尺寸。其設定後組件的大小為組件的原始最小尺寸加上ipadx*2個像素。
int anchor 參數( 默認值為GridBagConstraints.CENTER)
該參數指定當組件的大小小於格線單元時,組件在格線單元中的位置。一般情況下,在設定了weightx或者weighty的加權值時,如果不使用fill參數填充空白區域,則組件的大小將小於格線單元的大小,這時使用anchor參數就能看到其中的效果了。anchor參數可取的值有:GridBagConstraints.CENTER;GridBagConstraints.NORTH;GridBagConstraints.NORTHEAST;GridBagConstraints.EAST;GridBagConstraints.SOUTHEAST;GridBagConstraints.SOUTH;GridBagConstraints.SOUTHWEST;GridBagConstraints.WEST;GridBagConstraints.NORTHWEST;即居中,北,東北,東,東南,南,西南,西,西北方向。
Insets insets 參數( 默認值為0)
insets參數也被稱為外部填充,該參數指定組件與格線單元之間的最小空白區域大小,要注意的是即使使用了fill參數填充橫向和縱向但只要設定了insets參數,同樣會留出insets所設定的空白區域,在insets設定的空白區域不會被填充。在使用該參數時需要設定對象的top,left,right,bottom四個方向的值來調整組件與格線單元之間的空白區域大小,比如gc.insets=new Insets(10,10,10,10);其中gc是GridBagConstraints類型的約束對象,這裡要注意後面的new Insets其中的Insets第一個字母是大寫的。當然也可以為insets指定負值,以擴大其格線單元。
示例:
import java.awt.*;
public class Program
{public static void main(String[] args)
{//將容器ff的布局設為GridBagLayout
Frame ff = new Frame();
GridBagLayout gr = new GridBagLayout();
GridBagConstraints gc = new GridBagConstraints(); //創建一個名為gc的約束對象
ff.setLayout(gr);
//創建一組按鈕組件
Button bb1 = new Button("bb1"); Button bb2 = new Button("bb2"); Button bb3 = new Button("bb3");
Button bb4 = new Button("bb4"); Button bb5 = new Button("bb5"); Button bb6 = new Button("bb6");
Button bb7 = new Button("bb7"); Button bb8 = new Button("bb8");
gc.fill = GridBagConstraints.BOTH;
gc.weightx = 11; gc.weighty = 11;
gr.setConstraints(bb1, gc);
gc.weightx = 22;
gc.gridx = 1; gc.gridy = 1; //將下一個組件放置在坐標為1,1的位置。
gr.setConstraints(bb2, gc);
gc.weightx = 33;
gc.gridx = 2; gc.gridy = 1; //將下一個組件放置在坐標為2,1的位置。
gc.insets = new Insets(-10, -10, -10, -10); //將下一個組件與格線單元的空白區域向外擴展10個像素,在這裡可以看到格線包布局允許組件之間重疊。
gc.gridwidth = GridBagConstraints.REMAINDER;
gr.setConstraints(bb3, gc);
GridBagConstraints gc1 = new GridBagConstraints();
gc1.weighty = 22;
gc1.ipadx = 50; gc1.ipady = 50; //將組件的最小尺寸加大ipadx*2個像素。
gr.setConstraints(bb4, gc1);
gc1.ipadx = 0;
gc1.ipady = 0; //將以後的組件的最小尺寸設定為默認值,如果省掉該行,則以後組件的最小尺寸都會加大ipadx*2個像素。
gc1.anchor = GridBagConstraints.NORTHWEST; //將下一個組件bb5的位置放置在單元格線的西北方向。
gr.setConstraints(bb5, gc1); //因為bb5未設定fill,同時bb5設定了weightx(由gc參數設定)和weighty兩個值以確定bb5所在的格線單元的大小,因而組件bb5的原始最小尺寸無法占據整個格線單元。
gc1.fill = GridBagConstraints.BOTH;
gc1.gridwidth = GridBagConstraints.REMAINDER;
gr.setConstraints(bb6, gc1);
gc1.weighty = 33;
gc1.insets = new Insets(5, 15,40,150); //使下一個組件bb7與格線單元之間在上,左,下,右,分別保持5,15,40,150個像素的空白位置。
gr.setConstraints(bb7, gc1);
gc1.weighty = 0;
gc1.insets = new Insets(0, 0, 0, 0); //將insets的參數值設為默認值。
gr.setConstraints(bb8, gc1);
ff.setSize(500, 300);
ff.add(bb1); ff.add(bb2); ff.add(bb3); ff.add(bb4); ff.add(bb5); ff.add(bb6); ff.add(bb7); ff.add(bb8);
ff.setVisible(true);}}