深入Java Swing用戶界面組件布局管理器:網(wǎng)格布局+面板+邊界布局
布局管理器概述
在討論每個Swing組件(例如文本域和單選按鈕)之前,首先介紹一下如何把這些組件安排在一個框架內(nèi)。與Visual Basic不同,JDK沒有表單設(shè)計器,需要通過編寫代碼來定制(布局)用戶界面組件所在的位置。
當(dāng)然,如果有支持Java的開發(fā)環(huán)境,就可能存在某種布局工具部分自動地或全部自動地完成這些布局任務(wù)。然而,確切地了解底層的實現(xiàn)方式是非常重要的,因為即使最好的工具有時也需要手工編碼。
回顧上一章的程序,我們設(shè)計了幾個按鈕,點擊這些按鈕可以改變框架的背景顏色參見圖9-5。

下面快速回顧一下該程序的編寫過程:
1)在按鈕的構(gòu)造器中設(shè)置標(biāo)簽字符串定義每個按鈕的
外觀,例如:
JButton yellowButton = new JButton("Yellow")
2)然后把每個按鈕添加到面板中,例如:
panel.add(yellowButton);
3)添加需要的事件處理器。例如:
yellowButton.addActionListener(listener);
如果添加更多的按鈕會怎樣呢?圖9-6顯示了一個帶有6個按鈕的面板。正如你所看到的,按鈕居中顯示在一行中,當(dāng)一行的空間不夠時,將顯示在新的一行上。
即使用戶對框架進(jìn)行縮放,這些按鈕也會顯示在面板的中央,如圖9-7所示。

Java用一個非常出色的概念實現(xiàn)動態(tài)布局:容器內(nèi)的所有組件都由一個布局管理器(layoutmanager)進(jìn)行定位。在列舉的示例中,所有的按鈕都通過流布局管理器(flow layout manager)進(jìn)行管理,這是面板的默認(rèn)布局管理器。
流布局管理器的特點是在一行上水平排列組件,直到?jīng)]有足夠的空間為止,這時開始新的一行。
當(dāng)用戶縮放容器時,布局管理器自動地調(diào)整組件的位置使其填充可用的空間。
還可以選擇在每一行上排列組件的方案。默認(rèn)方式是居中顯示。另外還有容器的左對齊和右對齊。要想使用這些對齊方式,需要在FlowLayout對象的構(gòu)造器中指定LEFT或者RIGHT參數(shù)。例如:
panel.setLayout(new FlowLayout (FlowLayout.LEFT));
注意:通常情況下,可以讓流布局管理器控制組件間的水平和垂直間距。然而,也可以使用其他版本的流布局管理器的構(gòu)造器指定水平和垂直間距(請參考API注釋)。
java.awt.Container 1.0
? SetLayout (LayoutManager m)
為容器設(shè)置布局管理器。
java.awt.FlowLayout 1.0
? FlowLayout (int align)
采用指定的對齊方式構(gòu)造新的FlowLayout。
參數(shù):align LEFT、CENTER或者RIGHT
? FlowLayout (int align, int hgap, int vgap)
采用指定的對齊方式和組件間的水平和垂直間距構(gòu)造新的FlowLayout。
參數(shù):align LEFT、CENTER或者RIGHT
hgap 以像素為單位的水平間距(如果為負(fù)值,則強行重疊)
vgap 以像素為單位的垂直間距(如果為負(fù)值,則強行重疊)
邊界布局
Java帶有幾個布局管理器,而且還可以構(gòu)造自己的布局管理器。本章稍后將討論這方面的內(nèi)容。然而,為了在這里介紹一個更有趣的例子,我們需要簡要說明一下另一個布局管理器,稱為邊界布局管理器(border layout manager)。這是每個JFrame的內(nèi)容窗格的默認(rèn)布局管理器。流布局管理器完全控制每個組件的位置,邊界布局管理器則不同,它允許我們選擇每個組件的放置位置??梢赃x擇把組件放置在內(nèi)容窗格的中部、北部、南部、東部或者西部,如圖9-8所示。

例如:
panel.setLayout(new BorderLayout( ));
panel.add(yellowButton, BorderLayout.SOUTH);
先放入邊緣組件,剩余的可用空間由中間組件占用。當(dāng)容器縮放時,邊緣組件的厚度不會改變,而中部組件的大小會發(fā)生變化。
可以通過指定BorderLayout類中的CENTER、NORTH、SOUTH、EAST和WEST常量添加組件。并沒有要求所有的位置都要占滿。如果不提供任何值,系統(tǒng)默認(rèn)為CENTER。
注意:BorderLayout常量定義為字符串。例如,BorderLayout.SOUTH定義為字符串“South”。
許多程序員喜歡直接使用字符串,因為這些字符串都比較簡短,例如,frame.add(component, "SOUTH")。但是,如果字符串拼寫有誤,編譯器不會捕獲異常。
與流布局不同,邊界布局會擴大所有組件的尺寸以便填充可用空間(在流布局中每個組件都有首選的大?。?/p>
與流布局一樣,可以通過在BorderLayout的構(gòu)造器中提供間距參數(shù)來指定間距。
如同前面指出的,JFrame的內(nèi)容窗格使用了邊界布局。直到現(xiàn)在,我們尚未利用這個優(yōu)點—我們只是把面板添加到默認(rèn)(中部)區(qū)域。實際上也可以把組件添加到其他區(qū)域:
frame.add(yellowButton, BorderLayout.SOUTH);
然而,這段代碼有問題,我們會在下一節(jié)中討論。
java.awt.Container 1.0
? void add(Component c, Object constraints)?1.1
把一個組件添加到容器里。
參數(shù):c 要添加的組件
constraints 布局管理器理解的標(biāo)識符
java.awt.BorderLayout 1.0
? BorderLayout(int hgap, int vgap)
采用指定的組件水平和垂直間距來構(gòu)造BorderLayout。
參數(shù):hgap 以像素為單位的水平間距(如果為負(fù)值,則強行重疊)
vgap 以像素為單位的垂直間距(如果為負(fù)值,則強行重疊)
面板
只有BorderLayout還不夠,圖9-9展示了上一節(jié)中代碼的執(zhí)行結(jié)果。按鈕擴展到填滿框架的整個南部區(qū)域。而且,如果在南部區(qū)域添加另一個按鈕的話,就會取代第一個按鈕。
解決這種問題的常見方法是使用另外一個面板(panel)。面板如同界面元素的(較小的)容器,并且在布局管理器的控制之下,它們自己能夠排列在一個更大的面板中。例如,可以把一個面板放在南部區(qū)域用于容納按鈕,而另一個面板放在中部用于顯示文本。通過嵌套面板并將邊界布局與流布局混合使用,可以精確地定位組件。這種布局方法對于原型來說已經(jīng)足夠了,本章第一部分的示例程序使用的就是這種布局方法。如果要以更精確的方式定位組件,請參考后面的網(wǎng)格布局(GridBagLayout)一節(jié)。
例如,在圖9-10中,屏幕底部的三個按鈕包含在一個面板中。這個面板被放置到內(nèi)容窗格的南部。

假設(shè)希望顯示如圖9-10所示的外觀,添加一個存放三個按鈕的面板。首先創(chuàng)建一個新的JPanel的對象,然后往面板中添加單個按鈕。面板的默認(rèn)布局管理器是FlowLayout,這符合我們的需求。最后使用add方法將每個按鈕添加到面板中。由于把按鈕添加到面板中且沒有改變默認(rèn)的布局管理器,所以每個按鈕的位置和大小都由FlowLayout管理器所控制。這意味著這些按鈕將顯示在面板中央并且不會擴展至填充整個面板區(qū)域。
下面是把一個含有三個按鈕的面板添加到一個框架南部區(qū)域的代碼片斷。
JPanel panel = new JPanel( );
panel.add(yellowButton);
panel.add(blueButton);
panel.add(redButton);
frame.add(panel, BorderLayout.SOUTH);注意:面板邊界對用戶來說是不可見的。面板只是用戶界面設(shè)計者的一個組織機制。
前面講過,JPanel類使用FlowLayout作為默認(rèn)的布局管理器。對于JPanel來說,可以利用構(gòu)造器為其提供不同的布局管理器。而大多數(shù)其他的容器沒有這樣的構(gòu)造器。所有的容器都有一個用于設(shè)置布局管理器的setLayout方法。
javax.swing.JPanel 1.2
? JPanel(LayoutManager m)
為面板設(shè)置布局管理器。
網(wǎng)格布局
網(wǎng)格布局像電子數(shù)據(jù)表一樣,按行列排列所有的組件。不過,它的每個單元大小都一樣。圖9-11的計算器程序使用了網(wǎng)格布局來安排計算器按鈕。當(dāng)縮放窗口時,計算器中的按鈕隨之變大或變小,但所有的按鈕尺寸相同。
在網(wǎng)格布局對象的構(gòu)造器中,需要指定需要的行數(shù)和列數(shù):
panel.setLayout(new GirdLayout(5, 4));
使用邊界布局和流布局管理器,可以在組件間指定想要的水平和垂直間距:
panel.setLayout(new GridLayout(5, 4, 3, 3));
構(gòu)造器的后兩個參數(shù)指定了組件間的水平和垂直間距(以像素為單位)。
添加組件,從第一行的第一列開始,然后是第一行的第二列,以此類推。
panel.add(new JButton("1"));
panel.add(new JButton("2"));
例9-1是計算器程序的源代碼。這是一個規(guī)則的計算器,而不是在Java指南中的那種奇怪的計算器。在這個程序中,添加組件到框架之后,調(diào)用pack方法。這個方法用于將所有組件以最佳的高度和寬度顯示在框架中。
當(dāng)然,極少有應(yīng)用程序具有與計算器的外表一樣的布局。在實際應(yīng)用中,小的網(wǎng)格(通常僅僅一行或者一列)在組織窗口的布局區(qū)域時比較有用。例如,如果想有一行相同尺寸的按鈕,那么就可以把按鈕放置在一個面板里面,這個面板使用只有單行的網(wǎng)格布局進(jìn)行管理。
例9-1 Calculator.java






java.awt.GridLayout 1.0
? GridLayout(int rows, int cols)
構(gòu)造一個新的GridLayout對象。
參數(shù):rows 網(wǎng)格的行數(shù)
cols 網(wǎng)格的列數(shù)
? GridLayout(int rows, int columns, int hgap, int vgap)
使用組件間的水平和垂直間距來構(gòu)造一個新的GridLayout。
參數(shù):rows 網(wǎng)格的行數(shù)
columns 網(wǎng)格的列數(shù)
hgap 以像素為單位的水平間距(如果為負(fù)值,則強行重疊)
vgap 以像素為單位的垂直間距(如果為負(fù)值,則強行重疊)
java.awt.Window 1.0
? void pack( )
縮放窗口時,調(diào)整組件至最佳尺寸。
本文就是愿天堂沒有BUG給大家分享的內(nèi)容,大家有收獲的話可以分享下,想學(xué)習(xí)更多的話可以到微信公眾號里找我,我等你哦。
