Java图形用户界面设计AWT事件处理

前言

推荐一个网站给想要了解或者学习人工智能知识的读者,这个网站里内容讲解通俗易懂且风趣幽默,对我帮助很大。我想与大家分享这个宝藏网站,请点击下方链接查看。 https://www.captainbed.cn/f1

AWT事件处理涉及Java AWT(抽象窗口工具包)中定义的事件及其处理机制。它允许开发者为图形用户界面组件(如按钮、文本框等)定义事件响应行为,如点击、键盘输入等。通过注册事件监听器并编写事件处理逻辑,AWT能够响应用户与界面元素的交互,实现动态和交互式的应用体验。

前面的文章介绍了如何放置各种组件,从而得到了丰富多彩的图形界面,但这些界面还不能响应用户的任何操作。比如单击前面所有窗口右上角的“X”按钮,但窗口依然不会关闭。因为在 AWT 编程中 ,所有用户的操作,都必须都需要经过一套事件处理机制来完成,而 Frame 和组件本身并没有事件处理能力 。


一、GUI事件处理机制

定义

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

在GUI事件处理机制中涉及到4个重要的概念需要理解:

事件源(Event Source):操作发生的场所,通常指某个组件,例如按钮、窗口等; 事件(Event):在事件源上发生的操作可以叫做事件,GUI会把事件都封装到一个Event对象中,如果需要知道该事件的详细信息,就可以通过Event对象来获取。 事件监听器(Event Listener):当在某个事件源上发生了某个事件,事件监听器就可以对这个事件进行处理。

注册监听:把某个事件监听器(A)通过某个事件(B)绑定到某个事件源( C )上,当在事件源C上发生了事件B之后,那么事件监听器A的代码就会自动执行。

使用步骤

  1. 创建事件源组件对象;
  2. 自定义类,实现XxxListener接口,重写方法;
  3. 创建事件监听器对象(自定义类对象)
  4. 调用事件源组件对象的addXxxListener方法完成注册监听

Swing事件处理机制与AWT的区别

Swing 的事件处理机制与 AWT 保持一致,甚至很多事件的处理仍然使用的是java.awt.event包中的类和接口。为了扩展事件处理能力,在javax.swing.event包中新增了一些新的事件类及其监听器接口。

二、GUI中常见事件和事件监听器

事件监听器必须实现事件监听器接口, AWT 提供了大量的事件监听器接口用于实现不同类型的事件监听器,用于监听不同类型的事件 。 AWT 中提供了丰富的事件类,用于封装不同组件上所发生的特定操作, AWT 的事件类都是 AWTEvent 类的子类 , AWTEvent是 EventObject 的子类。

事件

AWT把事件分为了两大类:

低级事件

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

事件

触发时机

ComponentEvent

组件事件 , 当 组件尺寸发生变化、位置发生移动、显示/隐藏状态发生改变时触发该事件。

ContainerEvent

容器事件 , 当容器里发生添加组件、删除组件时触发该事件 。

WindowEvent

窗口事件, 当窗 口状态发生改变 ( 如打开、关闭、最大化、最 小化)时触发该事件 。

FocusEvent

焦点事件 , 当组件得到焦点或失去焦点 时触发该事件 。

KeyEvent

键盘事件 , 当按键被按下、松开、单击时触发该事件。

MouseEvent

鼠标事件,当进行单击、按下、松开、移动鼠标等动作 时触发该事件。

PaintEvent

组件绘制事件 , 该事件是一个特殊的事件类型 , 当 GUI 组件调 用 update/paint 方法 来呈现自身时触发该事件,该事件并非专用于事件处理模型 。

高级事件

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

事件

触发时机

ActionEvent

动作事件 ,当按钮、菜单项被单击,在 TextField 中按 Enter 键时触发

AjustmentEvent

调节事件,在滑动条上移动滑块以调节数值时触发该事件。

ltemEvent

选项事件,当用户选中某项, 或取消选中某项时触发该事件 。

TextEvent

文本事件, 当文本框、文本域里的文本发生改变时触发该事件。

事件监听器

不同的事件需要使用不同的监听器监听,不同的监听器需要实现不同的监听器接口, 当指定事件发生后 , 事件监听器就会调用所包含的事件处理器(实例方法)来处理事件 。

事件类别

描述信息

监听器接口名

ActionEvent

激活组件

ActionListener

ItemEvent

选择了某些项目

ItemListener

MouseEvent

鼠标移动

MouseMotionListener

MouseEvent

鼠标点击等

MouseListener

KeyEvent

键盘输入

KeyListener

FocusEvent

组件收到或失去焦点

FocusListener

AdjustmentEvent

移动了滚动条等组件

AdjustmentListener

ComponentEvent

对象移动缩放显示隐藏等

ComponentListener

WindowEvent

窗口收到窗口级事件

WindowListener

ContainerEvent

容器中增加删除了组件

ContainerListener

TextEvent

文本字段或文本区发生改变

TextListener

AWT事件类的继承关系

三、事件适配器

事件适配器(Adapter),本质上是一种特殊的类。它是一个或者多个事件监听器接口的实现类,为接口中的每个抽象方法进行了空实现,即在方法体经中没有任何语句。

当某个事件监听器接口中的抽象方法多于一个时,可能只对其中部分抽象方法的实现有需求。但是按照Java 语法规则,非抽象的事件监听器类必须实现接口中的全部方法;不但加大了编程工作量做无用功,而且增加程序的复杂度,降低程序的清晰度。为了解决此类问题,Java 中采用了事件适配器。很容易理解,Java 没有必要为每个事件监听器配备对应的事件适配器,只有抽象方法的数目超过一个的事件监听器才为之提供。

WindowListener、 KeyListener, MouseListener 和 MouseMotionListener 都有一个以上的抽象方法,因此在 java.awt.event 包中提供了相应的事件适配器 WindowAdapter、KeyAdapter、MouseAdapter、MouseMotionAdapter。

由于 Java 提供了事件适配器,事件监听器类可以通过继承事件适配器,按照需要来重写特定的事件处理方法,为编程带来了便利。但是,由于Java的类采用单一继承机制,当事件监听器类已经存在父类,或者需要实现多个事件监听器接口时,就不能再继承事件适配器。

三、示例

代码示例

示例一

完成下图效果,点击确定按钮,在单行文本域内显示 hello world:

代码语言:javascript
复制
public class EventDemo1 {
    Frame  frame = new Frame("这里测试事件处理");
//事件源
Button button = new Button("确定");

TextField tf = new TextField(30);
public void init(){
    //注册监听
    button.addActionListener(new MyActionListener());

    //添加组件到frame中
    frame.add(tf);
    frame.add(button,BorderLayout.SOUTH);

    //设置frame最佳大小并可见
    frame.pack();
    frame.setVisible(true);
}

//自定义事件监听器类
private  class MyActionListener implements ActionListener{

    @Override
    public void actionPerformed(ActionEvent e) {

        System.out.println("用户点击了确定按钮");
        tf.setText("hello world");
    }
}

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

}

  • 通过ContainerListener监听Frame容器添加组件;

  • 通过TextListener监听TextFiled内容变化;
  • 通过ItemListener监听Choice条目选中状态变化;
示例二
代码语言:javascript
复制
import java.awt.*;
import java.awt.event.ContainerAdapter;
import java.awt.event.ContainerEvent;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;

public class ListenerDemo1 {

public static void main(String[] args) {
    Frame frame = new Frame("这里测试监听器");

    //创建一个单行文本域
    TextField tf = new TextField(30);

    //给文本域添加TextListener,监听内容的变化
    tf.addTextListener(new TextListener() {
        @Override
        public void textValueChanged(TextEvent e) {
            System.out.println("当前内容:"+tf.getText());;
        }
    });


    //给frame注册ContainerListener监听器,监听容器中组件的添加
    frame.addContainerListener(new ContainerAdapter() {
        @Override
        public void componentAdded(ContainerEvent e) {
            Component child = e.getChild();
            System.out.println("容器中添加了新组件:"+child);
        }
    });


    //添加tf到frame
    frame.add(tf);

    //设置frame最佳大小并可见
    frame.pack();
    frame.setVisible(true);
}

}

示例三

给Frame设置WindowListner,监听用户点击 X 的动作,如果用户点击X,则关闭当前窗口

代码语言:javascript
复制
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class ListenerDemo2 {

public static void main(String[] args) {

    Frame frame = new Frame("这里测试WindowListener");



    frame.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
    });

    frame.setBounds(200,200,500,300);

    frame.setVisible(true);
}

}