第11章 在用户界面上排列组件
- 11.1 基本的界面布局
- 11.1.1 布置界面
- 11.1.2 顺序布局
- 11.1.3 方框布局
- 11.1.4 网格布局
- 11.1.5 边框布局
- 11.2 使用多个布局管理器
- 11.3 卡片布局
- 11.3.1 在应用程序中使用卡片布局
- 11.3.2 单元格内边距和面板内边距
11.1 基本的界面布局
11.1.1 布置界面
面板的默认布局管理器是FlowLayout类。这个类按组件加入到容器的顺序从左向右依次排列。第一行排满后,则从第二行开始,继续按从左到右的顺序排列。
通用的布局管理器:
- FlowLayout
- GridLayout
- BorderLayout
- CardLayout
创建布局管理器后,要将其用作容器的布局管理器,可调用方法setLayout()。 将组件加入到容器前,必须设置容器的布局管理器。如果没有指定布局管理器,将使用容器的默认布局:对于面板,为FlowLayout;对于框架,为BorderLayout。
11.1.2 顺序布局
类FlowLayout是最简单的布局管理器,位于java.awt中。它排列组件的方式与排列英语单词的方式相同,从左到右排列,到达行尾后,进入下一行开头。
默认情况下,如果调用构造函数FlowLayout()没有提供任何参数,每行的组件将居中排列。要让组件右对齐或左对齐,可将类变量FlowLayout.LEFT或FlowLayout.RIGHT作为唯一的参数传递给构造函数
FlowLayout rightly = new FlowLayout(FlowLayout.RIGHT)
这个管理器使用默认的水平间距(5像素)和垂直间距(5像素)。
- 您可以在调用构造函数FlowLayout(int,int,int)时,提供其他的参数来修改水平间距和垂直间距;
- 可以调用方法setVgap(int)和setHgap(int),并指定所需的水平间距和垂直间距
11.1.3 方框布局
方框布局(box layout)管理器将组件从左到右或从上到下排列,它是由javax.swing包中的BoxLayout类表示的,对顺序布局进行了改进——不管容器的大小如何变化,组件总是排列成一行或一列。
JPanel optionPane=new JPane();
BoxLayout box =new BOXLayout(optionPane,BoxLayout,Y_AXIS);
// X_AXIS表示按从左到右的顺序水平排列;Y_AXIS表示按从上到下的顺序垂直排列
optionPane.setLayout(box);
11.1.4 网格布局
网格布局是使用类GridLayout创建的,这个类位于java.awt包中。调用构造函数GridLayout时,提供两个参数:网格的行数和列数。
GridLayout gr=new GridLayout(10,3);
setHgap()和setVgap()
//设置指定组件的垂直间距和水平间距
默认情况下,网格布局组件间的垂直间距和水平间距都为0.
11.1.5 边框布局
边框布局是使用java.awt包中的BorderLayout类创建的,它将容器分成5个部分:北、南、东、西和中央。
BorderLayout()或BorderLayout(int, int)
// 创建边框布局,第一个边框布局的组件间距为0,第二个指定了水平间距和垂直间距
setVgap()和setHgap()
// 设置水平间距和垂直间距
add(Component,String)
// 第一个是要加入容器的组件,第二个指定组件加入边框布局的哪个区域。(NORTH、SOUTH、EAST、WEST和CENTER)
JButton quitButton = new JButton("quit");
add(quitButton,BorderLayout.NORTH);
11.2 使用多个布局管理器
为了找到合适的布局,常常需要在同一个界面中使用多个布局管理器。为此,可将多个容器加入到一个更大的容器中,并给每个小容器指定布局管理器。
小容器为面板,它是使用Java.swing包中的JPanel类创建的,面板是用于将组件组合在一起的容器。使用面板时需要注意两点:
- 将面板加入到更大容器之前,必须将相应的组件加入到面板中
- 面板有它自己的布局管理器
11.3 卡片布局
卡片布局管理器不同于其他布局管理器,因为它隐藏一些组件。卡片布局是一组容器或组件,每次只显示其中的一个。其中的容器称为卡片。
使用卡片布局时,最常见的方式是使用面板作为卡片。首先将组件加入到面板中,然后将面板加入到使用卡片布局的容器中。
CardLayout cc = new CardLayout();
setLayout(cc);
// 将容器设置为使用卡片布局管理器
add(Component,String)
// 第一个参数指定将用作卡片的容器或组件。如果是容器,将其作为卡片加入之前,必须包含所需的组件
// 第二个参数是表示卡片名称的字符串
使用卡片布局的容器首次显示时,显示的是加入到容器中的第一张卡片。要显示其他卡片,可调用show方法,该方法接受两个参数:
- 用于放置所有卡片的容器
- 卡片的名称
cc.show(this,"Fact Card");
关键字this指的是包含该语句的对象,Fact Card是要显示卡片的名称。
11.3.1 在应用程序中使用卡片布局
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SurveyWizard extends JPanel implements ActionListener {
int currentCard = 0;
CardLayout cards = new CardLayout();
SurveyPanel[] ask = new SurveyPanel[3];
public SurveyWizard() {
super();
setSize(240, 140);
setLayout(cards);
// set up survey
String question1 = "What is your gender?";
String[] resp1 = {"female", "male", "not telling"};
ask[0] = new SurveyPanel(question1, resp1, 2);
String question2 = "What is your age?";
String[] resp2 = {"Under 25", "25-34", "34-54", "Over 54"};
ask[1] = new SurveyPanel(question2, resp2, 1);
String qusetion3 = "How often do you exercise each week?";
String[] resp3 = {"Never", "1-3 times", "More than 3"};
ask[2] = new SurveyPanel(qusetion3, resp3, 1);
ask[2].setFinalQuestion(true);
addListenners();
}
private void addListenners(){
for(int i=0;i<ask.length;i++){
ask[i].nextButton.addActionListener(this);
ask[i].finalButton.addActionListener(this);
add(ask[i],"Card "+i);
}
}
@Override
public void actionPerformed(ActionEvent evt) {
currentCard++;
if (currentCard >= ask.length) {
System.exit(0);
}
cards.show(this, "Card " + currentCard);
}
}
class SurveyPanel extends JPanel {
JLabel question;
JRadioButton[] response;
JButton nextButton = new JButton("Next");
JButton finalButton = new JButton("Finish");
SurveyPanel(String ques, String[] resp, int def) {
super();
setSize(160, 110);
question = new JLabel(ques);
response = new JRadioButton[resp.length];
JPanel sub1 = new JPanel();
ButtonGroup group = new ButtonGroup();
JLabel quesLabel = new JLabel(ques);
sub1.add(quesLabel);
JPanel sub2 = new JPanel();
for (int i = 0; i < resp.length; i++) {
if (def == i) {
response[i] = new JRadioButton(resp[i], true);
} else {
response[i] = new JRadioButton(resp[i], false);
}
group.add(response[i]);
sub2.add(response[i]);
}
JPanel sub3 = new JPanel();
nextButton.setEnabled(true);
sub3.add(nextButton);
finalButton.setEnabled(false);
sub3.add(finalButton);
GridLayout grid = new GridLayout(3, 1);
setLayout(grid);
add(sub1);
add(sub2);
add(sub3);
}
void setFinalQuestion(boolean finalQuestion) {
if (finalQuestion) {
nextButton.setEnabled(false);
finalButton.setEnabled(true);
}
}
}
import java.awt.*;
import javax.swing.*;
public class SurveyFrame extends JFrame {
public SurveyFrame() {
super("Survey");
setSize(290, 140);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLookAndFeel();
SurveyWizard wiz = new SurveyWizard();
add(wiz);
setVisible(true);
}
private static void setLookAndFeel() {
try {
UIManager.setLookAndFeel(
"javax.swing.plaf.nimbus.NimbusLookAndFeel"
);
} catch (Exception exc) {
System.err.println(exc);
}
}
public static void main(String[] arguments) {
SurveyFrame.setLookAndFeel();
SurveyFrame surv = new SurveyFrame();
}
}
11.3.2 单元格内边距和面板内边距
下面语句创建一个Insets对象,指定上、下内边距为20像素,左右边距为13像素
Insets whitespace = new Insets(20,13,20,13);
// 在容器中可以覆盖getInsets()方法,返回Insets对象指定内边距
public Insets getInsets(){
return new Insets(10,30,10,30);
}