首页 > 文章列表 > 如何在Java中给按钮添加事件监听器?

如何在Java中给按钮添加事件监听器?

java
364 2023-04-24

Java怎么给按钮添加监视器

第一种:匿名对象

界面代码

package dragon;

import java.awt.FlowLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.Box;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JOptionPane;



public class View3 extends JFrame{

	private JButton submit, cancel;

	public View3() {

		this.init();

		this.setLayout(new FlowLayout());

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		this.setBounds(300,300,250,100);

		this.setVisible(true);

	}

	

	private void init() {

		submit = new JButton("确定");

		cancel = new JButton("取消");

		Box box = Box.createHorizontalBox();

		box.add(submit);

		box.add(Box.createHorizontalStrut(20));

		box.add(cancel);

		

		submit.addActionListener(new ActionListener() {

			@Override

			public void actionPerformed(ActionEvent e) {

				JOptionPane.showMessageDialog(null, "点击了确定按钮", "确定", JOptionPane.INFORMATION_MESSAGE);

			}

		});

		

		cancel.addActionListener(new ActionListener() {

			@Override

			public void actionPerformed(ActionEvent e) {

				JOptionPane.showMessageDialog(null, "点击了取消按钮", "取消", JOptionPane.CANCEL_OPTION);

			}

		});

		this.add(box);

	}

}

测试代码

package dragon;public class Test {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->public static void main(String[] args) {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->new View3();}}package dragon;



public class Test {

	public static void main(String[] args) {

		new View3();

	}

}

运行截图:

说明:比较常见的一种方式,初学Java的朋友一般都会见到这种方法,但是同时这也是很老的一种方式,不能很好的体现Java代码的变化。一般并不推荐使用这种方式,但是作为学习Java语法的例子,还是非常不错的

第二种:实现类

界面代码

package dragon;



import java.awt.FlowLayout;

import javax.swing.Box;

import javax.swing.JButton;

import javax.swing.JFrame;



public class View4 extends JFrame{

	private JButton submit, cancel;

	private SubmitListener submitListener;

	private CancelListener cancelListener;

	

	public View4() {

		this.init();

		this.setLayout(new FlowLayout());

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		this.setBounds(300,300,250,100);

		this.setVisible(true);

	}

	

	private void init() {

		submit = new JButton("确定");

		cancel = new JButton("取消");

		Box box = Box.createHorizontalBox();

		box.add(submit);

		box.add(Box.createHorizontalStrut(20));

		box.add(cancel);

		

		submitListener = new SubmitListener();

		cancelListener = new CancelListener();

		submit.addActionListener(submitListener);

		cancel.addActionListener(cancelListener);

		this.add(box);

	}

}

实现 ActionListener 接口的类

package dragon;



import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;



import javax.swing.JOptionPane;



public class SubmitListener implements ActionListener {



	@Override

	public void actionPerformed(ActionEvent e) {

		JOptionPane.showMessageDialog(null, "点击了确定按钮", "确定", JOptionPane.INFORMATION_MESSAGE);

	}

}



class CancelListener implements ActionListener {

	@Override

	public void actionPerformed(ActionEvent e) {

		JOptionPane.showMessageDialog(null, "点击了取消按钮", "取消", JOptionPane.CANCEL_OPTION);

	}

	

}

测试代码

package dragon;



public class Test {

	public static void main(String[] args) {

		new View4();

	}

}

运行截图:

说明:使用继承 ActionListener 接口的类,作为监视器,是一种很好的方式。

第三种:实现接口

界面代码

package dragon;



import java.awt.FlowLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;



import javax.swing.Box;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JOptionPane;



public class View1 extends JFrame implements ActionListener{

	private JButton submit, cancel;

	public View1() {

		this.init();

		this.setLayout(new FlowLayout());

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		this.setBounds(300,300,250,100);

		this.setVisible(true);

	}

	

	private void init() {

		submit = new JButton("确定");

		cancel = new JButton("取消");

		Box box = Box.createHorizontalBox();

		box.add(submit);

		box.add(Box.createHorizontalStrut(20));

		box.add(cancel);

		

		

		submit.addActionListener(this);

		cancel.addActionListener(this);

		this.add(box);

	}



	@Override

	public void actionPerformed(ActionEvent e) {

		if (e.getSource() == submit) {

			JOptionPane.showMessageDialog(null, "点击了确定按钮", "确定", JOptionPane.INFORMATION_MESSAGE);

		}

		if (e.getSource() == cancel) {

			JOptionPane.showMessageDialog(null, "点击了取消按钮", "取消", JOptionPane.CANCEL_OPTION);

		}

	}

	 

}

测试代码

package dragon;



public class Test {

	public static void main(String[] args) {

		new View1();

	}

}

运行截图

说明:这种方式和上面第二种差不多,但是我个人很喜欢这种,主要是少写了几个类。这也是一种很好的方式,主要是传递参数的方式,我以前对这个 submit.addActionListener(this); 很迷惑,哈哈。

第四种:Lambda 表达式

界面代码

package dragon;



import java.awt.FlowLayout;

import javax.swing.Box;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JOptionPane;



public class View extends JFrame{

	private JButton submit, cancel;

	public View() {

		this.init();

		this.setLayout(new FlowLayout());

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		this.setBounds(300,300,250,100);

		this.setVisible(true);

	}

	

	private void init() {

		submit = new JButton("确定");

		cancel = new JButton("取消");

		Box box = Box.createHorizontalBox();

		box.add(submit);

		box.add(Box.createHorizontalStrut(20));

		box.add(cancel);

		

		submit.addActionListener((e)->{

			JOptionPane.showMessageDialog(null, "点击了确定按钮", "确定", JOptionPane.INFORMATION_MESSAGE);

		});

		

		cancel.addActionListener((e)->{

			JOptionPane.showMessageDialog(null, "点击了取消按钮", "取消", JOptionPane.CANCEL_OPTION);

		});

		this.add(box);

	}

}

测试代码

package dragon;



public class Test {

	public static void main(String[] args) {

		new View();

	}

}

运行截图

说明:Lambda 表达式 是Java 8 的新特性,主要是简化了代码,这个可以理解为对第一种匿名对象方式的简化,主要是去除了很多的模板代码,从传递对象演进到传递行为(因为其它是多余的)。这个我现在比较喜欢使用,使用这种方法,可以少些很多的代码。当然了,它也是有不足的,使用 Lambda 表达式的前提是这个接口必须是函数式接口(接口中只有一个抽象方法),一般这种接口都会使用一个注解进行修饰:@FunctionalInterface

第五种:注解

界面代码

package dragon;



import java.awt.FlowLayout;

import java.awt.event.ActionListener;

import java.lang.reflect.InvocationTargetException;



import javax.swing.Box;

import javax.swing.JButton;

import javax.swing.JFrame;





public class View5 extends JFrame{

	@ButtonListener(listener=SubmitListener.class)

	private JButton submit;

	

	@ButtonListener(listener=CancelListener.class)

	private JButton cancel;

	

	public View5() {

		this.init();

		this.setLayout(new FlowLayout());

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		this.setBounds(300,300,250,100);

		this.setVisible(true);

	}

	

	private void init() {

		submit = new JButton("确定");

		cancel = new JButton("取消");

		Box box = Box.createHorizontalBox();

		box.add(submit);

		box.add(Box.createHorizontalStrut(20));

		box.add(cancel);

		

		//处理注解的类对象

		ButtonProcess process;

		process = new ButtonProcess();

		try {

			process.addListener(this);

		} catch (Exception e) {

			//直接处理 Exception 异常

			e.printStackTrace();

		}

		

		this.add(box);

	}

}

注解处理类

package dragon;



import java.awt.event.ActionListener;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import javax.swing.JButton;



public class ButtonProcess {

	public void addListener(Object ob) throws IllegalArgumentException, IllegalAccessException, NoSuchMethodException, SecurityException, InstantiationException, InvocationTargetException {

		Class<?> clazz = ob.getClass();

		Field[] fields = clazz.getDeclaredFields();

		for (Field field : fields) {

			//访问私有的成员变量,必须设置访问权限

			field.setAccessible(true);

			Object object = field.get(ob);

			//获取成员变量的注解

			ButtonListener buttonListener = field.getDeclaredAnnotation(ButtonListener.class);

			//如果注解对象不为空(有的成员变量没有注解,所以该对象为 null),

			//并且 该成员变量所对应的对象的类型是JButton 类型(这里只有一个注解,可以不需要这个判断,

			//但是从代码的健壮性角度来说,应该加上,如果有多个注解,必须进行判断才行)。

			if (buttonListener != null && object != null && object instanceof JButton) {

				//获取注解的成员变量(必须经过判断之后才能,获取成员变量,注解对象可能为 null)

				Class<? extends ActionListener> listener = buttonListener.listener();

				Constructor<?> con = listener.getDeclaredConstructor(new Class[] {});

				ActionListener actionListener = (ActionListener) con.newInstance(new Object[] {});

			//	ActionListener actionListener = listener.newInstance();

				//给按钮对象添加监视器

				((JButton)object).addActionListener(actionListener);

			}

		}

	}

}

测试代码

package dragon;



public class Test {

	public static void main(String[] args) {

		new View5();

	}

}

注意:ActionListener actionListener = listener.newInstance(); 这句话被我注释了,因为在 Java 9中,Class 对象的 newInstance()废弃了,不再推荐使用了,但是这个ActionListener 是一个接口,接口是没有构造方法的,但是我使用反射的方式获取到了,因为接口也是类的一种,可能是含有 私有的构造方法。

运行截图:

说明:这种实现方式,是这里最复杂的,但是不能说它是最差的(不过速度应该是最慢的了,毕竟反射的速度是没有直接创建对象快的。),上面代码参考了疯狂Java讲义,但是加了一点我的注释,但是这是一种新的方式,毕竟我们不能永远只写一些很容易就看得懂的代码,也是需要学习新的知识,这个例子主要是学习如何使用注解的,可以看出来虽然很复杂,但是这也是很有趣的一种方式。