JavaGUI编程&AWT图形用户界面设计&事件监听及响应

AWT

AWT简单介绍

抽象窗口工具集(CAbstract Window Toolkit)

awt编程中有两个基类:Component和MenuComponent

  • Component :代表一个能以图形化方式显示出来,并可以于用户交互的对象,例如Button代表一个按钮,TextField代表一个文本框等;
  • MenuComponent:则代表图形界面的菜单组件,包括MenuBar(菜单条),MenuItem(菜单项)等子类。

Container 是一种特殊的Component,它代表一种容器,可以承装普通的Component.

AWT还有一个非常重要的接口叫做LayoutManager(布局管理器),如果一个容器中有多个组件,那么容器就需要使用LayoutManager来管理这些组件的布局方式。(网状布局,流式布局等)

Container容器

Window 窗口容器:可以独立存在的顶级窗口,默认使用BorderaLayout管理其内部的组件布局

Panel 可以容纳其他组件,但不能独立存在,他必须内嵌其他容器中使用,默认使用FlowLayout管理其内部的组件布局

ScrollPane 是一个带滚动条的容器,他也不能独立存在,默认使用BorderLayout管理器内部的组件布局

Component基类方法签名方法功能
setLocation(int x,int y)设置组件位置
setSize(int width,int height)设置组件大小
setBounds(int x,int y,int width,int height)同时设置组件位置和大小
setVisible(Boolean b)设置该组件的可见性
Container容器根类方法签名方法功能
Component add(Component comp)向容器中添加其他组件,(该组件既可以是普通组件也可以是容器),并返回被添加的组件。
Component getComponentAt(int x,int y);返回指定点的组件
int getComponentCount()返回该容器组件的数量
Component[] getCompuonents();返回该容器内的所有组件。

Window 容器效果:

Panel 容器效果:

ScrollPane 容器效果:

LayoutManager 布局管理器

LayoutManager 布局管理器 可以根据运行的平台来自动调整组件的大小,程序员不用再手动设置组件(种类繁多)的大小和位置,只需要为容器选择合适的布局管理器即可;

LayoutManager 的实现类:GridLayout(网格布局),FlowLayout(流式布局)

LayoutManager的子接口:LayoutManager2 实现类:CardLayout(卡片布局),BorderLayout(边框布局),GridManager(网格包布局);

FlowLayout(流式布局)
构造方法方法功能
FlowLayout()使用默认的对齐方式和默认的垂直间距,水平间距创建FlowLayout 布局管理器
FlowLayout(int align)使用指定的对齐方式及默认的垂直间距,水平间距来创建FlowLayout布局管理器
FlowLayout(int align,int hgap,int vgap)使用指定的对其方法及指定的垂直间距和水平间距来创建FlowLayout布局管理器。
package com.awt.xm.layout_manager;

import org.junit.Test;

import java.awt.*;

/**
 * LayoutManager
 */
public class D1 {
    /**
     * FlowLayout(流式布局)
     */
    @Test        //测试类不用手动推出
    public void test2()
//    public static void main(String ...args)
    {
        Frame frame = new Frame("这里测试FlowLayout");
        frame.setLayout(new FlowLayout(FlowLayout.CENTER,20,20));
        for (int i = 0; i < 100; i++) {
            frame.add(new Button("按钮"+i));
        }
        //pack 方法设置标签(窗口)最佳大小
        frame.pack();
        frame.setVisible(true);
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
BorderLayout(边框布局)

将容器分为EAST WEST CENTER NORTH SOUTH

  1. 当使用BorderLayout布局管理器的容器中添加组件时,需要指定要添加的区域,如果没有指定添加区域,默认添加到中间区域
  2. 如果向一个区域中添加多个组件,后放入的组件会覆盖先前的组件
  3. 如果不往某个区域放入组件,那么该区域不会空白出来,而是被其他区域占用
package com.awt.xm.layout_manager;

import java.awt.*;

/**
 * BorderLayout(边框布局)
 */
public class D2 {
    public static void main(String[] args) {
        Frame frame = new Frame("测试BorderLayout");
        frame.setLayout(new BorderLayout(30,30));
        frame.add(new Button("东侧按钮"),BorderLayout.EAST);
        frame.add(new Button("北侧按钮"),BorderLayout.NORTH);
        frame.add(new Button("中侧按钮"),BorderLayout.CENTER);
        frame.add(new Button("南侧按钮"),BorderLayout.SOUTH);
        frame.add(new Button("西侧按钮"),BorderLayout.WEST);
        frame.add(new TextField("测试文件框"));
        frame.pack();
        frame.setBackground(Color.BLUE);
        frame.setVisible(true);
    }
}

GridLayout(网格布局)
构造方法方法功能
GridLayout(int rows,int cols)采用指定的行数和列数,以及默认的横向间距和纵向间距分割成多个网格
GridLayout(int rows,int cols,int hgap,int vgap)采用指定的行数和列数,以及指定的横向间距和纵向间距将容器分割成多个网格

计算器效果实现

package com.awt.xm.layout_manager;

import java.awt.*;

/**
 * GridLayout(网格布局)
 */
public class D3 {
    public static void main(String[] args) {
        Frame frame = new Frame("测试GridLayout计算器");
        Panel panel = new Panel();
        panel.add(new TextField(70));
        frame.add(panel, BorderLayout.NORTH);
        Panel panel1 = new Panel();
        for (int i = 0; i < 10; i++) {
            panel1.add(new Button(Integer.toString(i)));
        }
        panel1.add(new Button("+"));
        panel1.add(new Button("-"));
        panel1.add(new Button("*"));
        panel1.add(new Button("/"));
        panel1.add(new Button("="));

        panel1.setLayout(new GridLayout(3, 5,4,4));
        frame.add(panel1,BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }
}

GrigBagLayout(网格包布)

不推荐,因为Swing 中有更加强大的布局管理器

CardLayout(卡片布局)

CardLayout布局 以时间而非空间来管理它里面的组件,他将加入容器的所有组件看成一叠卡片(每个卡片其实就是一个组件),每次只有最上面的那个Component 才可见。

方法名称方法功能
CardLayout()创建默认的CardLayout布局管理器
CardLayout(int hgap,int vagp)通过指定卡片和容器左右边界的间距,上下边界的间距来创建CardLayout布局管理器
first(Container target)显示target容器中的第一张卡片
last(Container target)显示target容器中的最后一张卡片
previous(Container target)显示target容器中的前一张卡片
next(Container target)显示target容器中的后一张卡片
show(Container target,String name )显示target容器中指定名字的卡片
package com.awt.xm.layout_manager;

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

/**
 * CardLayout(卡片布局)
 */
public class D5 {
    public static void main(String[] args) {
        Frame frame = new Frame("CardLayout布局");
        Panel panel = new Panel();
        String[] names = {"第一张", "第二张", "第三张", "第四张", "第五张"};
        for (int i = 0; i < names.length; i++) {
            panel.add(names[i], new Button(names[i]));
        }
        CardLayout cardLayout = new CardLayout();
        panel.setLayout(cardLayout);
        frame.add(panel, BorderLayout.CENTER);
        Panel panel1 = new Panel();
        Button b1 = new Button("上一张");
        panel1.add(b1);
        Button b2 = new Button("下一张");
        panel1.add(b2);
        Button b3 = new Button("第一张");
        panel1.add(b3);
        Button b4 = new Button("最后一张");
        panel1.add(b4);
        Button b5 = new Button("第三张");
        panel1.add(b5);
        //事件监听器
        ActionListener actionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String actionCommand = e.getActionCommand();
                switch (actionCommand) {
                    case "上一张":
                        cardLayout.previous(panel);
                        break;
                    case "下一张":
                        cardLayout.next(panel);
                        break;
                    case "第一张":
                        cardLayout.first(panel);
                        break;
                    case "最后一张":
                        cardLayout.last(panel);
                        break;
                    case "第三张":
                        cardLayout.show(panel,"第三张");
                        break;
                }
            }
        };
        b1.addActionListener(actionListener);
        b2.addActionListener(actionListener);
        b3.addActionListener(actionListener);
        b4.addActionListener(actionListener);
        b5.addActionListener(actionListener);
        frame.add(panel1, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }
}
BoxLayout(盒子布局)

该布局属于java.swing 包

方法名称方法功能
BoxLayout(Container target int axis)指定创建基于target容器的BoxLayout布局管理器,该布局管理器的组件按axis方向排列。其中axis有BoxLayout.X_ASIX(横向)和BoxLayout.Y_ASIS(纵向)
package com.awt.xm.layout_manager;

import javax.swing.*;
import java.awt.*;

/**
 * BoxLayout(盒子布局)
 */
public class D6 {
    public static void main(String[] args) {
        Frame frame = new Frame("BoxLayout测试");
        frame.setLayout(new BoxLayout(frame,BoxLayout.Y_AXIS));
        frame.add(new Button("第一"));
        frame.add(new Button("第二"));
        frame.pack();
        frame.setVisible(true);
    }
}

在java.swing包中,提供了一个新的容器Box 该容器的默认布局管理器就是BoxLayout,大多数情况下,使用Box容器去容纳多个GUI组件,然后把Box容器作为一个组件,添加到其他容器中,从而形成整体的窗口布局。

Box容器方法
方法名称方法功能
static Box createHorizontalBox()创建一个水平排列组件的Box容器
static Box createVerticalBox()创建一个垂直排列组件的Box容器
package com.awt.xm.layout_manager;

import javax.swing.*;
import java.awt.*;

/**
 * Box容器默认实现BoxLayout布局
 */
public class D7 {
    public static void main(String[] args) {
        Frame frame = new Frame("Box容器默认实现BoxLayout布局");
        Box box = Box.createHorizontalBox();
        box.add(new Button("水平一"));
        box.add(new Button("水平二"));
        Box box1 = Box.createVerticalBox();
        box1.add(new Button("垂直一"));
        box1.add(new Button("垂直二"));
        frame.add(box);
        frame.add(box1,BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }
}
Box容器方法扩充
方法名称方法功能
static Component createHorizontalGlue()创建一条水平Glue组件(可在两个方向上同时拉伸)
static Component createVerticalGlue()创建一条垂直Glue组件(可在两个方向上同时拉伸)
static Component createHorizontalStrut(int width)创建一条指定宽度(水平方向不可拉伸,垂直方向可以)的Strut组件
static Component createVerticalStrut(int height)创建一条指定高度(垂直方向不可拉伸,水平方向可以)的Strut组件
package com.awt.xm.layout_manager;

import javax.swing.*;
import java.awt.*;

/**
 * Box容器和BoxLayout布局分割实现
 */
public class D8 {
    public static void main(String[] args) {
        Frame frame = new Frame("Box容器和BoxLayout布局分割实现");
        Box box = Box.createHorizontalBox();
        box.add(new Button("水平一"));
        box.add(Box.createHorizontalGlue());//返回组件,可以在两个方向拉伸
        box.add(new Button("水平二"));
        box.add(Box.createHorizontalStrut(30));//水平不可以拉伸
        box.add(new Button("水平三"));
        Box box1 = Box.createVerticalBox();
        box1.add(new Button("垂直一"));
        box1.add(Box.createVerticalGlue());//返回组件,可以在两个方向拉伸
        box1.add(new Button("垂直二"));
        box1.add(Box.createVerticalStrut(30));//垂直方向不能拉伸
        box1.add(new Button("垂直三"));
        frame.add(box,BorderLayout.NORTH);
        frame.add(box1,BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }
}


AWT常用组件

组件名功能
Button按钮
Canvas用于绘图的画布
CheckBox复选框(可以作为单选框使用)
CheckboxGroup用于将多个Checkbox组件合成一组,一组Checkbox组件将只用一个可以被选中,即全部变成 单选框组件
Choice下拉选择框
Frame窗口(Window容器的实现类对象)在GUI程序中通过该类创建窗口
Label标签类,用于放置提示性文本
List列表框组件,可以添加多条项目
Panel不能单独存在的基本容器类,必须放到其他容器中
Scrollbar滑动条组件,如果需要用户输入位于某个范围的值,就可以使用滑动条组件,比如调色板中设置%RGB的三个值所用的滑动条。当创建一个滑动条时,必须指定它的方向,初始值,滑块的大小,最大值和最小值
ScrollPane带水平及垂直滚动条的容器组件
TextArea多行文本域
TextField单行文本框

用法演示:

package com.awt.xm.component;

import javax.swing.*;
import java.awt.*;

/**
 * awt组件测试类
 */
class BasicComponent {

    Frame frame = new Frame("awt组件测试");
    TextArea textArea = new TextArea(5, 20);
    Choice choice = new Choice();
    CheckboxGroup checkboxGroup = new CheckboxGroup();
    Checkbox checkbox = new Checkbox("女", checkboxGroup, true);
    Checkbox checkbox1 = new Checkbox("男", checkboxGroup, false);
    Checkbox checkbox4 = new Checkbox("是美女吗");
    TextField textField = new TextField(60);
    Button button = new Button("确认");
    List list = new List(6, true);

    public void init() {

        Box box1 = Box.createHorizontalBox();
        choice.add("红色");
        choice.add("蓝色");
        choice.add("绿色");
        box1.add(choice);
        box1.add(checkbox);
        box1.add(checkbox1);
        box1.add(checkbox4);

        Box box2 = Box.createVerticalBox();
        box2.add(textArea);
        box2.add(box1);

        Box box3 = Box.createHorizontalBox();
        box3.add(box2);
        list.add("红色");
        list.add("白色");
        list.add("蓝色");
        box3.add(list);

        Box box4 = Box.createHorizontalBox();
        box4.add(textField);
        box4.add(button);

        frame.add(box3);
        frame.add(box4, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

}

public class Demo1 {
    public static void main(String[] args) {
        new BasicComponent().init();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.exit(0);
    }
}
//方法签名(全类名,形参列表,返回值数据类型)只是一种说法

菜单组件

Dialog对话框

Dialog对话框时Window类的子类,是一个容器类(BorderLayout布局),属于特殊组件,对话框时可以独立存在的顶级窗口,因此用法和普通的窗口用法几乎一样,但是使用对话框需要注意以下两点:

  • 对话框通常依赖于其他窗口,就是通常需要有一个父窗口
  • 对话框有非模式(non-modal)和模式(modal)两种,当某个模式对话框被打开后,该模式对话框总是位于他的父窗口之上,在模式对话框被关闭之前,父窗口无法获得焦点。
方法签名方法功能
Dialog (Frame owner,String title , boolean modal )创建一个对话框对象,owner:当前对话框的父窗口 title:当前对话框的标题 modal:当前对话框是否是模式对话框
package com.awt.xm.component;

import java.awt.*;

/**
 *Dialog对话框
 */
public class De2 {
     public static void main(String[] args) {
         Frame frame = new Frame("测试Dialog对话框");
         Dialog dialog1 = new Dialog(frame,"模式对话框",true);
         dialog1.setBounds(300,300,500,300);
         dialog1.add(new TextArea(5,30));
         dialog1.add(new Button("确认"),BorderLayout.SOUTH);
         Dialog dialog2 = new Dialog(frame,"非模式对话框",false);
         dialog2.setBounds(300,300,500,300);
         Button button1 = new Button("打开模式对话框");
         Button button2 = new Button("打开非模式对话框");
         button1.addActionListener(e -> dialog1.setVisible(true));
         button2.addActionListener(e -> dialog2.setVisible(true));
         frame.add(button1,BorderLayout.NORTH);
         frame.add(button2,BorderLayout.SOUTH);
         frame.pack();
         frame.setVisible(true);

     }
}

FileDialog (文件对话框)

Dialog类有一个子类: fileDialog ,他代表一个文件对话框,用于打开或保存文件,需要注意的是FileDialog无法指定模态或非模态,这是因为FileDialog依赖运行平台的实现,如果运行平台的文件对话框是模态的,那么FileDialog 也是模态的,否则是非模态的。

方法签名(全类名,形参列表)方法功能
FileDialog (Frame parent,String title,int mode)创建一个文件按对话框:parent: 指定父窗口,title:对话框标题 mode: 文件对话框类型,如果指定为FileDialog.LOAD,用于打开文件;指定为FileDialog.SAVE,用于保存文件
Stirng get Directory()获取被打开或保存文件的绝对路径
String getFile()获取被打开或保存的文件名
package com.awt.xm.component;

import java.awt.*;

/**
 * FileDialog对话框
 */
public class De3 {
    public static void main(String[] args) {
        Frame frame = new Frame("测试FileDialog对话框");
        FileDialog fileDialog1 = new FileDialog(frame, "选择要打开的文件::", FileDialog.LOAD);
        FileDialog fileDialog2 = new FileDialog(frame, "选择要保存的路径::", FileDialog.SAVE);
        Button button1 = new Button("打开文件");
        Button button2 = new Button("保存文件");
        button1.addActionListener(e -> {
            fileDialog1.setVisible(true);
            String directory = fileDialog1.getDirectory();
            String file = fileDialog1.getFile();
            System.out.println("打开的路径为:" + directory);
            System.out.println("打开的文件名为:" + file);
        });
        button2.addActionListener(e -> {
            fileDialog2.setVisible(true);
            String directory = fileDialog2.getDirectory();
            String file = fileDialog2.getFile();
            System.out.println("保存的路径为:" + directory);
            System.out.println("保存的文件名为:" + file);
        });
        frame.add(button1, BorderLayout.NORTH);
        frame.add(button2, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);

    }
}

GUI事件处理机制

定义及核心概念

定义:当在某一个组件上发生某些操作的时候,会自动的触发一段代码的执行。

4个核心的概念:

  • 事件源(Event Source):操作发生的场所,通常某个组件,例如按钮,窗口等;
  • 事件(Event):在事件源上发生的操作叫做事件,GUI会把事件都封装到一个Event对象中,如果需要知道该事件的详细信息,就可以通过Event对象来获取;
  • 事件监听器(Event Listener):当在某个事件源上发生了某个事件,事件监听器就可以对这个事件进行处理。(代码处理)
  • 注册监听(Register Listener): 吧某个事件监听器(A)通过某个事件(B)绑定到某个事件源(C)上,当在事件源(C)上发生了事件(B)之后,那么事件监听器(A)的代码就会自动执行;
package com.awt.xm.event_listener;

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

public class Dem1 {
    public Frame frame;
    public Button button;
    public TextField textField;
    public void init()
    {
        frame=new Frame("事件监听测试");
        //事件源
        button=new Button("显示");
        textField=new TextField();
        //注册监听,可以通过,外部类对象,成员内部类的对象,匿名内部类,Lambda表达式都可以
        //多个事件源得使用同一个事件监听器的话,用成员内部类或外部类比较好
        button.addActionListener(new MyListener());
        frame.add(textField,BorderLayout.NORTH);
        frame.add(button);
        frame.pack();
        frame.setVisible(true);
    }
    private class MyListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            textField.setText("你好世界!");
            System.out.println("OK按钮被点击了"+e);
        }
    }

    public static void main(String[] args) {
             new Dem1().init();
    }
}

常见的事件和事件监听器
常见事件:

AWT中的事件分为低级事件和高级事件

1.低级事件:

低级事件:这类事件是基于某一个特定的动作的事件。比如进入,点击,拖放等动作的鼠标事件,再比如得到焦点和失去焦点等焦点事件。

事件触发时机
ComponentEvent组件事件,当组织尺寸发生变化、位置发生移动、显示/隐藏状态发生改变时触发该事件。
ContainerEvent容器事件,当容器里发生添加组件、删除组件时触发该事件。
WindowEvent窗口事件,当窗 口状态发生改变(如打开、关闭、最大化、最 小化)时触发该事件。
FoucusEvent焦点事件,当组件得到焦点或失去焦点 时触发该事件。
KeyEvent键盘事件 ,当按键被按下、松开、单击时触发该事件。
MouseEvent鼠标事件, 当进行单击,按下,松开,移动鼠标等动作时触发该事件。
PaintEvent组件绘制事件,该事件是一个特殊的事件类型,当GUI组件调用update/paint方法来呈现自身时触发该事件,该事件并非专用于事件处理模型

2.高级事件:

这类事件并不会基于某个特定的动作,而是根据功能含义定义的事件。

事件触发时机
ActionEvent动作事件:当按钮,菜单项被单击时,在TextFiled中按下Enter键时触发
AdjustmentEvent调节事件:在滑动条上滑动滑块以调节数值时,触发该事件
ItemEvent选项事件:当用户选中某项,或取消选中某项时,触发该事件
TextEvent文本事件:当文本框,文本域中的文本发生改变时,触发该事件
事件监听器

不同的事件使用不同的监听器监听,不同的监听器需要不同的监听器接口,当指定事件发生后,事件监听器就会调用所包含的事件处理器(重写的接口代码)来处理事件。

事件类别描述信息监听器接口
ActionEvent激活组件ActionListener
ItemEvent选择某些项目ItemListener
MouseEvent鼠标移动MouseMotionListener
MouseEvent鼠标点击MouseListener
KeyEvent键盘输入KeyListener
FocusEvent组件收到或失去焦点KeyListener
AdjustmentEvent移动了滚动条等组件AdjustmentListener
ComponentEvent对象移动缩放显示隐藏ComponentListener
WindowEvent窗口收到窗口级事件WindowListener
ContainerEvent容器中增加或删除了组件ContainerListener
TextEvent文本字段或文本区发生改变TextListener

演示代码:

  1. 通过ContainerListener监听Frame容器添加组件,通过TextListener 监听Text Filed内容变化,通过ItemListener 监听Choice条目选中状态变化
  2. 适配器模式,避免多余实现
package com.awt.xm.event_listener;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Dem2 {
    Frame frame = new Frame("测试不同的监听器");
    TextField tf = new TextField(30);
    Choice choice = new Choice();

    public void init() {
        choice.add("宫本");
        choice.add("公孙离");
        choice.add("鲁班大师");
        //TextListener
        tf.addTextListener(new TextListener() {
            @Override
            public void textValueChanged(TextEvent e) {
                //System.out.println(e.getSource());
                System.out.println("当前文本框中的内容:" + tf.getText());
            }
        });
        //ComponentListener
        frame.addContainerListener(new ContainerListener() {
            @Override
            public void componentAdded(ContainerEvent e) {
                Component child = e.getChild();
                System.out.println("frame中添加了:" + child);
            }

            @Override
            public void componentRemoved(ContainerEvent e) {

            }
        });
        //ItemListener
        choice.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                Object item = e.getItem();
                System.out.println("当前选择的条目为:" + item);
            }
        });

        //适配器模式
        //监听用户点击X的动作
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        Box box = Box.createHorizontalBox();
        box.add(choice);
        box.add(tf);
        frame.add(box);
        frame.pack();
        frame.setVisible(true);

    }

    public static void main(String[] args) {
        new Dem2().init();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aurora-XM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值