一、AWT

1、AWT

JAVA使用AWT和Swing 类完成图形用户界面编程,AWT全称是抽象窗口工具集(Abstract Window Toolkit),它是最早的sun提供的GUI库(Graphics User Interface)图形用户界面。

AWT是窗口框架,它从不同平台的窗口系统中抽取共同组件,当使用AWT编写图形界面应用时,程序仅指定了界面组件的位置和行为,并为提供真正的实现,JVM 调用操作系统本地的图形界面来创建和平台一直的对等体。

2、AWT继承体系

所有和AWT编程相关的类都放在java.awt包以及他的子包中,AWT中有两个基类:Component和MenuComponent

  • Component:代表一个能以图形化方式显示出来,并可与用户交换的对象
  • MenuComponent:代表图形界面的菜单组件,包括菜单条、菜单项等子类

二、AWT容器

1、AWT容器

容器(Container)是Component的子类,因此容器对象本身也是一个组件,具有组件的所有性质,可以调用Component类的所有方法,Component类提供了几个常用方法设置组件的大小,位置和可见性:

  1. setLocation(int x, int y):设置组件的位置。
  2. setSize(int width, int height):设置组件的大小。
  3. setBounds(int x, int y, int width, int height):同时设置组件的位置、大小。
  4. setVisible(Boolean b):设置该组件的可见性。

Container容器,此容器还可以盛装其他组件,其提供了如下几个常用方法来访问容器里的组件。

  1. Component add(Component comp):向容器中添加其他组件(该组件既可以是普通组件,也可以是容器),并返回被添加的组件。
  2. Component getComponentAt(int x, int y):返回指定点的组件。
  3. int getComponentCount():返回该容器内组件的数量。
  4. Component getComponents():返回该容器内的所有组件。

2、AWT容器类型

AWT主要提供的容器类型:

  1. Window:可独立存在的顶级窗口,默认为BorderLayout布局管理器。
  2. Panel:可作为容器容纳其他组件,但不能独立存在,必须被添加到其他容器中(如 Window、Panel 或者 Applet等)。默认为FlowLayout布局管理器。
  3. ScrollPane:含有滚动条的容器,默认为BorderLayout布局管理器。

如下使用Frame创建一个窗口:

public static void main(String[] args) {     
	Frame f = new Frame("测试窗口"); 
  	f.setBounds(240,240,100,100);   //设置窗口大小,位置 
  	f.setVisible(true); 
}

常用的关闭窗口方法有以下4种

  1. DO NOTHING _ON_CLOSE       //代表什么都不做就能把窗口关闭
  2. DISPOSE_ON_CLOSE     //代表任何注册监听程序对象后会自动隐藏并释放窗体
  3. HIDE_ON_CLOSE     //表示隐藏窗口的默认窗口关闭
  4. EXIT_ON_CLOS     //表示退出应用程序默认窗口关闭

Panel是AWT中另一种典型的容器,他代表不能独立存在,必须放在其他容器中过的容器。Panel外在表现为一个矩形区域,该区域内可盛装其他组件,Panel容器存在的意义在于为其他组件提供空间,Panel容器特点如下:

  1. 可作为容器来盛装其他组件,为放置组件提供空间
  2. 不能单独存在,必须放置在其他容器中
  3. 默认使用FlowLayout作为其布局管理器

如下使用Pane作为容器盛装个按钮和一个文本框,并将该Panel对象添加到Frame对象中:

public static void main(String[] args) {
    Frame f = new Frame("测试窗口");
    //创建一个Panel容器
    Panel p = new Panel();
    //向容器中添加两个组件
    p.add(new TextField(20));
    p.add(new Button("按钮"));
    //将Panel容器添加到Frame窗口中
    f.add(p);
    //设置窗口大小,位置
    f.setBounds(240,240,100,100);
    //将窗口显示出来
    f.setVisible(true);
}

ScrollPane是一个带滚动条的容器,他不独立存在,必须被添加到其他容器中,ScrollPane具有以下几个特点:

  1. 可作为容器来盛装其他组件,当组件占用空间过大时,ScrollPane自动产生滚动条。当然也可以通过指定特定的构造器参数来指定默认具有滚动条
  2. 不能单独存在,必须放在其他容器中
  3. 默认使用BorderLayout作为布局管理器

如下使用ScrollPane容器代替Panel容器:

public static void main(String[] args) {
    Frame f = new Frame("测试窗口");
    //创建一个ScrollPanel容器,指定总是具有滚动条
    ScrollPane sp = new  ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);
    //向ScrollPanel容器中添加两个组件
    sp.add(new TextField(20));
    sp.add(new Button("单击此处"));
    //将ScrollPanel容器添加到Frame对象中
    f.add(sp);
    //设置窗口大小、位置
    f.setBounds(30,30,250,120);
    //将窗口显示出来
    f.setVisible(true);
}

三、布局管理器

1、FlowLayout

FlowLayout布局管理器中,组件像水流一样向某方向流动(排列),遇到障碍(边界)就会折回,重头开始排列,默认情况下,FlowLayout布局管理器从左向右排列所有组件,遇到边界就会折回下一行重新开始。

FlowLayout有三个构造器:

  1. FlowLayout():使用默认对齐方式及默认的垂直间距,水平间距创建FlowLayout布局管理器
  2. FlowLayout(int align):使用指定的对齐方式及默认的垂直间距、水平间距创建FlowLayout布局管理器
  3. FlowLayout(int align,int hgap,int vgap):使用指定的对齐方式及指定的水平间距、垂直间距创建FlowLayout布局管理器,其中align代表FlowLayout中组件的排列方向(从左向右、从右向左、从中间向两边),该参数使用FlowLayout类的静态常量:FlowLayout.LEFT、FlowLayout.CERTER、FlowLayout.RIGHT

如下将Frame改为使用FlowLayout布局管理器

public static void main(String[] args) {
    Frame f = new Frame("测试窗口");
    //设置Frame容器使用FlowLayout布局管理器
    f.setLayout(new  FlowLayout(FlowLayout.LEFT,20,5));
    //向窗口中添加10个按钮
    for(int i =1;i<=10;i++) {
        f.add(new Button("Button "+i));
    }
    //设置窗口为最佳大小
    f.pack();
    //将窗口显示出来
    f.setVisible(true);
}

2、BorderLayout布局管理器

BorderLayout 将容器分为 EAST、SOUTH、WEST、NORTH、CENTER (东、南、西、北、中心)五个区域,普通组件可以被放置在这 5 个区域的任意一个中。当改变使用 BorderLayout 的容器大小时,NORTH、SOUTH 和 CENTER区域水平调整,而 EAST、WEST 和 CENTER 区域垂直调整。BorderLayout最多可以放5个组件,如果某个区域没有放置组件时,旁白你的区域就会自动占据该区域。

使用BorderLayout 有如下两个注意点:

  1. 当向使用 BorderLayout 布局管理器的容器中添加组件时,需要指定要添加到哪个区域中。如果没有指定添加到哪个区域中,则默认添加到中间区域中。
  2. 如果向同一个区域中添加多个组件时,后放入的组件会覆盖先放入的组件。

BorderLayout有两个构造器:

  1. BorderLayout():使用默认的水平间距、垂直间距创建BorderLayout布局管理器
  2. BorderLayout(int hgap,int vgap):使用指定的水平间距,垂直间距创建BorderLayout布局管理器

如下将Frame改为使用BorderLayout布局管理器

public static void main(String[] args) {
    Frame f = new Frame("测试窗口");
    //设置Frame容器使用BorderLayout布局管理器
    f.setLayout(new BorderLayout(20,5));
    //向窗口中添加按钮
    f.add(new Button("东"),EAST);
    f.add(new Button("西"),WEST);
    f.add(new Button("南"),SOUTH);
    f.add(new Button("北"),NORTH);
    f.add(new Button("中"));
    //设置窗口为最佳大小
    f.pack();
    //将窗口显示出来
    f.setVisible(true);
}

3、GridBagLayout布局管理器

GridLayout 布局管理器将容器分割成纵横线分隔的网格,每个网格所占的区域大小相同。当向使用GridLayout 布局管理器的容器中添加组件时,默认从左向右、从上向下依次添加到每个网格中。与FlowLayout 不同的是,放置在 GridLayout 布局管理器中的各组件的大小由组件所处的区域来决定(每个组件将自动占满整个区域)。

GridLayout 有如下两个构造器。

  1. GridLayout(int rows,int cols):采用指定的行数、列数,以及默认的横向间距、纵向间距将容器分割成多个网格。
  2. GridLayout(int rows,int cols,int hgap,int vgap):采用指定的行数、列数,以及指定的横向间距、纵向间距将容器分割成多个网格。

如下将Frame改为使用GridLayout布局管理器

public static void main(String[] args) {
    Frame f = new Frame("计算器");
    Panel p1 = new Panel();
    p1.add(new TextField(30));
    f.add(p1.NORTH);
    Panel p2 = new Panel();
    p2.setLayout(new GridLayout(3,5,4, 4));
    String[] name = {"0","1","2","3","4","5","6","7","8","9","0","+","-","*","%","."};
    //向Panel中依次添加15个元素
    for(int i=1;i<=name.length;i++){
        p2.add(new Button(name[i]));
    }
    //默认将Panel对象添加到Frame窗口的中间
    f.add(p2);
    //设置窗口为最佳大小
    f.pack();
    //将窗口显示出来
    f.setVisible(true);
}

4、GridBagLayout布局管理器 

GridBagLayout 布局管理器的功能最强大,但也最复杂,与 GridLayout 布局管理器不同的是,在GridBagLayout 布局管理器中,一个组件可以跨越一个或多个网格,并可以设置各网格的大小互不相同,从而增加了布局的灵活性。当窗口的大小发生变化时,GridBagLayout 布局管理器也可以准确地控制窗口各部分的拉伸。为了处理 GridBagLayout 中 GUI 组件的大小、跨越性,Java 提供了 GridBagConstraints 对象,该对象与特定的 GUI 组件关联,用于控制该 GUI 组件的大小、跨越性。

使用GridBagLayout布局管理器步骤如下:

    1、创建GridBagLayout布局管理器,并指定GUI容器使用该布局管理器

GridBagLayout gb = new GridBagLayout();
container.setLayout(gb);

    2、创建GridBagConstraints对象,并设置该对象的相关属性(用于设置受该对象控制的GUI组件的大小、跨越性等)

gbc.gridx = 2;    //设置受该对象控制的GUI组件位于网络的横向索引
gbc.gridy = 1;    //设置受该对象控制的GUI组件位于网络的纵向索引
gbc.gridwidth = 2;    //设置受该对象控制的GUI的组件横向跨越多少网格
gbc.gridheight = 1;    //设置受该对象控制值得GUI组件纵向跨越多少网格

    3、调用GridBagLayout对象方法来建立GridBagConstraints对象和受控组件之间的关联

gb.setConstraints(c.gbc);    //设置c组件受gbc对象控制

    4、添加组件,与采用普通布局管理器添加组件的方法完全一样

container.add(c);

    GridBagLayout有7中属性:

  1. gridx、gridy:横向索引、纵向索引
  2. gridwidth、gridheight:设置受该对象控制的GUI组件横向、纵向跨越多少个网格
  3. fill:设置受该对象控制的GUI组件如何占据空白区域
  4. ipadx、ipady:设置受该对象控制的GUI组件横向、纵向内部填充的大小
  5. insets:设置受该对象控制的GUI组件的外部填充的大小
  6. anchor:设置受该对象控制的GUI组件在其显示区域的定位方式
  7. weightx、weighty:设置受该对象控制的GUI组件占据多余空间的水平、垂直增加比例,这两个属性的默认值是0

如何使用GridBagLayout布局管理器来管理窗口

public class GridBagLayout {
        private Frame f = new Frame("测试窗口");
        private GridBagLayout gb = new GridBagLayout();
        private GridBagConstraints gbc = new GridBagConstraints();
        private Button[] bs = new Button[10];
        public void init() {
            f.setLayout(gb);
            for (int i = 0; i < bs.length; i++) {
                bs[i] = new Button("按钮" + i);
            }
            //所有组件都可以在横向、纵向上扩大
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weightx = 1;
            addButton(bs[0]);
            addButton(bs[1]);
            addButton(bs[2]);
            //该GridBagConstraints控制的GUI组件将会成为横向最后一个组件
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            addButton(bs[3]);
            //该GridBagConstraints控制的GUI组件将在横向上不会扩大
            gbc.weightx = 0;
            addButton(bs[4]);
            //该GridBagConstraints控制的GUI组件将横跨两个网格
            gbc.gridwidth = 2;
            addButton(bs[5]);
            //该GridBagConstraints控制的GUI组件将横跨一个网格
            gbc.gridwidth = 1;
            //该GridBagConstraints控制的GUI组件将在纵向上跨两个网格
            gbc.gridwidth = 2;
            //该GridBagConstraints控制的GUI组件将会成为横向最后一个组件
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            addButton(bs[6]);
            //该GridBagConstraints控制的GUI组件纵向扩大的权重为1
            gbc.weighty = 1;
            addButton(bs[7]);
            //设置下面的按钮不会在纵向上扩大
            gbc.weighty = 0;
            //该GridBagConstraints控制的GUI组件将会成为横向最后一个组件
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            //该GridBagConstraints控制的GUI组件将在纵向上横跨一个网格
            gbc.gridwidth = 1;
            addButton(bs[8]);
            addButton(bs[9]);
            f.pack();
            f.setVisible(true);
        }
        private void addButton(Button button) {
            gb.setConstraints(button, gbc);
            f.add(button);
        }
    public static void main (String[]args){
        new GridBagLayout().init();
    }
}

5、CardLayout布局管理器

CardLayout将加入容器的所有组件看成一叠卡片,每次只有最上面的那个Component才可见。

CardLayout提供了两个构造器:

  1. CardLayout():创建默认的CardLayout布局管理器
  2. CardLayout(int hgap,int vgap):通过指定卡片与容器左右边界的间距(hgap)、上下边界(vgap)的间距来创建CardLayout布局管理器

CardLayout用于组件控制的5个常用方法:

  1. frist(Container target):显示target容器中的第一张卡片
  2. last(Container target):显示target容器中的最后一张卡片
  3. previous(Container target):显示target容器中的前一张卡片
  4. next(Container target):显示target容器中的后一张卡片
  5. show(Container target,String name):显示target容器中的指定名字的卡片

如何使用CardLayout布局管理器来管理窗口

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class AWTTest {
    public static void main(String[] args) {
        Frame frame = new Frame("test");
        //创建一个Panel,用来存储多张卡片
        Panel p1 = new Panel();
        //创建CardLayout,并且把该对象设置给之前创建的容器
        CardLayout cardLayout = new CardLayout();
        p1.setLayout(cardLayout);
        //往Panel中存储多个组件
        String[] names = {"第一张", "第二张", "第三张", "第四张", "第五张"};
        for (int i = 1; i < names.length; i++) {
            p1.add(names[i], new Button(names[i]));
        }
        //把Panel放到frame的中间区域
        frame.add(p1);
        //创建另外一个Panel p2,用来存储多个按钮组件
        Panel p2 = new Panel();
        //创建5个按钮组件
        Button b1 = new Button("上一张");
        Button b2 = new Button("下一张");
        Button b3 = new Button("第一张");
        Button b4 = new Button("最后一张");
        Button b5 = new Button("第三张");
        /**
         frame.add(new Button("上一张"));
         frame.add(new Button("下一张"));
         frame.add(new Button("第一张"));
         frame.add(new Button("最后一张"));
         frame.add(new Button("第三张"));
         */
        //创建一个事件监听器,监听按钮的点击动作
        ActionListener listener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String actionCommand = e.getActionCommand();    //字符串为按钮上的文字
                switch (actionCommand) {
                    case "上一张":
                        cardLayout.previous(p1);
                        break;
                    case "下一张":
                        cardLayout.next(p1);
                        break;
                    case "第一张":
                        cardLayout.first(p1);
                        break;
                    case "最后一张":
                        cardLayout.last(p1);
                        break;
                    case "第三张":
                        cardLayout.show(p1, "第三张");
                        break;
                }
            }
        };
        //把当前这个事件监听器和多个按钮绑定到一

6、绝对定位

    绝对定位即就是随意拖动控件,创建绝对定位的步骤如下:

  1. 将Container的布局管理器设成null:setLayout(null)
  2. 向容器中添加组件时,先调用setBounds或setSize()方法来设置组件的大小、位置、或者直接创建GUI组件时通过构造参数指定该组件的大小、位置,然后将该组件添加到容器中。

如何使用绝对定位来控制窗口中的GUI组件

import java.awt.Button;
import java.awt.Frame;
public class NullLayoutTest{
    Frame f = new Frame("测试窗口");
    Button b1 = new Button("第一个按钮");
    Button b2 = new Button("第二个按钮");
    public void init() {
        //设置使用null布局管理器
        f.setLayout(null);
        //下面强制设置每个按钮的大小、位置
        b1.setBounds(20,30,90,28);
        f.add(b1);
        b2.setBounds(50,45,120,35);
        f.add(b2);
        f.setBounds(50,50,200,100);
        f.setVisible(true);
    }
    public static void main(String[] args) {
        new NullLayoutTest().init();
    }
}

7、BoxLayout布局管理器

BoxLayout看可以在垂直和水平两个方向上摆放GUI组件。其提供了一个简单的构造器:

  • BoxLayout(Container target,int axis):指定创建基于target容器的BoxLayout布局管理器,该布局管理器中的组件按axis方向排列,其中axis有BoxLayout.X_AXIS(横向)和BosLayout.Y_AXIS(纵向)两个方向。

BoxLayout有两个方法:

  1. static Box createHorizoontalBox():创建一个水平排列组件的Box容器
  2. static Box createVerticalBox():创建一个垂直排列组件的Box容器

如何使用BoxLayout布局管理器来控制容器中按钮的布局:

public static void main(String[] args) {
        Frame frame = new Frame("BoxLayoutTest");
        //创建一个水平排列组件的Box容器
        Box hBox = Box.createHorizontalBox();
        //往当前容器中添加两个按钮
        hBox.add(new Button("水平按钮一"));
        hBox.add(new Button("水平按钮二"));
        //创建一个垂直排列组件的Box容器
        Box vBox = Box.createVerticalBox();
        //往当前容器中添加两个按钮
        vBox.add(new Button("垂直按钮一"));
        vBox.add(new Button("垂直按钮二"));
        //把两个Box容器添加到Frame中显示
        frame.add(hBox,BorderLayout.NORTH);
        frame.add(vBox);

        frame.setSize(500,500);
        frame.setVisible(true);
    }

Box类中,提供了5个方便的静态方法来生成间隔组件

  • static Component createHorizontalStrut(int width):创建一条指定宽度(宽度固定了,不能拉伸)的水平Strut(可在垂直方向上拉伸的间距)
  • static Component createVerticalStrut(int height):创建一条指定高度(高度固定了,不能拉伸)的垂直Strut(可在水平方向上拉伸的间距)
  • static Component createHorizontalGlue():创建一条水平Glue(可在两个方向上同时拉伸的间距)
  • static Component createVerticalGlue():创建一条垂直Glue(可在两个方向上同时拉伸的间距)
import javax.swing.*;
import java.awt.*;
public class BoxLayoutTest {
    public static void main(String[] args) {
        Frame frame = new Frame("BoxLayoutTest");
        //创建一个水平排列组件的Box容器 hBox
        Box hBox = Box.createHorizontalBox();
        //往hBox容器中添加按钮,还需在多个按钮之间添加分割
        hBox.add(new Button("水平按钮一"));
        hBox.add(Box.createHorizontalGlue());    //该分割在两个方向都可以拉伸
        hBox.add(new Button("水平按钮二"));
        hBox.add(Box.createHorizontalStrut(30));
        hBox.add(new Button("水平按钮三"));
        //创建一个垂直排列组件的Box容器 vBox
        Box vBox = Box.createVerticalBox();
        //往vBox容器中添加按钮,还需在多个按钮之间添加分割
        vBox.add(new Button("垂直按钮一"));
        vBox.add(Box.createVerticalGlue());
        vBox.add(new Button("垂直按钮二"));
        vBox.add(Box.createVerticalStrut(30));
        vBox.add(new Button("垂直按钮三"));
        //把Box容器添加到Frame中显示
        frame.add(hBox,BorderLayout.NORTH);
        frame.add(vBox);

        frame.setSize(500,500);
        frame.setVisible(true);
    }
}