〔轉貼〕Java入門(10) 佈局管理--from LinuxAid網站

Java入門(10) 佈局管理

原創 02-01-18 09:23 5769p fjxufeng



本章目標:
    在第9章中,我們學習了許多用來構建GUI程序的部件,不過到現在爲止,我們還無法讓其“聽話”的按照我們的意圖擺放這些部件。在本章中,我們要學習如何進行部件的佈局,也就是讓部件能夠“聽話”地擺放在我們想放的位置上。我們將學會通過邊框、網格、組合和GridBagLayout四種方式進行部件的佈局管理。

10.1 邊框佈局
    傳授新知


    我們回顧一下在第9章中,我們在程序中總是使用以下兩條語句定義了一個容器:
        JPanel panel1=(JPanel)getContentPane();
        panel1.setLayout(new FlowLayout());
    憑着我們現在所積累的閱讀程序的功夫,應該能夠很快地知道我們通過第一條語句創建了一個容器JPanel類的panel1。
    而接下來,我們則調用了panel1.setLayout(new FlowLayout()),在上一章中,我們一直沒有對它進行相應的分析。現在該是揭開它的面紗的時候了。
    單詞layout的中文意思是“佈局”、“佈置”,setLayout就是設置佈局格式。也就是說,容器panel1的方法setLayout是用來設置佈局格式的。那麼,我們一直用的是什麼模式呢?對,就是後面括號裏的FlowLayout()。顧名思義,也就是流佈局方式。這是一種順其自然的方式:從左到右,一個個對象地擺放,擺不下,就擺到下一行。所以,我們就無法去控制它。
    從本章開始,我們就要學習一種控制佈局的方法。在Java語言中,提供了各種佈局管理器,以便大家能夠達到這一目的。
    通常我們最常使用的佈局管理器是:Border Layout(邊框佈局管理器),如下圖所示,邊框佈局管理器將一個屏幕分成了五個部分:東、南、西、北、中。

10-1.jpg
圖10-1 邊框佈局管理示意圖

    如果要使用這種邊框佈局管理進行佈局控制,我們必須先將“容器”設置爲“邊框佈局控制模式”,具體來說,就是當調用setLayout方法爲容器設置佈局控制模式時,參數設置爲BorderLayout。例如:
        JPanel panel1=(JPanel)getContentPane();
        panel1.setLayout(new BorderLayout());
    然後,我們就可以在使用容器的add方法添加部件時,附加上位置參數,使得該部件顯示在指定的位置上。位置參數分別是:
       BorderLayout.NORTH 位置爲北
       BorderLayout.SOUTH 位置爲南
       BorderLayout.EAST 位置爲東
       BorderLayout.WEST 位置爲西
       BorderLayout.NORTH 位置爲中心


   實例說明

    下面,我們就來試一試,使用按鈕排出五個方向!請創建一個testBorder.java,輸入以下源程序:
      源程序:useTextArea.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class testBorder extends JApplet
{
  public void init()
  {
   JPanel panel1=(JPanel)getContentPane();
   panel1.setLayout(new BorderLayout());
   
   JButton north=new JButton("North");
   JButton south=new JButton("South");
   JButton east=new JButton("East");
   JButton west=new JButton("West");
   JButton center=new JButton("Center");

   panel1.add(north,BorderLayout.NORTH);
   panel1.add(south,BorderLayout.SOUTH);
panel1.add(east,BorderLayout.EAST);
   panel1.add(west,BorderLayout.WEST);
   panel1.add(center,BorderLayout.CENTER);
  }
}

    然後,我們使用javac編譯這個程序,然後編輯一個顯示這個Java Applet的HTML頁面。最後調用appletviewer來觀察這個頁面,如下圖所示:

10-2.jpg
     圖10-2 程序testBorder.java的輸出(1)

10-3.jpg
      圖10-3 程序testBorder.java的輸入(2)

    爲了試一下,如果並沒有在每個位置都安排一個部件,那麼會怎麼樣呢?我們修改一下程序,將panel1.add(west,BorderLayout.WEST);這一行註釋掉(就是在前面加上“//”號),也就是不顯示西邊的按鈕,看一下結果如何。正如上圖(圖10-3)所示,西邊由於沒有部件,因此“中”就朝西靠,“佔領”了它的位置。
    而同樣的,如果沒有了南邊北邊,正如下圖(10-4)所示,其它部件就會佔領其位置:

10-4.jpg
     圖10-4 程序testBorder.java的輸出(3)

10-5.jpg
      圖10-5 程序testBorder.java的輸入(4)

    而如果我們修改一下程序,讓中間的按鈕不顯示的話,就會出現如圖10-5的樣子,中間的區域並未並佔領,而是空在那裏了!這是與其它位置不同的地方,大家一定要記住。

    一些提示:
    其實這很好理解,如果中間的那一塊的位置被其它位置上的部件佔領的話,就會使得分不清“東”、“南”、“西”、“北”了。倒成了“左上角”、“左下角”、“右上角”、“右下角”了。


    自測練習
    1) 使用____________位置參數,能夠使一個部件位於容器的頂部。
      a. Layout.TOP b. BorderLayout.TOP
      c. Layout.NORTH d. BorderLayout.NORTH
    2) 使用____________位置參數,能夠使一個部件位於容器的右邊。
      a. BorderLayout.WEST b. BorderLayout.RIGHT
      c. BorderLayout.EAST d. BorderLayout.NORTH
    3) 如果在東面沒有放置部件,其它位置都有放置部件,那麼中間的部件將靠向______。
      a.左邊 b.上面 c.右邊 d.下面
    4) 在第9章中,我們使用的佈局管理器是_____________。
      a.雜亂管理器 b.流管理器
      c.沒有使用佈局管理器 d.順序佈局管理器
    5) 邊框佈局管理器將一個“容器”分成了__________個位置。
      a.9個 b.3個 c.4個 d.5個
    6) 編寫一個程序,使其界面如下圖:

10-6.jpg
圖10-6 練習題圖(1)

    而且,當我們擴大這個窗體的寬度時,OK按鈕並不會出現在文本框之後,而是產生如下圖之輸出結果:

10-7.jpg
圖10-7 練習題圖(2)


    練習答案

    1)d 在邊框佈局管理器中,頂部是北,所以選擇BorderLayout.NORTH。
    2)c 在邊框佈局管理器中,右邊是東,所以選擇BorderLayout.EAST。
    3)c 東在右邊,所以東邊沒有部件,其它部件就擠向右邊,佔領了右邊。
    4)b 雖然a、d從字面意義上特別象我們得到的結果,而c則從感覺上比較象,但這些都不是正確答案。這種佈局管理器稱爲流管理器。
    5)d 當然是“東”、“西”、“南”、“北”、“中”5個部分了!
    6) 以下是一個程序實例:

      源程序:lianxi10_1.java

import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class lianxi10_1 extends JApplet
{
  Label comment;
  JTextField username;
  JButton buttonOK;

  public void init()
  {
   JPanel panel1=(JPanel)getContentPane();
   panel1.setLayout(new BorderLayout());
 
   comment=new Label("Please enter you name:");
   username=new JTextField();
   buttonOK=new JButton("OK");

   panel1.add(comment,BorderLayout.NORTH);
   panel1.add(username,BorderLayout.CENTER);
   panel1.add(buttonOK,BorderLayout.SOUTH);
  }

}


10.2 網格佈局
   實例說明

  
    下面,我們來看一個新的程序!首先創建一個testGrid.java文件,並輸入以下源程序:
      源程序:testGrid.java

import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class testGrid extends JApplet
{
  String buttonLabels[]={"No.1","No.2","No.3","No.4","No.5",
        "No.6","No.7","No.8","No.9"};

  public void init()
  {
   JPanel panel1=(JPanel)getContentPane();
   panel1.setLayout(new GridLayout(3,3));
   
   for (int x=0; x<buttonLabels.length;x++)
       panel1.add(new JButton(buttonLabels[x]));
   }
}

    然後,我們使用javac編譯這個程序,然後編輯一個顯示這個Java Applet的HTML頁面。最後調用appletviewer來觀察這個頁面,如下圖所示:

10-8.jpg
圖10-8 程序testGrid.java的輸出


   傳授新知

    由於在本章中,我們主要是關心如何擺放各個部件,而不是如何構建一個程序。所以,正如本例中的按鈕一下,這一章中的所有部件都是一個樣子,沒有任何作用。這樣也使得程序儘可能地變短了,更易於大家閱讀和理解程序。
下面,我們就一起來看一下上面的這個程序。
    1) String buttonLabels[]={"No.1","No.2","No.3","No.4","No.5",
        "No.6","No.7","No.8","No.9"}
    我想大家都能很輕鬆地讀懂這條語句,我們在此定義了一個字符串數組buttonLabels,它有9個字符串成員,也就是我們後面定義的9個按鈕的標籤文本。
    值得注意的是,大家一定要知道,buttonLabels[1]表示哪個字符串!如果您的答案是“No.1”的話,就錯了!正確的答案是“No.2”,這是因爲在數組中索引值是從0開始的,也就是說如果要使用“No.1”的話,應該使用buttonLabels[0]。這對更好地理解後面的程序十分重要,也是基本功之一。
    2) JPanel panel1=(JPanel)getContentPane();
        panel1.setLayout(new GridLayout(3,3));
    在這兩行程序中,我們首先定義了一個容器部件panel1。然後調用setLayout方法設置佈局管理器。這裏我們使用了一個新的佈局管理器:GridLayout,網格佈局管理器。
    我們注意到GridLayout的後面帶了兩個參數:3,3。這有什麼用呢?我們一起來看一下GridLayout方法的定義:
       public GridLayout (int rows,int cols)
    我們看一下這兩個參數,首先它們都是int型—整型的。那麼它們分別起到什麼作用呢?我們還是採用顧名思義法吧!row的中文意思是行,col的中文意思是列,後面加上一個s,是這兩個單詞的複數形式。
    好,我們現在串起來想一下,我們定義了一個網格佈局,然後定了它的行、列數!這不就畫出了這個網格了嗎?如果我們在語句是使用GridLayout(5,5)的話,就會把整個容器分成25個單元,如下圖所示:

10-9.jpg
        圖10-9 GridLayout(5,5)

10-10.jpg
        圖10-10 GridLayout(3,3)

    而我們在程序中使用的是GridLayout(3,3),所以它就將整個容器分成了如上圖所示的9個部分(圖10-10)。

    注意:
    這種劃分是一種邏輯上的,暗藏式的劃分,而不會把格子給劃出來。另外,我們這裏舉的兩個例子行、列都相等,其實完全可以不等。

    3) for (int x=0; x<buttonLabels.length;x++)
       panel1.add(new JButton(buttonLabels[x]));
    這是一個循環結構的程序。我們先看循環語句,循環的初值是“x=0”,繼續執行循環的條件語句是“x<buttonLabels.length”,每做一次循環,執行“x++”。
    buttonLabels.length就是用來請得字符串數組buttonLabels的長度!也就是這個字符串數組中有多少個字符串?我們知道,我們在該數組中定義了9個。
從程序中,我們可以獲知,當x=buttonLabels.length時,循環就將結束,應爲它不滿足條件x<buttonLabels.length。那不是少了一個嘛!
    別忘了,我們使用buttonLabels[0]表示第一個字符串,buttonLabels[1]表示第二個字符串……,那麼最後一個字符串就應該是buttonLabels[buttonLabels.length-1]嘛。
    在循環中,我們使用容器提供的add方法,將新定義的按鈕部件添加進去。
    有時,我們可能想獲得象下圖所示的佈局效果!讓各個部件之間存在一些間隙。使用Java的網格佈局可以實現嗎?

10-11.jpg
圖10-11 有間隙的網格佈局

    我很高興地回答你:“可以!”,我們可以使用GridLayout的另一種構造器方法(簽名不同)來實現:
       public GridLayout (int rows,int cols,int hgap,int vgap)
    在這個方法中,可以帶上四個整型參數,前兩個我們已經很熟悉了,行數與列數。後面則是兩個新的參數。
    第一個是hgap,其中gap的意思是間隙、空隙的意思,而h則是horizontal(水平)的第一個字母。也就是說,我們可以通過hgap參數設置橫向的間隙。
第二個是vgap,v則是vertical(垂直)的第一個字母。也就是說,我們可以通過vgap參數設置縱向的間隙。


    自測練習

    1)_________________是網格佈局管理器。
      a.BorderLayout b.GridLayout c.ReseauLayout
      d.FlowLayout
    利用以下代碼回答問題2、3、4、5:
    2)這個佈局中有__________行?
      a.7行 b.5行 c.6行 d.8行
    3)這個佈局中有__________列?
      a.7行 b.5行 c.6行 d.8行
    4)這個佈局將容器分爲_________個部分?
      a.48個 b.35個 c.30個 d.40個
    5)第5個部件位於__________位置。
      a.左上角 b.左下角 c.右上角 d.右下角 e.中間
    6)根據以下界面,編寫一個程序

10-12.jpg
圖10-12 練習題圖
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________
    7) 如果我們構建一個5*5的網格佈局,但只在該容器中加入17個按鈕,將會出現什麼情況?請編寫一個程序,來試一試效果。
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________


    練習答案

    1)b 沒什麼好解釋的,請大家記住!
    2)a 第一個參數是行數,因此是7行。
    3)b 第二個參數是列數,因此爲5列。
    4)b 7行5列,其7*5,35個部分嘛。
    5)c 第5個部件是第一行的最後一個,當然在右上角嘛。
    6)下面是一個實現的程序實例:
      源程序:lianxi10_2.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class lianxi10_2 extends JApplet
{
  String buttonLabels[]={"1","2","3","4","5","6","7",
            "8","9","*","0","#"};

  public void init()
  {
   JPanel panel1=(JPanel)getContentPane();
   panel1.setLayout(new GridLayout(4,3,10,10));
   
   for (int x=0; x<buttonLabels.length;x++)
       panel1.add(new JButton(buttonLabels[x]));
   }
}

7)下面是一個實現的程序實例:
      源程序:lianxi10_3.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class lianxi10_3 extends JApplet
{
  
String buttonLabels[]={"No.1","No.2","No.3","No.4","No.5",
        "No.6","No.7","No.8","No.9","No.10","No.11","No.12",
        "No.13","No.14","No.15","No.16","No.17"};

  public void init()
  {
   JPanel panel1=(JPanel)getContentPane();
   panel1.setLayout(new GridLayout(5,5));
   
   for (int x=0; x<buttonLabels.length;x++)
       panel1.add(new JButton(buttonLabels[x]));
   }
}
    這個程序使用javac編譯完後,編寫一個包含這個類的HTML頁面,再用appletviewer來觀察發現運行結果如下圖所示:

10-13.jpg
圖10-13 練習答案圖

    這個輸出是不是令你感到十分意外,整個程序根本不按要求分成5列,所以我們從這裏得到一個使用網格佈局中要十二分注意的一點:“請別忘了將網格填滿”。否則程序的輸出將不可預料。

    一些提示:
    如果你真的沒有那麼多東西來“佔領”網格的話,我建議你使用一個空標籤來填補這個空白的網格,使得程序的輸出如你所願。使用空標籤的方法很容易:
           panel1.add(new Label(“”));
    從這裏,我們也看出了,我們學習過的流佈局管理器、邊框佈局管理器,以及我們剛學習過的網格佈局管理器都比較死板,不夠高級。


10.3 組合佈局
    傳授新知


    正如我們在上一小節結束的時候說的一樣,各種佈局管理器都有自己的缺點,沒有一種能夠真正地完全滿足我們編寫GUI程序時的要求。
    而在Java語言中,允許在容器中加入其他容器,這樣每個容器可以根據自己的需要採用不同的佈局管理器,組合成爲一個我們所需要的GUI程序界面。這種方法,我們就稱之爲組合佈局。

    注意:
    與流佈局、邊框佈局、網格佈局不同,組合佈局並不是一個新的佈局管理器,它是通過結合各種佈局管理器的優點,將它們組合地應用在GUI程序界面的開發中。這是一種佈局管理的方法。也可以說是一種GUI程序界面的開發技巧。
    當我們設計GUI程序界面時,最好先在紙上把它畫出來,然後“分塊解決”。也就是將能夠組合在一起的部件找出來,將它們放在一個容器裏,併爲它們選擇合適的佈局管理器。然後把這些容器擺放在一起,就解決了。
    設計時還要考慮到窗體大小發生改變的時候,引起的部件形體變化。這方面,請你熟記幾個設計技巧:
    1) 對於那些要求扁平狀的部件,我們應該將它放置在邊框佈局中的南面或北面;
    2) 對於那些要求細高狀的部件,我們應該將它放置在邊框佈局中的東面或西面;
    3) 對於那些可以隨着窗體改變大小部分,我們可以將它放置在邊框佈局的中間;
    4) 如果我們要求部件保持大小相同,那麼,我們就應該採用網格佈局。
下面,我們就通過幾個實際的例子,來讓大家領會和掌握這種設計的思路與方法。


    實例說明
    我們首先創建一個testCombination.java文件,然後輸入以下源程序:
      源程序:testCombination.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class testCombination1 extends JApplet
{
  
  public void init()
  {
 Frame frame1=new Frame("testCombination1");
   frame1.setLayout(new BorderLayout());
   TextArea text1=new TextArea();
   frame1.add(text1,BorderLayout.CENTER);
    
   JPanel panel1=(JPanel)getContentPane();
   panel1.setLayout(new GridLayout(1,3,10,5));
   panel1.add(new JButton("A"));
   panel1.add(new JButton("B"));
   panel1.add(new JButton("C"));
   frame1.add(panel1,BorderLayout.SOUTH);
   
   frame1.pack();
   frame1.show();
  }
}

    然後,我們使用javac編譯這個程序,然後編輯一個顯示這個Java Applet的HTML頁面。最後調用appletviewer來觀察這個頁面,如下圖所示:

10-14.jpg
圖10-14 程序testCombination.java的輸出

    正如上圖所示,程序的輸出與以前不同,各個部件不是顯示在Appletviewer程序框中,而是顯示在另一個窗口中。
    這是怎麼回事呢?下面我們就一起來看一下這個程序!


    傳授新知

    在以前的程序中,我們一直都是使用容器JPanel,面板。而我們在這個程序中引進了一個新的容器Frame。使用了這個容器後,就會新創建一個窗口。這也就是爲什麼程序的輸出有這麼大的變化的原因。
    1) Frame frame1=new Frame("testCombination");
    這條語句,定義了一個Frame容器frame1,然後使用new操作符調用構造器方法,後面帶的參數“testCombination”則是這個Frame的標題。

    一些提示:
    其實大家能Frame所體現出來的效果是很熟悉的,它等價於Windows中的窗體。而Frame的標題就是窗體的標題。

    2) frame1.setLayout(new BorderLayout());
    與JPanel容器一樣,我們可以調用setLayout方法來設置Frame的佈局管理器。在這裏,我們將Frame容器frame1的佈局管理器設置成爲邊框佈局管理器(也就是我們在10.1小節中學習過的佈局管理器)。
    3) frame1.add(text1,BorderLayout.CENTER);
    緊接着,我們調用frame1的add方法,將文本區部件text1添加到frame1容器中來。注意我們設置了它的位置:BorderLayout.CENTER。
    這是因爲,我們希望這個文本區能夠隨着窗體的大小變化而變化。所以適合將其放在在中間位置。
    4) panel1.setLayout(new GridLayout(1,3,10,5));
    我們又定義了一個JPanel容器panel1,並將其的佈局管理器設置爲網格佈局管理器。並通過指定參數,使得整個panel1被分成1行3列,水平空隙爲10的網格。
    5) frame1.add(panel1,BorderLayout.SOUTH);
    這是組合佈局方法最重要的一步,我們將panel1這個容器,加入到了frame1這個容器中去了。並且指定了panel1這個容器在整個frame1中所佔的位置:BorderLayout.SOUTH,也就是下邊。這樣,panel1中包含的三個按鈕就會永遠(不管窗體大小如何改變)呆在文本區的下邊,而且三個按鈕的大小會根據窗體大小的改變而改變。

    一些提示:
    這是因爲,panel1中的按鈕是用網格佈局的。
    6) frame1.pack();
        frame1.show();
    與JPanel不一樣,使用Frame容器,不能夠直接顯示了出來。我們必須調用Frame容器的show方法才能使得Frame顯示出來。
    而在使用show方法之前,我們還需要使用pack方法將Frame中的內容做一個整合。請記住這裏的使用方法。



     自測練習

    1)___________不屬於佈局管理器。
     a.邊框佈局 b.組合佈局 c.流佈局 d.網格佈局
    2)如果要使用組合佈局,需將容器的佈局管理設置爲__________。
     a.BorderLayout() b.GridLayout() c.CombinationLayout()
   d.以上都不對
   請說明理由:
   ____________________________________________________________________
    3)對於同一個容器,可以使用多種佈局管理方式?________
      a.對 b.不對
    4)對於同一種容器,可以使用多種佈局管理方式?________
      a.對 b.不對
    5) 將一個容器panel1放到容器frame1中的方法是___________。
      a.frame1.insert(panel1) b.frame1.add(panel1)
      c.frame1.addJPanel(panel1) d.frame1.insertJPanel(panel1)
    6) 編寫一個程序,模擬如下圖所示的小鍵盤:

10-15.jpg
圖10-15 練習題圖
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________


   練習答案

    1)b 組合佈局是一種將多種佈局管理器應用在一個程序中的方法,它不屬於佈局管理器。
    2)d 組合佈局是一種方法,所以無須指定佈局管理器,想指定也無法指定。
    3)b 在一個程序中,一個容器只能有一種佈局管理。
    4)a 對於同一種容器在不同的程序中,當然可以採用不同的佈局管理。
    5)b 與在Frame上添加一個部件一樣,使用Frame的add方法就可以了。
    6) 以下是一個程序實現的實例:
      源程序:lianxi10_4.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class lianxi10_4 extends JApplet
{
  
  public void init()
  {
   Frame framePad=new Frame("NumberPad");
   framePad.setLayout(new BorderLayout());
    
   JPanel panelTop=new JPanel();
   panelTop.setLayout(new GridLayout(1,4,5,10));
   panelTop.add(new JButton("Lock"));
   panelTop.add(new JButton("/"));
   panelTop.add(new JButton("*"));
   panelTop.add(new JButton("-"));
   framePad.add(panelTop,BorderLayout.NORTH);

   JPanel panelMid=new JPanel();
   panelMid.setLayout(new GridLayout(3,3,10,5));
   for(int x=1;x<=9;x++)
     panelMid.add(new JButton(String.valueOf(x)));
   
   JPanel panelBot=new JPanel();
   panelBot.setLayout(new BorderLayout());
   panelBot.add(new JButton("0"),BorderLayout.CENTER);
   panelBot.add(new JButton("."),BorderLayout.EAST);
 
   JPanel panelNum=new JPanel();
panelNum.setLayout(new BorderLayout());
   panelNum.add(panelMid,BorderLayout.CENTER);
   panelNum.add(panelBot,BorderLayout.SOUTH);
   framePad.add(panelNum,BorderLayout.CENTER);

   JPanel panelRight=new JPanel();
   panelRight.setLayout(new GridLayout(2,1,10,5));
   panelRight.add(new JButton("+"));
   panelRight.add(new JButton(" "));
   framePad.add(panelRight,BorderLayout.EAST);
   
   framePad.pack();
   framePad.show();
  }
}


10.4 GridBag佈局
    實例說明

  
    到現在爲止,我們已經學習了邊框佈局、網格佈局以及組合佈局,現在大家試一試編寫一個程序,使其顯示如下圖所示的界面:

10-16.jpg
圖10-16 挑戰(1)

    怎麼樣,挺有難度的吧!完成這個GUI得花很多心思去設計組合,十分討厭,下面我們就使用一個新的佈局管理器GridBagLayout來解決這種難題。
    首先,輸入以下源程序:
      源程序:testGridBag.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class testGridBag extends JApplet
{
  
  public void init()
  {
   JPanel panel1=(JPanel)getContentPane();
   panel1.setLayout(new GridBagLayout());
   GridBagConstraints gbdc=new GridBagConstraints();
   gbdc.fill=GridBagConstraints.BOTH;
  
   gbdc.weightx=1;
   gbdc.weighty=1;
   panel1.add(new JButton("No.1"),gbdc);
   panel1.add(new JButton("No.2"),gbdc);
   panel1.add(new JButton("No.3"),gbdc);
   gbdc.gridwidth=2;
   gbdc.gridx=0;
   panel1.add(new JButton("No.4"),gbdc);
   gbdc.gridx=2;
   gbdc.gridwidth=1;
   gbdc.gridheight=2;
   panel1.add(new JButton("No.5"),gbdc);
   
   gbdc.gridx=0;
   gbdc.gridheight=1;
   panel1.add(new JButton("No.6"),gbdc);
   gbdc.gridx=1;
   panel1.add(new JButton("No.7"),gbdc);

   gbdc.gridx=0;
   gbdc.gridwidth=2;
   panel1.add(new JButton("No.8"),gbdc);
   gbdc.gridx=2;
   gbdc.gridwidth=1;
   panel1.add(new JButton("No.9"),gbdc);
  }
}


    傳授新知

    在這個程序中,我們使用了GridBagLayout輕鬆地完成了這個界面的設計,允分凸現出它的強大。可以這麼說,GridBagLayout是Java語言中最強大的佈局管理器。
    GridBagLayout,從名字上看,就知道它與GridLayout有一定的淵源,是的,GridBagLayout的確與其十分類似,也是使用網格來進行佈局管理的。但與GridLayout(網格佈局)不同的是,GridBagLayout不像網格佈局一相,需要所有的部件的大小、形狀相同。而且還可以將某一個部件放在一個固定的位置上。
下面,我們一起來分析一下testGridBag.java程序。
    1) panel1.setLayout(new GridBagLayout());
    在調用setLayout方法時,指定爲GridBagLaoyout,使panel1使用GridBag佈局管理。
    2) GridBagConstraints gbdc=new GridBagConstraints();
    GridBagLayout佈局管理器是通過一個GridBagConstraints類來實現神奇的效果的。所以,我們要在使用時先定義一個GridBagConstraints類的對象。在這個程序中,我們定義了一個GridBagConstraints類的對象gbdc。
    3) gbdc.fill=GridBagConstraints.BOTH;
    由於網格單元可能比該單元中的部件大,如果是這樣,部件放置在單元格內會有一些多餘空間。在默認情況下,部件不會擴張,也就是不會填充這個多餘空間。
    GridBagConstraints提供了一個fill屬性,我們可以通過設置它的值來起到不同的效果。
    ¨ GridBagConstraints.NONE:不擴張,是默認值;
    ¨ GridBagConstraints.HORIZONTAL:部件水平擴張,將水平方向的多餘空間填滿;
    ¨ GridBagConstraints.VERTICAL:部件垂直擴張,將垂直方向的多餘空間填滿;
    ¨ GridBagConstraints.BOTH:部件同時向兩個方向擴張,將單元格填滿。
    4) gbdc.weightx=1;
        gbdc.weighty=1;
    weightx和weighty是GridBagConstraints提供的另一對屬性。它的取值是整型數,默認值爲0。用來設置行(weightx)、列(weighty)的“重量”,如果值爲0的話,所有的部件都會緊收在一起,聚集在中央,如圖10-17所示。
而如果取值爲其它數字,則會根據值來分配空間。
    5) panel1.add(new JButton("No.1"),gbdc);
        panel1.add(new JButton("No.2"),gbdc);
        panel1.add(new JButton("No.3"),gbdc);
    在沒有任何約束的時候,向gbdc中添加按鈕,這時效果與採用網格佈局的效果完全一樣。一個接着一個地“佔領”單元格。

10-17.jpg
圖10-17 當weightx與weighty爲0時的效果圖

    6) gbdc.gridwidth=2;
        gbdc.gridx=0;
        panel1.add(new JButton("No.4"),gbdc);
     
    由於第四個按鈕(No.4)是寬度是2,在GridBagLayout中,是由gridwidth屬性來控制添加進入的部件的寬度的。
    我們通過gbdc.gridwidth=2將其設置爲2,這樣,再添加進入的部件就會變成爲2個單元格的寬度。
    另外,我們再使用gbdc.gridx=0讓其另起一行,從最左邊的單元格開始填充。
    因此,我們發現第四個按鈕被加在了第二行,寬度爲2個單元格。

    7) gbdc.gridx=2;
        gbdc.gridwidth=1;
        gbdc.gridheight=2;
        panel1.add(new JButton("No.5"),gbdc);
    接下來,我們要擺放第五個按鈕,這個按鈕將從第3個單元開始填充,其寬度爲一個單元格,而高度則爲兩個單元格。
    因此,我們首先使用用gbdc.gridx=2,使得下一個添加的部件(第五個按鈕)放入第3個單元格(0代表第1個單元格,因此第3個單元格應該是2)。
    由於,前面我們已經將gridwidth設置爲2了,因此,我們需要使用gbdc.gridwidth=1,將其值設置回1。
    最後使用gdbc.gridheight=2,使得添入的部件的單元格縱向跨越兩個單元格。

    8) gbdc.gridx=0;
        gbdc.gridheight=1;
        panel1.add(new JButton("No.6"),gbdc);
    我想這一段程序,大家應該都不會再有什麼理解上的問題了吧!主要提醒大家注意的是,我們使用gbdc.gridheight=1將單元格縱向跨度改成了默認值1。這是因爲我們在前面需要時將其改成了2,所以在此需要將其改回來。


  實例說明
    爲了更好地理解這個強大的GridBagLayout佈局管理器,我們再來做一個有趣的實驗。首先,我們創建一個testGridBag2.java
      源程序:testGridBag2.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class testGridBag2 extends JApplet
{
  
  public void init()
  {
   JPanel panel1=(JPanel)getContentPane();
   panel1.setLayout(new GridBagLayout());
   GridBagConstraints gbdc=new GridBagConstraints();
   
   panel1.add(new JButton("No.1"),gbdc);
   panel1.add(new JButton("No.2"),gbdc);
   setSize(300,200);
  }
}
    運行這個程序,我們將得到以下結果:

10-18.jpg
圖10-18 實驗結果(1)

    然後我們使用鼠標改變一下窗口的大小,看一下,這兩個按鈕有什麼變化?你會驚奇地發現,窗口改變了大小,兩個按鈕的大小卻沒有變,而且一直呆在正中央的位置。

    一些說明:
    在這個程序中,我們使用了一個以前沒有用過的語句:setsize(300.200),它的功能是在程序中設置窗口的大小。

    現在我們對這個程序做一些修改!將添加兩個按鈕的兩條語句:
           panel1.add(new JButton("No.1"),gbdc);
           panel1.add(new JButton("No.2"),gbdc);
    將它們擴展爲:
           gbdc.weightx=1;
           panel1.add(new JButton("No.1"),gbdc);
           gbdc.weightx=3;
           panel1.add(new JButton("No.2"),gbdc);
    再重新編譯、運行這個程序,你想會發生什麼變化呢?我們一起來看一下結果:

10-19.jpg
圖10-19 實驗結果(2)
 
    爲什麼會得到這個效果呢?我們在程序中添加按鈕的程序段前加入一句:
           gbdc.fill=GridBagConstraints.HORIZONTAL;
    再重新編譯一下程序,再看看程序的輸出有什麼變化!
    在得到結果之前,自己可以想象一下結果,然後看一下程序的實際輸出與你的想法是否相吻合。
    我們驚奇地發現,第二個按鈕,突然變得十分寬起來(如圖10-20所示)。這是因爲放置第二個按鈕的單元格的寬度是3,而第一個按鈕的寬度是1。而且,我們又讓第二個按鈕橫向擴展,因此得到了這樣的輸出結果。

10-20.jpg
圖10-20 程序實驗結果(3)

    相信實驗做到這裏,不須我說,大家也會有一些心得體會了。但是GridBagLayout遠不止這一點,大家應該多做試驗,才能夠在真實的使用環境中有效地掌握GridBagLayout。


    自測練習

    1) 如果不設置,GridBagConstraints的fill屬性的值是_________。
        a.GridBagConstraints.VERTICAL b.GridBagConstraints. HORIZONTAL
        c.GridBagConstraints.BOTH d.GridBagConstraints.NONE
    2) GridBagConstraints的weightx和weighty的值是_______和_______。
        a. 1 0 b.0 0 c.0 1 d.1 1
    3) 如果在程序中,我們將gridx設置爲0,則______________。
        a.新的部件從新的一行開始添加 b.新的部件將覆蓋掉第一個部件
    4) 編寫一個程序,使用GridBagLayout佈局管理器實現對小鍵盤的模擬。程序的輸出如下圖所示:

10-21.jpg
圖10-21 練習題圖
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________
   ____________________________________________________________________


    練習答案

    1)d GridBagConstraints屬性fill的默認值是GridBagConstraints.NONE。
    2)b 這兩個值的默認值均是0。
    3)a 當然不會覆蓋已經存在的部件了。
    4)以下是一個程序實例:
      源程序:lianxi10_5.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;

public class lianxi10_5 extends JApplet
{
  
  public void init()
  {
   JPanel panel1=(JPanel)getContentPane();
   panel1.setLayout(new GridBagLayout());
   GridBagConstraints gbdc=new GridBagConstraints();
   gbdc.fill=GridBagConstraints.BOTH;
   gbdc.weightx=1;
   gbdc.weighty=1;
  
   panel1.add(new JButton(" "),gbdc);
   panel1.add(new JButton("/"),gbdc);
   panel1.add(new JButton("*"),gbdc);
   panel1.add(new JButton("-"),gbdc);

   gbdc.gridx=0;
   panel1.add(new JButton("7"),gbdc);
   gbdc.gridx=1;
   panel1.add(new JButton("8"),gbdc);
gbdc.gridx=2;
   panel1.add(new JButton("9"),gbdc);
   gbdc.gridheight=2;
   gbdc.gridx=3;
   panel1.add(ne

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章