用戶界面的佈局
開始爲Java程序設計圖形用戶界面時,面臨的一個障礙是組件會移動。容器大小發生變化時,容器中的組件將會根據容器的新尺寸重新排列。這種變化對程序員有利,因爲它考慮到了界面組件在不同操作系統中的顯示方式。對於同一個Java程序,可單擊的按鈕在Windows、linux和Mac操作系統中的外觀可能不同。
使用一組被稱爲佈局管理器的類來排列界面中的組件,這些類定義了組件如何在容器中顯示。界面中的每個容器都有自己的佈局管理器。
1、使用佈局管理器
1)、FlowLayout管理器
它是面板的默認佈局管理器類,使用時,想在頁面中排列英文單詞那樣排列組件:從左到右,當前行沒有空間後進入下一行。
當框架中添加進組件時,可以使用如下代碼示例來調用浮動的佈局:
FlowLayout layout = new FlowLayout();
setLayout(layout);
也可以指定用於特定容器(如JPanle對象)的佈局管理器,爲此可以使用該容器對象的setLayout()方法。
FlowLayout類僅根據容器的尺寸來排列組件。調整應用程序窗口的大小時,組件將立刻重新排列。將窗口的寬度增大到原來的兩倍,將發現所有的JButton組件都顯示在同一行。
2)、GridLayout容器
它將容器中所有的組件組織爲指定的行數和列數。分配給每個組件的顯示區域都相同,因此如果指定3*3的網格,容器將被劃分爲9個大小相等的區域。
當組件加入到容器中時,GridLayout將所有的組件放置到網格中的某個位置,而且組件是從左向右一次添加,當這一行滿了之後,再從下一行的最左邊開始添加。下面的語句創建了一個2行3列的網格佈局:
GridLayoutgridLayout = new GridLayout(2, 3);
setLayout(gridLayout);
JButton button1 = new JButton("1號按鈕");
JButton button2 = new JButton("2號按鈕");
JButton button3 = new JButton("3號按鈕");
JButton button4 = new JButton("4號按鈕");
JButton button5 = new JButton("5號按鈕");
add(button1);
add(button2);
add(button3);
add(button4);
add(button5);
使用此佈局時,如果組件容納不下標籤文本,將使用省略號(...)表示省略的文本。
3)、BorderLayout管理器
它將容器中的組件放置在特定的位置,該位置有5個方位:東、南、西、北、中。其中4個位置由方向羅盤方向指定,另外一個由中心區域指定。
與GridLayout類相同,BorderLayout也會將所有可用空間都分配給組件。在周圍放置4個邊界組件後,餘下的空間都分配給中央的組件,因此它通常是最大的。下面的語句創建一個使用邊界佈局的容器:
//參數10,20用於指定組件之間的水平,垂直距離
BorderLayout borderLayout = newBorderLayout(10, 20);
setLayout(borderLayout);
JButton button1 = new JButton("1號按鈕");
JButton button2 = new JButton("2號按鈕");
JButton button3 = new JButton("3號按鈕");
JButton button4 = new JButton("4號按鈕");
JButton button5 = new JButton("5號按鈕");
add(button1 , BorderLayout.NORTH);
add(button2 , BorderLayout.SOUTH);
add(button3 , BorderLayout.WEST);
add(button4 , BorderLayout.EAST);
add(button5 , BorderLayout.CENTER);
4)、BoxLayout管理器
它可以講組件排列成一行或一列。使用該佈局時,先創建一個放置組件的面板,然後再創建一個佈局管理器,它帶有兩個參數:
以框式佈局(box layout)組織的組件;
BoxLayout.Y_AXIS指定垂直排列,BoxLayout.Y_AXIS指定水平排列。
下面的語句創建一個使用BoxLayout的容器:
JPanel panel = new JPanel();
BoxLayout boxLayout = newBoxLayout(panel, BoxLayout.Y_AXIS);
panel.setLayout(boxLayout);
JButton button1 = new JButton("1號按鈕");
JButton button2 = new JButton("2號按鈕");
JButton button3 = new JButton("3號按鈕");
JButton button4 = new JButton("4號按鈕");
JButton button5 = new JButton("5號按鈕");
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.add(button5);
add(panel);
5)、使用Insets將組件隔開
在容器中排列組件時,可以使用Insets令組件遠離容器邊緣,Insets是代表容器邊界區域的對象,它有一個接受4個參數的構造函數:在容器上下左右留出的空間。每個參數都以像素爲單位,像素是定義框架大小時使用的度量單位。下面的語句創建一個Insets對象:
Insets insets =new Insets(10 , 6 , 10 , 3);
意思是insets對象代表的容器邊界:上左下右邊緣內10,6,10,3像素。
要想在容器中使用Insets對象,必須覆蓋容器的getInsets()方法。該方法不接受任何參數,並返回一個Insets對象,如下所示:
Public InsetsgetInsets(){
return new Insets(50 , 15 ,10 , 15); }
Jframe容器有內置的Insets,用於爲標題欄留出空間。當覆蓋getInsets()方法並設置自定義值時,過小的insets將導致容器將組件顯示在標題欄下面。
2、應用程序的界面佈局
到目前爲止,佈局管理器應用於整個框架:調用框架的setLayout方法,所有組件遵循相同的規則。這適用於有些程序,但使用Swing開發圖形用戶界面時,將經常發現這些佈局管理器都不合適。
解決這種問題的方式之一是,將一組JPanel對象作爲容器,用於放置圖形用戶界面的不同部分。對於其中每部分,可以使用JPanel對象的setLayout()方法設置不同的佈局規則。這些面板包含需要包含的組件後,就可以將這些面板直接加入到框架中。
接下來我們將開發一個完整的界面,該程序是一個猜數遊戲,確定用戶一生中贏得百萬大獎的機會。它不斷隨機生成6個數,知道用戶選擇的數字與要出的數字相同。界面如下:
源碼爲:
package guessyourchance;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GuessYourChance extends JFrame{
JPanel row1 = new JPanel();
ButtonGroup btgOption = new ButtonGroup();
JCheckBox quickPick = new JCheckBox("快速選擇", false);
JCheckBox personal = new JCheckBox("個人的" , true);
JPanel row2 = new JPanel();
JLabel numbersLabel = new JLabel("你的輸入" , JLabel.RIGHT);
JTextField[] numbers = new JTextField[6];
JLabel winnersLabel = new JLabel("中獎數" , JLabel.RIGHT);
JTextField[] winners = new JTextField[6];
JPanel row3 = new JPanel();
JButton stop = new JButton("停止");
JButton play = new JButton("開始");
JButton reset = new JButton("重置");
JPanel row4 = new JPanel();
JLabel got3Label = new JLabel("6中3" , JLabel.RIGHT);
JTextField got3 = new JTextField("0");
JLabel got4Label = new JLabel("6中4" , JLabel.RIGHT);
JTextField got4 = new JTextField("0");
JLabel got5Label = new JLabel("6中5" , JLabel.RIGHT);
JTextField got5 = new JTextField("0");
JLabel got6Label = new JLabel("6中36" , JLabel.RIGHT);
JTextField got6 = new JTextField("0");
JLabel drawingsLabel = new JLabel("Drawing" , JLabel.RIGHT);
JTextField drawings = new JTextField("0");
JLabel yearsLabel = new JLabel("Years" , JLabel.RIGHT);
JTextField years = new JTextField("0");
public GuessYourChance() throws HeadlessException {
super("看看你滴運氣咋樣");
setSize(500 , 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridLayout gridLayout = new GridLayout(5, 1, 10, 10);
setLayout(gridLayout);
FlowLayout flowLayout1 = new FlowLayout(FlowLayout.CENTER , 10 , 10);
btgOption.add(quickPick);
btgOption.add(personal);
row1.setLayout(flowLayout1);
row1.add(quickPick);
row1.add(personal);
add(row1);
GridLayout gridLayout1 = new GridLayout(2, 7, 10, 10);
row2.setLayout(gridLayout1);
row2.add(numbersLabel);
for (int i = 0; i < 6; i++) {
numbers[i] = new JTextField();
row2.add(numbers[i]);
}
row2.add(winnersLabel);
for (int i = 0; i < 6; i++) {
winners[i] = new JTextField();
winners[i].setEditable(true);
row2.add(winners[i]);
}
add(row2);
FlowLayout flowLayout2 = new FlowLayout(FlowLayout.CENTER);
row3.setLayout(flowLayout2);
stop.setEnabled(false);
row3.add(stop);
row3.add(play);
row3.add(reset);
add(row3);
GridLayout gridLayout2 = new GridLayout(2, 3, 20, 10);
row4.setLayout(gridLayout2);
row4.add(got3Label);
row4.add(got3);
row4.add(got4Label);
row4.add(got4);
row4.add(got5Label);
row4.add(got5);
row4.add(got6Label);
row4.add(got6);
row4.add(drawingsLabel);
row4.add(drawings);
drawings.setEditable(false);
row4.add(yearsLabel);
row4.add(years);
years.setEditable(false);
add(row4);
setVisible(true);
}
public static void main(String[] args) {
GuessYourChance guessYourChance = new GuessYourChance();
}
}<strong>
</strong>