GUI全称是Graphical User Interface,即图形用户界面。
Java中针对GUI设计提供了丰富的类库,这些类分别位于java.awt和javax.swing包中,简称为AWT和Swing。
AWT是用于创建图形用户界面的一个工具包,它提供了一系列用于实现图形界面的组件,如窗口、按钮、文本框、对话框等。在JDK中针对每个组件都提供了对应的Java类,这些类都位于java.awt包中,接下来通过一个图例来描述这
些类的继承关系,如图所示。
从图的继承关系可以看出,在AWT中组件分为两大类,这两类的基类分别是Component和MenuComponent。其中,MenuComponent是所有与菜单相关组件的父类,Component则是除菜单外其他AWT组件的父类,它表示一个能
以图形化方式显示出来,并可与用户交互的对象。
Component类通常被称为组件,根据Component的不同作用,可将其分为基本组件类和容器类。基本组件类是诸如按钮、文本框之类的图形界面元素,而容器类则是通过Component的子类Container实例化的对象。Container类表示容器,它是一种特殊的组件,可以用来容纳其他组件。Container容器又分为两种类型,分别是Window和Panel
Window类是不依赖其他容器而独立存在的容器,它有两个子类,分别是Frame类和Dialog类。Frame类用于创建一个具有标题栏的框架窗口,作为程序的主界面,Dialog类用于创建一个对话框,实现与用户的信息交互
Panel也是一个容器,但是它不能单独存在,只能存在其他容器(Window或其子类)中,一个Panel对象代表了一个长方形的区域,在这个区域中可以容纳其他组件。在程序中通常会使用Panel来实现一些特殊的布局。
import java.awt.*;
public class FrameEx {
public static void main(String[] args) {
Frame frame=new Frame("我的窗口");
frame.setSize(800,300);
frame.setLocation(600,200);
frame.setVisible(true);
}
}
组件不能单独存在,必须放置于容器当中,而组件在容器中的位置和尺寸是由布局管理器来决定的。
在java.awt包中提供了多种布局管理器,包括FlowLayout(流式布局管理器)、BorderLayout(边界布局管理器)、GridLayout(网格布局管理器)和CardLayout(卡片布局管理器)。每个容器在创建时都会使用一种默认的布局管理器,在程序中可以通过调用容器对象的setLayout()方法设置布局管理器,通过布局管理器来自动进行组件的布局管理。
例如把一个Frame窗体的布局管理器设置为FlowLayout,代码如下所示:
Frame frame = new Frame();
frame.setlayout(new FlowLayout());
最简单的布局管理器,在这种布局下,容器会将组件按照添加顺序从左向右放置。当到达容器的边界时,会自动将组件放到下一行的开始位置。这些组件可以左对齐、居中对齐(默认方式)或右对齐的方式排列。FlowLayout对象有三个构造方法,如表所示。
表中,列出了FlowLayout的三个构造方法,其中,参数align决定组件在每行中相对于容器边界的对齐方式,可以使用该类中提供的常量作为参数传递给构造方法,其中FlowLayout.LEFT用于表示左对齐、FlowLayout.RIGHT用于表示右对齐、FlowLayout.CENTER用于表示居中对齐。参数hgap和参数vgap分别设定组件之间的水平和垂直间隙,可以填入一个任意数值。
import java.awt.*;
public class FlowEx {
public static void main(String[] args) {
final Frame f=new Frame("flowlayout");
f.setLayout(new FlowLayout(FlowLayout.LEFT,20,30));
f.setSize(220,300);
f.setLocation(300,200);
f.setVisible(true);
f.add(new Button("第1个按钮"));
f.add(new Button("第2个按钮"));
f.add(new Button("第3个按钮"));
f.add(new Button("第4个按钮"));
f.add(new Button("第5个按钮"));
f.add(new Button("第6个按钮"));
}
}
一种较为复杂的布局方式,它将容器划分为五个区域,分别是东(EAST)、南(SOUTH)、西(WEST)、北(NORTH)、中(CENTER)。组件可以被放置在这五个区域中的任意一个。BorderLayout布局的效果如图所示。
从图可以看出BorderLayout边界布局管理器,将容器划分为五个区域,其中箭头是指改变容器大小时,各个区域需要改变的方向。也就是说,在改变容器时NORTH和SOUTH区域高度不变长度调整,WEST和EAST区域宽度不变高度调整,CENTER会相应进行调整。
当向BorderLayout布局管理器的容器中添加组件时,需要使用add(Component comp,Object constraints)方法。其中参数comp表示要添加
的组件,constraints指定将组件添加到布局中的方式和位置的对象,它是一个Object类型,在传参时可以使用BorderLayout类提供的5个常量,它们分别是EAST、SOUTH、WEST、NORTH和CENTER。
import java.awt.*;
public class BorderEx {
public static void main(String[] args) {
final Frame f=new Frame("border layout");
f.setLayout(new BorderLayout());
f.setSize(300,300);
f.setLocation(300,300);
f.setVisible(true);
f.add(new Button("东部"),BorderLayout.EAST);
f.add(new Button("西部"),BorderLayout.WEST);
f.add(new Button("北部"),BorderLayout.NORTH);
f.add(new Button("南部"),BorderLayout.SOUTH);
f.add(new Button("中部"), BorderLayout.CENTER);
}
}
使用纵横线将容器分成n行m列大小相等的网格,每个网格中放置一个组件。添加到容器中的组件首先放置在第1行第1列(左上角)的网格中,然后在第1行的网格中从左向右依次放置其他组件,行满后,继续在下一行中从左到右放置组件。与FlowLayout不同的是,放置在
GridLayout布局管理器中的组件将自动占据网格的整个区域。
GridLayout的构造方法,如表所示。
表中,列出了GridLayout的三个构造方法,其中,参数rows代表行数,cols代表列数,hgap和vgap规定水平和垂直方向的间隙。水平间隙指的是网格之间的水平距离,垂直间隙指的是网格之间的垂直距离。
import java.awt.*;
public class GridEx {
public static void main(String[] args) {
Frame f=new Frame("grid layout");
f.setLayout(new GridLayout(3,3));
f.setSize(300,300);
f.setLocation(300,300);
for(int i=0;i<6;i++){
f.add(new Button("byn"+i));
}
f.setVisible(true);
}
}
在操作程序时,经常会遇到通过选项卡按钮来切换程序中的界面,这些界面就相当于一张张卡片,而管理这些卡片的布局管理器就是卡片布局管理器(CardLayout)。卡片布局管理器将界面看做是一系列卡片,在任何时候只有其中一张卡片是可见的,这张卡片占据容器的整个区域。
在CardLayout布局管理中经常会用到下面几个方法,如表所示。
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CardEx {
public static void main(String[] args) {
Frame frame=new Frame();
frame.setSize(300,300);
frame.setVisible(true);
CardLayout cardLayout=new CardLayout();
Panel cardPanel=new Panel();
cardPanel.setLayout(cardLayout);
cardPanel.add(new Label("第一个界面",Label.CENTER));
cardPanel.add(new Label("第二个界面"),Label.CENTER);
cardPanel.add(new Label("第三个界面"),Label.CENTER);
Panel controlPanel=new Panel();
Button nextButton=new Button("下一张卡片");
Button preButton=new Button("上一张卡片");
controlPanel.add(nextButton);
controlPanel.add(preButton);
frame.add(cardPanel,BorderLayout.NORTH);
frame.add(controlPanel,BorderLayout.SOUTH);
nextButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.next(cardPanel);
}
});
preButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.previous(cardPanel);
}
});
}
}
当一个容器被创建后,它们都会有一个默认的布局管理器。Window、Frame和Dialog的默认布局管理器是BorderLayout,Panel的默认布局管理器是FlowLayout。如果不希望通过布局管理器来对容器进行布局,也可以调用容器的setLayout(null)方法,将布局管理器取消。在这种情况下,程序必须调用容器中每个组件的setSize()和setLocation()方法或者是setBounds()方法(这个方法接收四个参数,分别是左上角的x、y坐标和组件的长、宽)来为这些组件在容器中定位。
import java.awt.*;
public class NoLayoutEx {
public static void main(String[] args) {
Frame frame=new Frame("hello world");
frame.setLayout(null);
frame.setSize(300,300);
Button btn1=new Button("press");
Button btn2=new Button("pop");
btn1.setBounds(40,60,100,30);
btn2.setBounds(140,90,100,30);
frame.add(btn1);
frame.add(btn2);
frame.setVisible(true);
}
}