Swing 事件监听:事件处理模型和事件监听器
程序与用户的交互机制包括多种方式:如在文本框输入、列表框或组合框中选择、勾选复选框或单选框以及点击按钮等。该响应机制负责处理用户的操作,并由相应的程序实现。
一旦发生某件事 系统会自动识别这一情况 并生成记录相关行为的事件对象 这些对象会被分配到程序内部的任务处理模块中进行处理 这种编码方案决定了如何应对此类事件从而为用户提供所需的信息
事件处理模型
在之前的内容中,我们介绍了如何布置各种组件以丰富图形界面的表现形式。然而目前该系统还无法直接响应用户的操作指令。为了实现这一功能系统需要对各个组件安装相应的事件处理机制在这些机制的运作过程中主要会涉及到三种类型的对象
- Event(事件):用户对组件的行为称为一个Event,并采用类的方式来表示。
- Event Source(来源):这些发生的位置通常是各个组件或具体实例中的一个实例,并如Button控件所示。
- Event Handler(处理器):响应和处理该特定类型的Event的对象方法通常是某个Java类中负责响应和处理该类型特定的Event的方法。
在使用场景中,默认情况下,在鼠标触发了按钮对象 Button的情况下,默认情况下,默认情况下,默认情况下,默认情况下,默认情况下,默认情况下,默认情况下,默认情况下,默认情况下,默认情况下,默认情况下,默认情况下

因为同一个来源能够生成多种不同的数据流。Java 采用了基于权限的模型(Delegation Model)。该来源能够将在其自身生成的所有可能的数据流分别授予不同的处理器进行处理。例如,在某个面板对象上可能会同时发生鼠标点击和键盘输入两种类型的数据流。这个面板对象能够将鼠标点击的数据流授予处理器A进行处理,并将键盘输入的数据流授予处理器B进行处理。
有时候会将这类技术工具统称为一种特定的技术架构。主要原因包括实时监控系统对数据流的高度关注能力以及其在实际应用中的高效性表现等特性。这类架构通过建立一个独立于数据流管理系统的中间层来实现对数据流实时监控能力的提升。这种架构允许系统管理员通过配置中心化的监控服务来管理整个系统的实时监控需求,并且能够灵活地根据业务需求调整监控策略和资源分配方案。这样一来不仅能够提高系统的整体性能还能有效降低运行成本并确保系统的稳定性和可靠性。这种架构通过引入一种中间服务层将对数据流实时监控的需求与数据流本身的管理职责分离开来从而实现了对数据流实时监控能力的有效提升同时又避免了直接在业务层面上引入复杂的监控逻辑进而简化了系统的设计提升了系统的可维护性和扩展性
通常情况下,事件处理者(也称为监听器)是一个类。当某个类能够处理特定类型的事件时,则必须实现与其相关联的接口。例如,在ButtonHandler类中能够处理ActionEvent的原因在于它实现了与ActionEvent相关的接口ActionListener。每一个具体的事件类型都对应有一个相应的接口。
动作事件监听器
作为 Swing 中较为常见的事件监听器之一,动作事件监听器常用于触发组件响应。许多组件的动作都会通过该机制进行监控,在按钮被点击时以及列表框中选择一项等情况中。与动作事件 listeners 相关的信息如下:
- 此事件名称为ActionEvent。
- 对应的事件监听接口为ActionListener。
- 该类涉及的主要操作方法包括addActionListener()和removeActionListener()。
- 该类主要处理的对象包括JButton、JList和JTextField等。
例 1
为了阐述动作单击事件监听器的应用,请参考以下基于按钮单击事件的技术示例:在此案例中记录了窗口内按钮被点击的总次数。
本案例的核心代码如下:
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Swing20 extends JFrame {
JList list;
JLabel label;
JButton button1;
int clicks = 0;
public Swing20() {
setTitle("动作事件监听器示例");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 400, 200);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
label = new JLabel(" ");
label.setFont(new Font("楷体", Font.BOLD, 16)); //修改字体样式
contentPane.add(label, BorderLayout.SOUTH);
button1 = new JButton("我是普通按钮"); //创建JButton对象
button1.setFont(new Font("黑体", Font.BOLD, 16)); //修改字体样式
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setText("按钮被单击了 " + (clicks++) + " 次");
}
});
contentPane.add(button1);
}
//处理按钮单击事件的匿名内部类
class button1ActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
label.setText("按钮被单击了 " + (clicks++) + " 次");
}
}
public static void main(String[] args) {
Swing20 frame = new Swing20();
frame.setVisible(true);
}
}
上述代码通过 addActionListener() 方法为 button1 添加了一个单击动作的事件监听器,并由 button1ActionListener 类负责实现这一功能。为了使该事件监听器能够响应相关操作,在其类中需继承自父类并将 actionPerformed() 方法进行重写。在 actionPerformed() 方法体内,则应编写按钮被单击后需要执行的具体功能。
图 2 所示为程序运行后,没有单击和单击后的效果。


在本例中使用的是内部类形式,当然也可以写成如下形式的代码:
//为按钮buttonl添加ActionEvent事件的处理程序
buttonl.addActionListener(new ActionListener()
{
public void action Performed(Action Event e)
{
//具体代码编写在这里
label.setTextC 按钮被单击了 "+(ciicks++)+1 次");
}
}
焦点事件监听器
除了单击事件之外,在实际开发中,焦点事件监听器的应用也非常常见。例如当光标从文本框移出时会触发显示提示对话框;同时也会将焦点重新归还给该文本框。
与焦点事件监听器有关的信息如下。
- 该事件被称为 FocusEvent。
- 此接口定义为 FocusListener。
- 这些方法分别为 addFocusListener() 和 removeFocusListener() 调用。
- 主要针对此源及其继承类。
该接口包含了两个函数(API),分别是 focusGained() 函数和 focusLost() 函数。其中一个是 focusGained() 函数,在组件激活焦点时被调用;另一个是 focusLost() 函数,在组件失活焦点时被调用。
例 2
下面以\boxed{\text{文本框}}为例展示焦点单击事件监听器的应用过程。其中核心代码片段如下所示:
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
public class Swing21 extends JFrame {
JList list;
JLabel label;
JButton button1;
JTextField txtfield1;
public Swing21() {
setTitle("焦点事件监听器示例");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 400, 200);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
label = new JLabel(" ");
label.setFont(new Font("楷体", Font.BOLD, 16)); //修改字体样式
contentPane.add(label, BorderLayout.SOUTH);
txtfield1 = new JTextField(); //创建文本框
txtfield1.setFont(new Font("黑体", Font.BOLD, 16)); //修改字体样式
txtfield1.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent arg0) {
// 获取焦点时执行此方法
label.setText("文本框获得焦点,正在输入内容");
}
@Override
public void focusLost(FocusEvent arg0) {
// 失去焦点时执行此方法
label.setText("文本框失去焦点,内容输入完成");
}
});
contentPane.add(txtfield1);
}
public static void main(String[] args) {
Swing21 frame = new Swing21();
frame.setVisible(true);
}
}
该组件通过调用 addFocusListener() 方法为 txtfield1 添加了焦点事件监听器,并采用匿名实现的方式实现了这一功能。在 FocusListener 接口的实现代码中,编写了 focusGained() 和 focusLost() 方法。经过上述操作后,程序运行效果如图 3 所示。

监听列表项选择事件
列表框控件 JList 展示出多个可供用户挑选的选项,在操作过程中会根据所选项目自动执行相应的功能。
本案例旨在阐述选择列表项时的事件监听方法,并探讨用于处理这些事件的代码逻辑。具体实现步骤如下:
(1) 创建一个继承自 JFrame 的 JListDemo2 类。
对于 JListDemo2 类体中声明并添加 JList 和 JLabel 组件对象,并定义一个空的构造方法,请参见以下代码片段。
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Swing22 extends JFrame {
JList list;
JLabel label;
public Swing22() {
}
public static void main(String[] args) {
Swing22 frame = new Swing22();
frame.setVisible(true);
}
}
(3) 在构造方法中为列表框填充数据源,主要代码如下:
public Swing22() {
setTitle("监听列表项选择事件");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100,100,400,200);
JPanel contentPane=new JPanel();
contentPane.setBorder(new EmptyBorder(5,5,5,5));
contentPane.setLayout(new BorderLayout(0,0));
setContentPane(contentPane);
label=new JLabel(" ");
contentPane.add(label,BorderLayout.SOUTH);
JScrollPane scrollPane=new JScrollPane();
contentPane.add(scrollPane,BorderLayout.CENTER);
list=new JList();
scrollPane.setViewportView(list);
String[] listData=new String[7];
listData[0]="《一点就通学Java》";
listData[1]="《一点就通学PHP》";
listData[2]="《一点就通学Visual Basic)》";
listData[3]="《一点就通学Visual C++)》";
listData[4]="《Java编程词典》";
listData[5]="《PHP编程词典》";
listData[6]="《C++编程词典》";
list.setListData(listData);
}
(4) 为列表框组件 list 添加选择事件监听,代码如下所示。
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
do_list_valueChanged(e);
}
});
在上述代码中,list 组件绑定了一个名为ListSelectionListener的事件监听器,在触发该事件时程序将调用do_list_valueChanged()方法来执行具体的业务逻辑处理。
请实现do_liSt_ValueChanged()方法,并将其功能定义为将所选列表项展示至标签字段中。具体代码如下:
protected void do_list_valueChanged(ListSelectionEvent e) {
label.setText("感谢您购买:" + list.getSelectedValue());
}
(6) 运行程序,列表框选择前后的效果如图 4 所示。


package com.demo;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Swing22 extends JFrame {
JList list;
JLabel label;
public Swing22() {
setTitle("监听列表项选择事件");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 400, 200);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
label = new JLabel(" ");
contentPane.add(label, BorderLayout.SOUTH);
JScrollPane scrollPane = new JScrollPane();
contentPane.add(scrollPane, BorderLayout.CENTER);
list = new JList();
scrollPane.setViewportView(list);
String[] listData = new String[7];
listData[0] = "《一点就通学Java》";
listData[1] = "《一点就通学PHP》";
listData[2] = "《一点就通学Visual Basic)》";
listData[3] = "《一点就通学Visual C++)》";
listData[4] = "《Java编程词典》";
listData[5] = "《PHP编程词典》";
listData[6] = "《C++编程词典》";
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
do_list_valueChanged(e);
}
});
list.setListData(listData);
}
protected void do_list_valueChanged(ListSelectionEvent e) {
label.setText("感谢您购买:" + list.getSelectedValue());
}
public static void main(String[] args) {
Swing22 frame = new Swing22();
frame.setVisible(true);
}
}
