使用的教材是java核心技术卷1,我将跟着这本书的章节同时配合视频资源来进行学习基础java知识。
day076 Swing用户界面组件(二:布局管理概述)(边框布局、网格布局)
布局管理概述
在讨论每个Swing组件(例如:文本域和单选按钮)之前,首先介绍一下如何把这些组件排列在一个框架内。与VisualBasic不同,由于在JDK中没有表单设计器,所以需要通过编写代码来定制(布局)用户界面组件所在的位置。当然,如果有支持Java的开发环境,就可能有某种布局工具来部分自动地或全部自动地完成这些布局任务。然而,弄清底层的实现方式是非常重要的,因为即使最好的工具有时也需要手工编码。回顾之前的程序,我们设计了几个按钮,点击这些按钮可以改变框架的背景颜色。如图所示。这几个按钮被放置在一个JPanel对象中,且用流布局管理器(flowlayoutmanager)管理,这是面板的默认布局管理器。图2展示了向面板中添加多个按钮后的效果。正如读者所看到的,当一行的空间不够时,会将显示在新的一行上。
另外,按钮总是位于面板的中央,即使用户对框架进行缩放也是如此。如图所示。通常,组件放置在容器中,布局管理器决定容器中的组件具体放置的位置和大小。按钮、文本域和其他的用户界面元素都继承于Component类,组件可以放置在面板这样的容器中。由于Container类继承于Component类,所以容器也可以放置在另一个容器中。图2给出了Component的类层次结构。
1.边框布局
边框布局管理器(borderlayoutmanager)是每个JFrameI的内容窗格的默认布局管理器。流布局管理器完全控制每个组件的放置位置,边框布局管理器则不然,它允许为每个组件选择一个放置位置。可以选择把组件放在内容窗格的中部、北部、南部、东部或者西部。如图
例如:frame,add(component,BorderLayout.SOUTH);
先放置边缘组件,剩余的可用空间由中间组件占据。当容器被缩放时,边缘组件的尺寸不会改变,而中部组件的大小会发生变化。在添加组件时可以指定BorderLayout类中的CENTER、NORTH、SOUTH、EAST和WEST常量。并非需要占用所有的位置,如果没有提供任何值,系统默认为CENTER。
与流布局不同,边框布局会扩展所有组件的尺寸以便填满可用空间(流布局将维持每个组件的最佳尺寸)。当将一个按钮添加到容器中时会出现问题:frame.add(yellowButton,BorderLayout.SOUTH);//don't
图1给出了执行上述语句的显示效果。按钮扩展至填满框架的整个南部区域。而且,如果再将另外一个按钮添加到南部区域,就会取代第一个按钮。解决这个问题的常见方法是使用另外一个面板(panel)。例如,如图2所示。屏幕底部的三个按钮全部包含在一个面板中。这个面板被放置在内容窗格的南部。
要想得到这种配置效果,首先需要创建一个新的 JPanel 对象,然后逐一将按钮添加到面板中。面板的默认布局管理器是HowLayout,这恰好符合我们的需求。随后使用在前面已经看到的add方法将每个按钮添加到面板中。每个按钮的放置位置和尺寸完全处于FlowLayout布局管理器的控制之下。这意味着这些按钮将置于面板的中央,并且不会扩展至填满整个面板区域。最后,将这个面板添加到框架的内容窗格中。
JPanel panel = newJPanel();
panel.add(yellowButton);
panel.add(blueButton);
panel.add(redButton);
frame.add(panel, BorderLayout.SOUTH);
边框布局管理器将会扩展面板大小,直至填满整个南部区域。
2.网格布局
网格布局像电子数据表一样,按行列排列所有的组件。不过,它的每个单元大小都是一样的。计算器程序就使用了网格布局来排列计算器按钮。当缩放窗口时,计算器按钮将随之变大或变小,但所有的按钮尺寸始终保持一致。在网格布局对象的构造器中,需要指定行数和列数:panel.setLayout(new CridLayout(4, 4));
添加组件,从第一行的第一列开始,然后是第一行的第二列,以此类推。
panel.add(newJButton("l"));
panel.add(newJButton("2"));
下面的程序是计算器程序的源代码。这是一个常规的计算器,而不像Java指南中所提到的“逆波兰”那样古怪。在这个程序中,在将组件添加到框架之后,调用了pack方法。这个方法使用所有组件的最佳大小来计算框架的高度和宽度。当然,极少有像计算器这样整齐的布局。实际上,在组织窗口的布局时小网格(通常只有一行或者一列)比较有用。例如,如果想放置一行尺寸都一样的按钮,就可以将这些按钮放置在一个面板里,这个面板使用只有一行的网格布局进行管理。
/**
*@author zzehao
*/
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
/**
* 设计一个计算器
*/
public class CalculatorPanel extends JPanel
{
private JButton display;
private JPanel panel;
private double result;
private String lastCommand;
private boolean start;
//返回组件的首选大小
public Dimension getPreferredSize()
{
return new Dimension(300,200 );
}
public CalculatorPanel()
{
//构造一个新的边界布局,在组件之间没有间隙。
setLayout( new BorderLayout() );
result = 0;
lastCommand = "=";
start = true;
//用一个不可以点击的按钮作为计算器的显示栏
display = new JButton("0");
display.setEnabled(false);
add( display, BorderLayout.NORTH );//边框布局的使用
//数字键和符号键会发出两种事件,分别处理
ActionListener insert = new InsertAction();
ActionListener command = new CommandAction();
panel = new JPanel();
panel.setLayout(new GridLayout(4, 4));//网格布局的使用,4行4列
//向panel中添加按钮,并且该方法会让按钮绑定一个监听器
addButton("7", insert);
addButton("8", insert);
addButton("9", insert);
addButton("/", command);
addButton("4", insert);
addButton("5", insert);
addButton("6", insert);
addButton("*", command);
addButton("1", insert);
addButton("2", insert);
addButton("3", insert);
addButton("-", command);
addButton("0", insert);
addButton(".", insert);
addButton("=", command);
addButton("+", command);
add( panel, BorderLayout.CENTER );//边框布局的使用
}
private void addButton(String label, ActionListener listener)
{
JButton button = new JButton( label );
button.addActionListener(listener);
panel.add(button);
}
private class InsertAction implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e) {
//返回与此操作相关联的命令字符串
String input = e.getActionCommand();
//开始时start是true,若按了任意数字键,先将显示栏清空
if( start )
{
display.setText("");
start = false;
}
//将原有的数字和现在点击的数字键字符拼接
display.setText(display.getText() + input);
}
}
private class CommandAction implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
String command = e.getActionCommand();
//刚开始时的符号只有 - 能算数
if( start )
{
//这里-是负号的意思,表示负数
if( command.equals("-") )
{
display.setText(command);
start = false;
}else
{
lastCommand = command;
}
}
else
{
//默认设置了一个result和一个输入做运算,得到的结果放入result中
calculate(Double. parseDouble( display.getText() ));
lastCommand = command;
start = true;
}
}
}
public void calculate(double x)
{
if( lastCommand.equals("+") )
result += x;
else if( lastCommand.equals("-") )
result -= x;
else if( lastCommand.equals("*") )
result *= x;
else if( lastCommand.equals("/") )
result /= x;
else if( lastCommand.equals("=") )
result = x;
display.setText(""+result);
}
}
/**
*@author zzehao
*/
import java.awt.EventQueue;
import javax.swing.JFrame;
public class CalFrame extends JFrame
{
public CalFrame()
{
add(new CalculatorPanel());
pack();//更加组件的首选大小,调整窗口
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new CalFrame();//初始化窗口
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置:关闭窗口,则程序退出
frame.setVisible(true);//显示窗口
}
});
}
}
运行的结果是: