Swing和AWT
介绍java的时候,将图形用户界面相关类捆绑在一起,放在一个称为抽象窗口工具箱(Abstract Window Toolkit,AWT)的库中。AWT适合开发简单的图形用户界面,但并不适合开发复杂的GUI项目。除此之外,AWT更容易发生与特定平台相关的故障。AWT的用户界面组件就被一种更稳定,更通用和更灵活的库取代,这种库称为Swing组件(Swing component)库。大多数Swing组件都是直接用java代码在画布上绘图的,而java.awt.Window或java.awt.Panel的子类的组件例外,它们必须使用在特定平台上自己的GUI 来绘图。Swing组件更少的依赖于目标平台并且更少的使用自己的GUI资源。因此,不依赖于自己GUI的Swing组件称为轻量级组件(lightweight component),而AWT组件称为重量级组件(heavyweight component).
Java GUI API
GUI API包含的类可以分为三个组:组件类(component class),容器类(container class),辅助类(helper class).它们的体系结构如下:
组件类是创建用户界面的,例如,JButton,JLabel和JTextField。容器类是用来包含其他组件的,例如,JFrame,JPanel和JApplet。辅助类是用来支持GUI组件的,例如,Graphics,Color,Font,FontMetrics和Dimension。
组件类
Component 类的实例可以显示在屏幕上。Component类是包括容器类的所有用户界面的根类,而JComponent类是所有轻量级Swing组件类的根类。Component和JComponent都是抽象类。
JButton jbtOK = new JButton("OK");
System.out.println(jbtOK instanceof JButton);
System.out.println(jbtOK instanceof JComponent);
System.out.println(jbtOK instanceof Container);
System.out.println(jbtOK instanceof Component);
System.out.println(jbtOK instanceof Object);
容器类
一个Container的实例可以包含Component实例。容器类是用于盛装其他GUI组件的GUI组件。Window,Panel,Applet,Frame和Dialog都是AWT组件的容器类。要使用Swing组件做容器,可以使用下表的Container,JFrame,JDialog,JApplet和JPanel.
GUI辅助类
辅助类都不是Component的子类,例如,Graphics,Color,Font,FontMetrics,Dimension和LayoutManager等。它们用来描述GUI组件的属性,例如,图形的内容,颜色,字体以及大小尺寸等。
框架
创建一个框架
MyFrame.java代码:
package chapter12;
import javax.swing.JFrame;
public class MyFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame("MyFrame");
frame.setSize(400,300);//Set the frame size
frame.setLocationRelativeTo(null);//Center a frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
直到调用frame.setVisible(true)方法之后才会显示框架。frame.setSize(400,300)指定框架的宽度为400像素,高度为300像素。如果没有使用setSize方法,那么框架的大小就只够显示标题栏。由于setSize和setVisible方法都被定义在Component类中,所以,它们都可以被JFrame类所继承。调用setLocattionRelativeTo(null)方法可以在屏幕上居中显示框架。调用setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)方法来告诉程序,当框架关闭时结束程序。如果不使用这条语句,就会造成关闭框架后程序并不会结束。这种情况下,就必须在Windows系统中的DOS提示符窗口中按下Ctrl+C组合键或者在UNIX系统中使用kill命令来结束这个进程。
向框架中添加组件
代码MyFrameWithComponents.java:
package chapter12;
import javax.swing.*;
public class MyFrameWithComponents
{
public static void main(String[] args)
{
JFrame frame = new JFrame("MyFrameWithComponents");
//Add a button into the frame
JButton jbtOK = new JButton("OK");
frame.add(jbtOK);
frame.setSize(400,300);//Set the frame size
frame.setLocationRelativeTo(null);//Center a frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
布局管理器
FlowLayout
FlowLayout 是最简单的布局管理器。按照组件添加的顺序,从左到右地将组件排列在容器中。当放满一行时,就开始新的一行。可以使用三个常量FlowLayout.RIGHT,FlowLayout.CENTER和FlowLayout.LEFT之一来指定组件的对齐方式。还可以指定组件之间以像素为单位的间隔。
使用FlowLayout管理器向这个框架添加三个标签和文本域.
ShowFlowLayout.java:
package chapter12;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JFrame;
import java.awt.FlowLayout;
public class ShowFlowLayout extends JFrame
{
public ShowFlowLayout()
{
//Set FlowLayout,aligned left with horizontal gap 10
//and vertical gap 20 between components
setLayout(new FlowLayout(FlowLayout.LEFT,10,20));
//Add labels and text fields to the frame
add(new JLabel("First Name"));
add(new JTextField(8));
add(new JLabel("MI"));
add(new JTextField(1));
add(new JLabel("Last Name"));
add(new JTextField(8));
}
public static void main(String[] args)
{
ShowFlowLayout frame = new ShowFlowLayout();
frame.setTitle("ShowFlowLayout");
frame.setSize(200,200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
BorderLayout
BorderLayout管理器将容器分成五个区域:东区,南区,西区,北区和*。使用add(Component,index)方法可以将组件添加到BorderLayout中,其中index是一个常量,取值为BorderLayout.EAST,BorderLayout.SOUTH,BorderLayout.WEST,BorderLayout.NORTH或BorderLayout.CENTER.
package chapter12;
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.BorderLayout;
public class ShowBorderLayout extends JFrame
{
public ShowBorderLayout()
{
//Set BorderLayout with horizontal gap 5 and vertical gap 10
setLayout(new BorderLayout(5,10));
//Add buttons to the frame
add(new JButton("East"),BorderLayout.EAST);
add(new JButton("South"),BorderLayout.SOUTH);
add(new JButton("West"),BorderLayout.WEST);
add(new JButton("North"),BorderLayout.NORTH);
add(new JButton("Center"),BorderLayout.CENTER);
}
public static void main(String[] args)
{
ShowBorderLayout frame = new ShowBorderLayout();
frame.setSize(400,300);//Set the frame size
frame.setLocationRelativeTo(null);//Center a frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
GridLayout
GridLayout管理器以网格(矩阵)的形式管理组件。组件按照它们添加的顺序从左到右排列,先是第一行,接着是第二行,以此类推。
可以指定网格中的行数和列数。基本规则如下:
(1)行数或列数可以为零,但不能两者都为零。如果一个为零另一个不为零,那么不为零的行或列的大小已经固定,而为零的行或列的大小由布局管理器动态的决定。例如,如果指定一个网格有0行3列10个组件,GridLayout就会创建3个固定的列和4个行,最后一行只包含1个组件。如果指定一个网格有3行0列10个组件,GridLayout就会创建3个固定的行和4个列,最后一行包含2个组件。
(2)如果行数和列数都不为零,那么行数就是主导参数;也就是说,行数是固定的,布局管理器会动态的计算列数。例如,如果指定一个网格有3行3列10个组件,GridLayout就会创建3个固定的行和4个列,最后一行包含2个组件。
ShowGridLayout代码:
package chapter12;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JFrame;
import java.awt.GridLayout;
public class ShowGridLayout extends JFrame
{
public ShowGridLayout()
{
//Set GridLayout,3 rows,2 columns,and gaps 5 between
//components horizontally and vertically
setLayout(new GridLayout(3,2,5,5));
//Add labels and text fields to the frame
add(new JLabel("First Name"));
add(new JTextField(8));
add(new JLabel("MI"));
add(new JTextField(1));
add(new JLabel("Last Name"));
add(new JTextField(8));
}
public static void main(String[] args)
{
ShowGridLayout frame = new ShowGridLayout();
frame.setTitle("ShowGridLayout");
frame.setSize(200,125);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
布局管理器的属性
可以动态的改变布局管理器的属性。FlowLayout具有属性alignment,hgap和vgap。可以使用setAlignment,setHgap和setVgap方法来表明对齐方式,水平间隔和垂直间隔。GridLayout具有属性rows,columns,hgap和vgap。可以使用setRows,setColumns,setHgap和setVgap方法来指定行数,列数以及水平间隔和垂直间隔。BorderLayout具有属性hgap和vgap。可以使用setHgap和setVgap方法来指定水平间隔和垂直间隔。
如果需要动态地改变布局管理器的属性,布局管理器必须使用一个变量显示的引用。然后,可以通过这个变量来改变布局管理器的属性。
//Create a layout manager
FlowLayout flowlayout = new FlowLayout();
//Set layout properties
flowLayout.setAlignment(FlowLayout.RIGHT);
flowLayout.setHgap(10);
flowLayout.setVgap(20);
使用面板作为子容器
假设要在框架中放置是个按钮和一个文本域。按钮以网格形式放置,文本域单独占一行。如果将所由这些组件放在一个单独的容器中,是很难达到要求的视觉效果的。使用Java图形用户界面进行程序设计,可以将一个窗口分成几个面板。面板的作用就是分组放置用户界面组件的子容器。可以将这些按钮添加到一个面板中,然后再将这个面板添加到框架中。
面板的Swing版本是JPanel.可以使用new JPanel()创建一个带默认FlowLayout管理器的面板,也可以使用new JPanel(LayoutManager)创建一个带特定布局管理器的面板。使用add(Component)方法可以向面板添加一个组件。例如,下面的代码创建了一个面板并且给他添加一个按钮:
JPanel p = new JPanel();
p.add(new JButton("OK"));
面板可以放到一个框架中或者放在另一个面板中。下面的语句将面板p放到框架f中:
p.add(p);
演示使用面板作为子容器的例子。程序创建了一个微波炉的用户界面.
package chapter12;
import java.awt.*;
import javax.swing.*;
public class TestPanels extends JFrame
{
public TestPanels()
{
//Create panel p1 for the buttons and set GridLayout
JPanel p1 = new JPanel();
p1.setLayout(new GridLayout(4,3));
//Add buttons to the panel
for(int i = 1; i <= 9; i++)
{
p1.add(new JButton("" + i));
}
p1.add(new JButton("" + 0));
p1.add(new JButton("Start"));
p1.add(new JButton("Stop"));
//Create panel p2 to hold a text field and p1
JPanel p2 = new JPanel(new BorderLayout());
p2.add(new JTextField("Time to be displayed here"),BorderLayout.NORTH);
p2.add(p1,BorderLayout.CENTER);
//add contents into frame
add(p2,BorderLayout.EAST);
add(new JButton("Food to be placed here"),BorderLayout.CENTER);
}
public static void main(String[] args)
{
TestPanels frame = new TestPanels();
frame.setTitle("The Front View of a MicroWave Oven");
frame.setSize(400,250);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Color类
可以使用java.awt.Color类为GUI组件设置颜色。颜色是由红,绿,蓝这三原色构成的,每种原色都用一个int值表示它的深度,取值范围从0(最暗度)到255(最亮度)。这就是通常所说的RGB模式(RGB model)
可以使用下面的构造方法创建一个color对象:
public color(int r,int g,int b);
其中r,g和b指定某个颜色的红,绿,蓝成分。例如:
Color color = new Color(128,100,100);
注意参数r,g和b的取值都在0到255之间。如果传递给参数的值超过这个范围,就会导致一个IllegalArgumentException异常
可以使用定义在java.awt.Component类中的setBackground(Color c)和setForeground(Color c)方法来设置一个组件的背景色和前景色。下面是设置一个背景色和前景色的例子:
JButton jbtOK = new JButton("OK");
jbtOK.setBackground(color);
jbtOK.setForeground(new Color(100,1,1));
还可以选择使用java.awt.Color中定义为常量的13种标准颜色(BLACK黑色,BLUE蓝色,CYAN青色,DARK_GRAY深灰,GRAY灰色,GREEN绿色,LIGHT_GRAY浅灰,MAGENTA洋红,ORANGE橘色,PINK粉红,RED大红,WHITE白色,YELLOW黄色)之一.
例如,下面的代码可以将按钮的前景色设置成红色:
jbtOK.setForeground(Color.RED);
Font类
可以使用java.awt.Font类创建一种字体,然后使用Component类中的SetFont方法设置组件的字体.
Font的构造方法是:
public Font(String name,int style,int size);
可以从SansSerif,Serif,Monospaced,Dialog或DialogInput中选择一种字体名,可以从Font.PLAIN(0),Font.BOLD(1),Font.ITALIC(2)和Font.BOLD+Font.ITALIC(3)中选择风格,然后指定正整数的字体大小。例如,下面的语句创建两种字体,并且给按钮设置一种字体:
Font font1 = new Font("SansSerif",Font.BOLD,16);
Font font2 = new Font("Serif",Font.BOLD + Font.ITALIC,12);
JButton jbtOK = new JButton("OK");
jbtOK.setFont(font1);
Swing GUI组件的公共特性
Component类是所有GUI组件和容器的根,所有Swing GUI组件(除了JFrame,JApplet和JDialog)都是JComponent的子类,下图列出了Component,Container和JComponent中对像字体,颜色,大小,工具提示文本及其边界这样的属性的常用操作方法.
以下例创建一个面板p1放置三个按钮,创建p2放置两个标签,按钮jbtLeft的背景色设置为白色,按钮jbtCenter的前景色设置为绿色.按钮jbtRight的工具提示设置,在面板p1和p2上设置标题边界,而在标签上设置线边界.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class TestSwingCommonFeatures extends JFrame {
public TestSwingCommonFeatures() {
// Create a panel to group three buttons
JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2));
JButton jbtLeft = new JButton("Left");
JButton jbtCenter = new JButton("Center");
JButton jbtRight = new JButton("Right");
jbtLeft.setBackground(Color.WHITE);
jbtCenter.setForeground(Color.GREEN);
jbtRight.setToolTipText("This is the Right button");
p1.add(jbtLeft);
p1.add(jbtCenter);
p1.add(jbtRight);
p1.setBorder(new TitledBorder("Three Buttons"));
// Create a font and a line border
Font largeFont = new Font("TimesRoman", Font.BOLD, 20);
Border lineBorder = new LineBorder(Color.BLACK, 2);
// Create a panel to group two labels
JPanel p2 = new JPanel(new GridLayout(1, 2, 5, 5));
JLabel jlblRed = new JLabel("Red");
JLabel jlblOrange = new JLabel("Orange");
jlblRed.setForeground(Color.RED);
jlblOrange.setForeground(Color.ORANGE);
jlblRed.setFont(largeFont);
jlblOrange.setFont(largeFont);
jlblRed.setBorder(lineBorder);
jlblOrange.setBorder(lineBorder);
p2.add(jlblRed);
p2.add(jlblOrange);
p2.setBorder(new TitledBorder("Two Labels"));
// Add two panels to the frame
setLayout(new GridLayout(2, 1, 5, 5));
add(p1);
add(p2);
}
public static void main(String[] args) {
// Create a frame and set its properties
JFrame frame = new TestSwingCommonFeatures();
frame.setTitle("TestSwingCommonFeatures");
frame.setSize(300, 150);
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
图像图标
图标是一个大小固定的图片;通常情况下,他都比较小,用来装饰组件。头像通常存储在图像文件中。Java目前支持三种头像格式:GIF(图像交换格式),JPEG(联合图像专家组),以及PNG(便携网络图片).为了使用一个图像图标,首先使用new java.swing.ImageIcon(filename)创建一个ImageIcon对象.例如,下面的语句使用当前路径下的image目录的图像文件us.gif来创建一个图标:
ImageIcon icon = new ImageIcon("image/us.gif");
使用new JLabel(imageIcon)或new JButton(imageIcon)在标签或按钮上显示图像图标。
创建两个带图标的标签和两个带图标的按钮
import javax.swing.*;
import java.awt.*;
public class TestImageIcon extends JFrame {
private ImageIcon usIcon = new ImageIcon("image/us.gif");
private ImageIcon myIcon = new ImageIcon("image/my.jpg");
private ImageIcon frIcon = new ImageIcon("image/fr.gif");
private ImageIcon ukIcon = new ImageIcon("image/uk.gif");
public TestImageIcon() {
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(usIcon));
add(new JLabel(myIcon));
add(new JButton(frIcon));
add(new JButton(ukIcon));
}
/** Main method */
public static void main(String[] args) {
TestImageIcon frame = new TestImageIcon();
frame.setTitle("TestImageIcon");
frame.setSize(500, 125);
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}