深入學習GridBagLayout

轉自 http://www.cnblogs.com/renyuan/archive/2012/10/15/2723809.html

試着用用你會發現GridBagLayout真的能解決幾乎所有界面佈局的問題,窗口大小的隨意改變也不會影響到整體佈局,更重要的是它可以實現任何你想要的佈局設計,只要你做到更有計劃和更有耐心一點就行了。

對於簡單的程序使用Boborderlayout和Gridlayout就綽綽有餘了, 但如果要把程序提到實際應用上你就得考慮使用GridBagLayout。當然, 做複雜的應用程序時,一開始就使用GridBagLayout就會更有效率。一旦你決定使用GridBagLayout,接下來一步便是要找一些紙和鉛筆,只有你準確知道你的界面看上去需要成什麼樣子,你就可以敲鍵盤。這就是說,你應該在編碼之前進行妥善規劃。

昨天看了一晚上Swing 聯想到做前端的經歷, 我對能夠自由操作組件的依賴性很高, 否則會讓我覺得很彆扭. 腦海裏重複對比思考六種佈局管理器. 最終將最終的選擇放在了網絡包管理器, 我不覺得它很複雜,倒是覺得正是這些靈活性使得 我擁有更多的自由操縱組件的空間.

GridBagLayout從它的名字中你也可以猜到,它同GridLayout一樣,在容器中以網格形式來管理組件.但GridBagLayout功能要來得強大得多.

  1. GridBagLayout管理的所有行和列都可以是大小不同的.
  2. GridLayout把每個組件限制到一個單元格,而GridBagLayout並不這樣: 組件在容器中可以佔據任意大小的矩形區域, GridBagLayout通常由一個專用類來對他佈局行爲進行約束, 該類叫GridBagConstraints. 其中的所有成員都是public的, 因此要學好如何使用GridBagLayout首先要了解有那些約束變量,以及如何設置這些約束變量.以下是GridBagConstraints的公有成員變量:

構造函數:
GirdBagLayout()
建立一個新的GridBagLayout管理器。

GridBagConstraints()
建立一個新的GridBagConstraints對象。

GridBagConstraints(int gridx,int gridy, int gridwidth,int gridheight, double weightx,double weighty,int anchor,int fill, Insets insets, int ipadx,int ipady)
建立一個新的GridBagConstraints對象,並指定其參數的值。

參數說明:
gridx,gridy —— 設置組件的位置,
gridx設置爲GridBagConstraints.RELATIVE代表此組件位於之前所加入組件的右邊。
gridy設置爲GridBagConstraints.RELATIVE代表此組件位於以前所加入組件的下面。
建議定義出gridx,gridy的位置以便以後維護程序。gridx=0,gridy=0時放在0行0列。

gridwidth,gridheight —— 用來設置組件所佔的單位長度與高度,默認值皆爲1。
你可以使用GridBagConstraints.REMAINDER常量,代表此組件爲此行或此列的最後一個組件,而且會佔據所有剩餘的空間。

weightx,weighty —— 用來設置窗口變大時,各組件跟着變大的比例。
當數字越大,表示組件能得到更多的空間,默認值皆爲0。

anchor —— 當組件空間大於組件本身時,要將組件置於何處。
有CENTER(默認值)、NORTH、NORTHEAST、EAST、SOUTHEAST、WEST、NORTHWEST選擇。

insets —— 設置組件之間彼此的間距。
它有四個參數,分別是上,左,下,右,默認爲(0,0,0,0)。

ipadx,ipady —— 設置組件間距,默認值爲0。

在這裏插入圖片描述
你應該能看到在草圖裏有一些線,這些線是用來把總界面分成若干行和列的,這樣你就很清楚每一個組件放置的格子位置。這就是GridBagLayout裏"格"的那一部分,而圖上的數字就是格的號碼。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GridBagWindow extends JFrame {
    private JButton searchBtn;
    private JComboBox modeCombo;
    private JLabel tagLbl;
    private JLabel tagModeLbl;
    private JLabel previewLbl;
    private JTable resTable;
    private JTextField tagTxt;
    public GridBagWindow() {
        Container contentPane = getContentPane();
        GridBagLayout gridbag = new GridBagLayout();
        contentPane.setLayout(gridbag);
        GridBagConstraints c = new GridBagConstraints();
        //setting a default constraint value
        c.fill =GridBagConstraints.HORIZONTAL;
        tagLbl = new JLabel("Tags");
        c.gridx = 0; //x grid position
        c.gridy = 0; //y grid position
        gridbag.setConstraints(tagLbl, c); //associate the label with a constraint object 
        contentPane.add(tagLbl); //add it to content pane

        tagModeLbl = new JLabel("Tag Mode");
        c.gridx = 0;
        c.gridy = 1;
        gridbag.setConstraints(tagModeLbl, c);
        contentPane.add(tagModeLbl);
        tagTxt = new JTextField("plinth");
        c.gridx = 1;
        c.gridy = 0;
        c.gridwidth = 2;
        gridbag.setConstraints(tagTxt, c);
        contentPane.add(tagTxt);
        String[] options = {"all", "any"};
        modeCombo = new JComboBox(options);
        c.gridx = 1;
        c.gridy = 1;
        c.gridwidth = 1;
        gridbag.setConstraints(modeCombo, c);
        contentPane.add(modeCombo);
        searchBtn = new JButton("Search");
        c.gridx = 1;
        c.gridy = 2;
        gridbag.setConstraints(searchBtn, c);
        contentPane.add(searchBtn);
        resTable = new JTable(5,3);
        c.gridx = 0;
        c.gridy = 3;
        c.gridwidth = 3;
        gridbag.setConstraints(resTable, c);
        contentPane.add(resTable);
        previewLbl = new JLabel("Preview goes here");
        c.gridx = 0;
        c.gridy = 4;
        gridbag.setConstraints(previewLbl, c);
        contentPane.add(previewLbl);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
    public static void main(String args[]) {
        GridBagWindow window = new GridBagWindow();
        window.setTitle("GridBagWindow");
        window.pack();
        window.setVisible(true);
    }
}
 

構造方法前的代碼都不是很特殊,都是一些相當標準的import和變量定義。但是進入構造方法後,事情就變得有趣了。

Container contentPane = getContentPane();
GridBagLayout gridbag = new GridBagLayout();
contentPane.setLayout(gridbag);

我們以GridBagWindow的內容面板作爲開始來創建一個GridBagLayout對象,準確地說,這個方法與過去我們所創建GridLayout對象和BorderLayout對象的方法是一樣的。那麼,現在我們就開始來設置GridBagLayout對象使它作爲內容面板的佈局。

GridBagConstraints c = new GridBagConstraints();

然後我要提到這整個進程中的一個獨特的對象,那就是GridBagConstraints。這個對象在GridBagLayout中控制所有被安置在其中組件的約束。爲了把一個組件增加到你的GridBagLayout中去,你首先必須將它與一個GridBagConstraints對象建立連接。

GridBagConstraints可以從11個方面來進行控制和操縱,也可以給你提供一些幫助。這些內容是:

  • Gridx——組件的橫向座標 Girdy——組件的縱向座標
  • Gridwidth——組件的橫向寬度,也就是指組件佔用的列數,這與HTML的colspan類似
  • Gridheight——組件的縱向長度,也就是指組件佔用的行數,這與HTML的rowspan類似
  • Weightx——指行的權重,告訴佈局管理器如何分配額外的水平空間
  • Weighty——指列的權重,告訴佈局管理器如何分配額外的垂直空間
  • Anchor——告訴佈局管理器組件在表格空間中的位置
  • Fill——如果顯示區域比組件的區域大的時候,可以用來控制組件的行爲。控制組件是垂直填充,還是水平填充,或者兩個方向一起填充
  • Insets——指組件與表格空間四周邊緣的空白區域的大小 Ipadx——
  • 組件間的橫向間距,組件的寬度就是這個組件的最小寬度加上ipadx值 ipady——
  • 組件間的縱向間距,組件的高度就是這個組件的最小高度加上ipady值

可能對於一個組件的每一個實例你都需要爲它建立一個單獨的GridBagConstraints;然而,這種方法我們並不推薦使用。最好的方法是,當你調用它的時候把對象設置爲默認值,然後針對於每一個組件改變其相應的域。

這個方法具有通用性,因爲在一些域中,比如insets、padx、pady和fill這些域,對於每一個組件來說一般都是相同的,因此這樣對一個域進行設置就會更輕鬆了,也能更輕鬆的在另外的組件中改變某些域的值。

如果在改變了某些域值之後,你想回到原始的域值的話,你應該在增加下一個組件之前進行改變。這種方法使你更容易明白你正在修改的內容,也能使你更容易明白在一連串對象中的這11個參數的作用。

也許你現在對這些內容還是一知半解,不過事實上一旦你理解了GridBagConstraints,值得安慰的是你以後做再困難的工作都會遊刃有餘了。

所以,如果我們已經明白了GridBagConstraints的詳細用法了,那麼現在就讓我們來看看在實際應用中應該如何來實現它:

tagLbl = new JLabel("Tags");
c.gridx = 0; //x grid position
c.gridy = 0; //y grid position
gridbag.setConstraints(tagLbl, c); //設置標籤的限制

contentPane.add(tagLbl); //增加到內容面板

我們所做的是示例我們的標籤、分配給它一個格位置,將它與一個約束對象聯繫起來並把它增加到我們的內容面板中。

tagModeLbl = new JLabel("Tag Mode");
c.gridx = 0;
c.gridy = 1;
gridbag.setConstraints(tagModeLbl, c);

contentPane.add(tagModeLbl);

請注意,雖然我們已經在我們的約束對象中把gridx的值設置爲0,但是在這裏我們仍然要對它進行重新設置——這樣做沒有其它原因,只是爲了增加可讀性。

下面,我們增加一個文本域以便能存儲我們希望能搜索到的關鍵字,再增加一個組合框以便用來搜索多個關鍵字。除了我們希望的文本域有兩列之外,這個概念其他的方面都與上面所說的是相同的,所以,我們需要在增加組合框之前重新設置文本域的值。

tagTxt = new JTextField("plinth");
c.gridx = 1;
c.gridy = 0;
c.gridwidth = 2;
gridbag.setConstraints(tagTxt, c);
contentPane.add(tagTxt);

String[] options = {"all", "any"};
modeCombo = new JComboBox(options);
c.gridx = 1;
c.gridy = 1;
c.gridwidth = 1;
gridbag.setConstraints(modeCombo, c);
contentPane.add(modeCombo);

做了這些之後,我們再在內容面板中增加一些其餘的簡單組件,這時候我們就能夠瀏覽它了;其餘的代碼應該不會出現任何問題了。

到這個階段,我們應該已經得到了一個類似於我們先前所設計的界面了。


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