先来了解什么是事件,事件就是表示一个对象的状态发生了变化。例如,每当一个按钮按下时,实际按钮的状态就发生了改变,那么此时就会产生一个事件,而如果需要事件的监听者不断的监听事件的变化,并根据这些事件进行相应的处理。
在 Swing
编程中,依然使用了最早的 AWT
的事件处理方式,所有的事件类(基本上任意一个组件都有对应的事件)都是 EventObject
类的子类。如下图所示。
EventObject
类的JDK源码:
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
protected transient Object source;
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
public Object getSource() {
return source;
}
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
在 EventObject
中定义了三个方法,其中可以通过 getSource()
方法取得发生此事件的源对象。
如果没有能够接受和处理事件的对象,图形界面程序生成的一切事件都是无用的,这些事件接收对象被称为事件监听器。
所有的事件监听器都是以接口的形式出现的,处理是只需要实现此接口即可。
WindowListener
是专门处理窗体的事件监听接口,一个窗体的所有变换,如窗口打开,关闭等都可以使用 WindowListener
这个接口进行监听。WindowListener
接口定义的方法如下表所示。
序号 | 方法 | 描述 |
---|---|---|
1 | void windowActivated(WindowEvent e) | 将窗口变为活动窗口时触发 |
2 | void windowDeactivated(WindowEvent e) | 将窗体变为不活动窗口是触发 |
3 | void windowClosing(WindowEvent e) | 当窗口正在关闭时触发 |
4 | void windowClosed(WindowEvent e) | 当窗口被关闭了触发 |
5 | void windowIconified(WindowEvent e) | 窗口从正常状态变为最小化状态时触发 |
6 | void windowDeiconified(WindowEvent e) | 窗口从最小化状态变为正常状态时触发 |
7 | void windowOpened(WindowEvent e) | 窗口打开是触发 |
通过实现 WindowListener
接口来监听窗体事件
import java.awt.event.WindowListener;
import java.awt.event.WindowEvent;
import java.awt.Color;
import javax.swing.JFrame;
//通过实现事件监听器接口方式来监听事件
class MyWindowEventHandle implements WindowListener
{
public void windowActivated(WindowEvent e)
{
System.out.println("windowActivated --> 窗口被选中");
}
public void windowClosed(WindowEvent e)
{
System.out.println("windowClosed --> 窗口被关闭");
}
public void windowClosing(WindowEvent e)
{
System.out.println("windowClosing --> 窗口关闭");
System.exit(1);//退出程序
}
public void windowDeactivated(WindowEvent e)
{
System.out.println("windowDeactivated --> 取消窗口选中");
}
public void windowDeiconified(WindowEvent e)
{
System.out.println("windowDeiconified --> 窗口从最小化恢复");
}
public void windowIconified(WindowEvent e)
{
System.out.println("windowIconified --> 窗口最小化");
}
public void windowOpened(WindowEvent e)
{
System.out.println("windowOpened --> 窗口被打开");
}
}
public class MyEventWindowEventJFrame01
{
public static void main(String args[])
{
JFrame frame = new JFrame("窗体事件处理");
//窗体中加入事件监听器
frame.addWindowListener(new MyWindowEventHandle()); // 加入事件
frame.setSize(300, 150);
//设置背景颜色
frame.getContentPane().setBackground(Color.PINK);
frame.setLocation(300, 200);
frame.setVisible(true);
}
}
当鼠标移动当窗体上的时候,窗体被选中,当鼠标移出窗体之外的位置时,窗体不被选中。当最小化窗体的时候,触发最小化事件,再次显示点击窗体按钮时,触发从最小化恢复事件,最大化好像没有对应的事件。在上面的窗口关闭事件中写入了 System.exit(1)
语句,这样当关闭窗体时程序结束。关闭按钮起作用。
如果现在只需要对关闭窗体的事件进行监听,其他操作我们根本不关心,就没必要通过实现接口的方式来监听事件,因为通过实现接口的方式,我们要实现事件监听接口( WindowListener
)里面的所有的方法。
为解决上述问题,引入适配器设计模式,在实现类和接口之间增加一个过渡的抽象来,字节继承抽象类就可以根据自己的需要进行事件方法的覆盖。在整个事件处理中提供了很多的 Adapter
(适配器)类,方便用户进行事件处理的实现。以 WindowAdapter
为例,用户只需要继承 WindowAdapter
类,就可以根据自己的需要覆盖方法,如果现在只关心窗体的关闭事件方法,则只下子类中覆盖 windowClosing()
方法即可。
实例:通过 WindowAdapter
实现监听
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.Color;
import javax.swing.JFrame;
class MyWindowEventHandle1 extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.out.println("windowClosing --> 窗口关闭");
System.exit(1);
}
}
public class MyEventWindowEventJFrame02
{
public static void main(String args[])
{
JFrame frame = new JFrame("通过适配器监听处理事件");
frame.addWindowListener(new MyWindowEventHandle1()); // 加入事件
frame.setSize(300, 150);
frame.getContentPane().setBackground(Color.yellow);
frame.setLocation(300, 200);
frame.setVisible(true);
}
}
关闭该窗体,控制台输出:
windowClosing --> 窗口关闭
如果此监听处理只需要操作一次,没有必要将其设置成为一单独的类,此时可以利用匿名内部类来事件的操作。
实例:使用匿名内部类方式实现事件监听
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.Color;
import javax.swing.JFrame;
public class MyEventWindowEventJFrame03
{
public static void main(String args[])
{
JFrame frame = new JFrame("使用匿名内部来");
// 加入事件
frame.addWindowListener(
//匿名内部类方式,实现事件监听。
new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.out.println("windowClosing --> 窗口关闭");
System.exit(1);
}
});
frame.setSize(300, 150);
frame.getContentPane().setBackground(Color.green);
frame.setLocation(300, 200);
frame.setVisible(true);
}
}
点击窗体的关闭按钮,控制输出:
windowClosing --> 窗口关闭
使用适配器操作类,直接编写匿名内部类就可以减少监听类的定义,这是在开发中比较常见的一种方法。
要想让一个按钮变得有意义,就必须使用事件处理。在 Swing
的事件处理中,可以使用 ActionListener
接口处理按钮的动作事件。 ActionListener
接口只定义了一个方法,如下表所示。
序号 | 事件 | 描述 |
---|---|---|
1 | void actionPerformed(ActionEvent e) | 发生操作时调用 |
下面使用上面的监听接口监听按钮的单击事件。
实例:使用 ActionListener
监听
下面实现一个简单的用户登录操作:如果用户输入的用户名为 user
,密码为 admin
,则认为是合法用户,提示登录成功的信息,反之,则提示登录失败的信息,代码如下所示。
import java.awt.event.WindowAdapter;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JPasswordField;
import javax.swing.JPanel;
class LoginCheck
{
private String name;
private String password;
public LoginCheck(String name, String password)
{
this.name = name;
this.password = password;
}
public boolean ispass()
{
if ("user".equals(name) && "admin".equals(password))
{
return true;
} else
{
return false;
}
}
};
class ActionHandle1
{
private JFrame frame = new JFrame("简单登录模式");
private JButton submit = new JButton("登陆");
private JButton reset = new JButton("重置");
private JLabel nameLab = new JLabel("用户名:");
private JLabel passLab = new JLabel("密 码:");
private JLabel infoLab = new JLabel("请输入用户名和密码");
private JTextField nameText = new JTextField(10);
private JPasswordField passText = new JPasswordField();
private JPanel pan = new JPanel();
public ActionHandle1()
{
// 设置字体
Font fnt = new Font("Serief", Font.ITALIC + Font.BOLD, 14);
// 标签设置字体样式
infoLab.setFont(fnt); // 设置标签的显示文字
submit.setFont(fnt);
reset.setFont(fnt);
nameLab.setFont(fnt);
passLab.setFont(fnt);
// 监听登录按钮事件
submit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == submit)
{
// 获取名字框的文本
String tname = nameText.getText();
// 获取密码框的文本
String tpass = new String(passText.getPassword());
// 检查用户名和密码
LoginCheck log = new LoginCheck(tname, tpass);
if (log.ispass())
{
// 设置提示标签
infoLab.setText("登陆成功,欢迎光临!");
} else
{
infoLab.setText("登陆失败,错误的用户名或密码!");
}
}
}
});
// 设置重置按钮事件处理
reset.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == reset)
{
// 用户名和密码框置空
nameText.setText("");
passText.setText("");
infoLab.setText("请输入用户名和密码");
}
}
});
// 关闭窗口事件
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(1);
}
}); // 加入事件
// 不适用布局管理器
frame.setLayout(null);
// 设置第一行的三个组件的位置和大小
nameLab.setBounds( 5, 5, 60, 20);
nameText.setBounds(65, 5, 100, 20);
submit.setBounds( 170, 5, 80, 20);
// 设置第2行的三个组件的位置和大小
passLab.setBounds( 5, 30, 60, 20);
passText.setBounds(65, 30, 100, 20);
reset.setBounds( 170, 30, 80, 20);
// 设置提示标签的位置和大小
infoLab.setBounds(5, 65, 220, 30);
// 添加组件
// 添加第一行
frame.add(nameLab);
frame.add(nameText);
frame.add(submit);
// 添加第二行
frame.add(passLab);
frame.add(passText);
frame.add(reset);
// 添加第三行
frame.add(infoLab);
frame.setSize(280, 130);
// 设置窗体背景颜色
frame.getContentPane().setBackground(Color.PINK);
frame.setLocation(300, 200);
frame.setVisible(true);
}
}
public class MyActionEventDemo03
{
public static void main(String args[])
{
new ActionHandle1();
}
}