Java的GUI事件处理

事件和监听器

先来了解什么是事件,事件就是表示一个对象的状态发生了变化。例如,每当一个按钮按下时,实际按钮的状态就发生了改变,那么此时就会产生一个事件,而如果需要事件的监听者不断的监听事件的变化,并根据这些事件进行相应的处理。

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 接口定义的方法如下表所示。

序号方法描述
1void windowActivated(WindowEvent e)将窗口变为活动窗口时触发
2void windowDeactivated(WindowEvent e)将窗体变为不活动窗口是触发
3void windowClosing(WindowEvent e)当窗口正在关闭时触发
4void windowClosed(WindowEvent e)当窗口被关闭了触发
5void windowIconified(WindowEvent e)窗口从正常状态变为最小化状态时触发
6void windowDeiconified(WindowEvent e)窗口从最小化状态变为正常状态时触发
7void 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 接口只定义了一个方法,如下表所示。

序号事件描述
1void 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();
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值