Java 事件监听原理及Demo实现

简介

Java的事件监听是Java事件机制的实现,以Java Swing的事件机制为例,分析一下事件监听的各个组成部分以及功能:


Java事件机制的三个基本组成成分

1.事件对象

通常继承自java.util.EventObject的对象,一般可以用来判断事件类型的作用

2.事件源

触发事件的源头,在GUI和Swing编程中,如Button按钮等对象就是一个事件源

3.事件监听器

负责监听事件源发出的事件并作出响应动作的对象,通常实现java.util.EventListener接口

事件的一般流程

1.事件源注册监听器

2.事件发生,事件源向监听器发送事件对象

3.监听器对象响应事件


实现

下面用Demo来介绍事件机制的实现原理

1.事件对象类

import java.util.EventObject;

/**
 * Created by Xuyh at 2016/11/30 下午 04:00.
 *
 * <pre>
 *     自己理解事件对象的作用:
 *     (1)事件对象储存了事件源对象,
 *     当事件监听器方法进行处理程序的时候,
 *     如果需要改变事件源的属性值等等操作时候,
 *     就可以通过事件对象获取到事件源对象,
 *     从而对事件事件源的属性进行修改或者调用事件源的方法。
 *     (2)继承了java.util.EventObject之后的自定义事件对象,
 *     可以添加其他属性,比如说事件类型等等,
 *     添加一些必要的业务属性等。
 *
 * </pre>
 */
public class JohnsonEventObject extends EventObject {
	public static int EVENT_TYPE_ONE = 1;
	public static int EVENT_TYPE_TWO = 2;
	public static int EVENT_TYPE_THREE = 3;
	private int eventType;

	/**
	 * source是事件源
	 *
	 * @param source
	 */
	public JohnsonEventObject(Object source) {
		super(source);
	}

	public JohnsonEventObject(Object source, int eventType) {
		super(source);
		this.eventType = eventType;
	}

	@Override
	public Object getSource() {
		return super.getSource();
	}

	@Override
	public String toString() {
		return super.toString();
	}

	public int getEventType() {
		return eventType;
	}

	public void setEventType(int eventType) {
		this.eventType = eventType;
	}
}

在该事件对象类中,除了默认继承自java.util.EventObject的source(即事件源对象属性)之外,另外添加了一个eventType(事件类型属性),用来代表事件的类型。

当事件发生后,事件监听器的响应方法会接受到事件对象(作为方法参数被传递),事件对象中的事件源属性可以提供数据源对象供响应方法调用,从而改变事件源的属性等。


2.事件源类

import java.util.HashSet;
import java.util.Set;

/**
 * Created by Xuyh at 2016/11/30 下午 04:00.
 *
 * <pre>
 *     事件源是事件发生的地方,
 *     是事件触发的源头,
 *     事件监听器注册的地方。
 * </pre>
 */
public class JohnsonEventSource {
	/**
	 * 事件监听器的集合
	 * 
	 * <pre>
	 *     事件源中存储一个监听器集合,
	 *     当事件发生之后,事件源会依次调用
	 *     每个监听器的响应方法。
	 * </pre>
	 */
	private Set<JohnsonEventListener> eventListeners = new HashSet<JohnsonEventListener>();

	/**
	 * 注册监听器
	 * 
	 * <pre>
	 *     理解:
	 *     添加监听器
	 * </pre>
	 *
	 * @param eventListener
	 */
	public void addEventListener(JohnsonEventListener eventListener) {
		if (eventListener != null) {
			eventListeners.add(eventListener);
		}
	}

	/**
	 * 注销监听器
	 * 
	 * <pre>
	 *     理解:
	 *     把这个监听器去掉
	 * </pre>
	 *
	 * @param eventListener
	 * @return
	 */
	public boolean removeEventListener(JohnsonEventListener eventListener) {
		return eventListeners.remove(eventListener);
	}

	/**
	 * 发生事件1
	 * 
	 * <pre>
	 * 发生事件方法需要外部调用
	 * </pre>
	 */
	public void event1() {
		JohnsonEventObject object = new JohnsonEventObject(this, JohnsonEventObject.EVENT_TYPE_ONE);
		doOnAction(object);
	}

	/**
	 * 发生事件2
	 * 
	 * <pre>
	 * 发生事件方法需要外部调用
	 * </pre>
	 */
	public void event2() {
		JohnsonEventObject object = new JohnsonEventObject(this, JohnsonEventObject.EVENT_TYPE_TWO);
		doOnAction(object);
	}

	/**
	 * 发生事件3
	 * 
	 * <pre>
	 * 发生事件方法需要外部调用
	 * </pre>
	 */
	public void event3() {
		JohnsonEventObject object = new JohnsonEventObject(this, JohnsonEventObject.EVENT_TYPE_THREE);
		doOnAction(object);
	}

	/**
	 * 遍历监听器执行响应方法
	 * 
	 * @param eventObject
	 */
	private void doOnAction(JohnsonEventObject eventObject) {
		for (JohnsonEventListener listener : eventListeners) {
			listener.onAction(eventObject);
		}
	}

	/**
	 * <pre>
	 * 定义一个事件源方法,
	 * 给事件监听器调用,
	 * 用来体现事件对象保存事件源的作用。
	 * </pre>
	 * 
	 * @param message
	 */
	public void sourceFunction(String message) {
		System.out.println(message);
	}
}
事件源是事件触发的地方,其中有一个事件监听器集合,通过addEventListener方法可以添加事件监听器到监听器集合中,也就是经常说的“注册事件监听器”。

其中的doOnAction方法是必不可少的一个操作,即在事件发生之后遍历监听器集合,执行监听器定义的动作响应方法。

event1,event2,event3是定义的三个事件方法,模拟事件的发生,发生事件之后程序需要实例化事件对象(事件对象储存了事件源即本对象的引用),并将其作为参数依次调用每个监听器的动作响应方法,即上面的步骤。


3.事件监听器类

import java.util.EventListener;

/**
 * Created by Xuyh at 2016/11/30 下午 04:00.
 *
 * <pre>
 *     事件监听器定义了一个接口,
 *     用来规范事件发生之后事件源调用的处理方法
 * </pre>
 */
public interface JohnsonEventListener extends EventListener {
	/**
	 * 事件产生需要调用的方法
	 */
	public void onAction(JohnsonEventObject eventObject);
}
事件监听器是一个接口,里面定义了一个固定名字的响应方法,用来提供给事件源调用。

注册事件监听器就是实现监听器接口的响应方法并添加到事件源的监听器集合中。


其中,事件对象继承自java.util.EventObject ,源码如下

package java.util;

/**
 * <p>
 * The root class from which all event state objects shall be derived.
 * <p>
 * All Events are constructed with a reference to the object, the "source",
 * that is logically deemed to be the object upon which the Event in question
 * initially occurred upon.
 *
 * @since JDK1.1
 */

public class EventObject implements java.io.Serializable {

    private static final long serialVersionUID = 5516075349620653480L;

    /**
     * The object on which the Event initially occurred.
     */
    protected transient Object  source;

    /**
     * Constructs a prototypical Event.
     *
     * @param    source    The object on which the Event initially occurred.
     * @exception  IllegalArgumentException  if source is null.
     */
    public EventObject(Object source) {
        if (source == null)
            throw new IllegalArgumentException("null source");

        this.source = source;
    }

    /**
     * The object on which the Event initially occurred.
     *
     * @return   The object on which the Event initially occurred.
     */
    public Object getSource() {
        return source;
    }

    /**
     * Returns a String representation of this EventObject.
     *
     * @return  A a String representation of this EventObject.
     */
    public String toString() {
        return getClass().getName() + "[source=" + source + "]";
    }
}

事件监听类实现java.util.EventListener 接口,源码如下:

package java.util;

/**
 * A tagging interface that all event listener interfaces must extend.
 * @since JDK1.1
 */
public interface EventListener {
}


使用

定义好了事件监听Demo之后就可以测试使用了,下面根据这个Demo来实现几种事件监听的实现方式:

1.自身类作为事件监听器 :

import event.JohnsonEventListener;
import event.JohnsonEventObject;
import event.JohnsonEventSource;

/**
 * 自身类作为事件监听器
 * 
 * @Author Xuyh created at 2016年12月11日 下午5:57:46
 *
 */
public class TestMain implements JohnsonEventListener {

	public void onAction(JohnsonEventObject eventObject) {
		JohnsonEventSource source = (JohnsonEventSource) eventObject.getSource();
		source.sourceFunction("事件监听器  监听到事件--事件类型: " + String.valueOf(eventObject.getEventType()));
	}

	public static void main(String[] args) {
		JohnsonEventSource source = new JohnsonEventSource();
		source.addEventListener(new TestMain());
		source.event1();
		source.event2();
		source.event3();
	}

}

2.外部类作为事件监听器 :

监听器:

package xuyihao;

import event.JohnsonEventListener;
import event.JohnsonEventObject;
import event.JohnsonEventSource;

/**
 * 外部类作为事件监听器的外部类
 * 
 * @Author Xuyh created at 2016年12月11日 下午6:02:46
 *
 */
public class OuterListerner implements JohnsonEventListener {

	public void onAction(JohnsonEventObject eventObject) {
		JohnsonEventSource source = (JohnsonEventSource) eventObject.getSource();
		source.sourceFunction("事件监听器  监听到事件--事件类型: " + String.valueOf(eventObject.getEventType()));
	}
}


/**
 * 外部类作为事件监听器的外部类
 * 
 * @Author Xuyh created at 2016年12月11日 下午6:02:46
 *
 */
public class JohnsonMain {
	public static void main(String args[]) {
		exentTest();
	}

	/**
	 * 外部类作为事件监听器
	 */
	public static void exentTest() {
		JohnsonEventSource source = new JohnsonEventSource();
		source.addEventListener(new OuterListerner());
		source.event1();
		source.event2();
		source.event3();
	}
}

/**
 * 
 * 
 * @Author Xuyh created at 2016年12月11日 下午6:02:46
 *
 */
public class JohnsonMain {
	public static void main(String args[]) {
		exentTest();
	}

	/**
	 * 外部类作为事件监听器
	 */
	public static void exentTest() {
		JohnsonEventSource source = new JohnsonEventSource();
		source.addEventListener(new OuterListerner());
		source.event1();
		source.event2();
		source.event3();
	}
}


3.匿名内部类作为事件监听器 :

import event.JohnsonEventListener;
import event.JohnsonEventObject;
import event.JohnsonEventSource;

public class JohnsonMain {
	public static void main(String args[]) {
		eventTest();
	}
		

	/**
	 * 匿名方式实现监听
	 */
	public static void eventTest() {
		System.out.println("匿名方式实现监听");
		// 定义事件源
		JohnsonEventSource source = new JohnsonEventSource();
		// 事件源绑定事件监听1,这里使用匿名方式实现监听器
		source.addEventListener(new JohnsonEventListener() {
			public void onAction(JohnsonEventObject eventObject) {
				JohnsonEventSource source1 = (JohnsonEventSource) eventObject.getSource();
				source1.sourceFunction("事件监听器 1 监听到事件--事件类型: " + String.valueOf(eventObject.getEventType()));
				// 这里也可以直接使用外部的source对象,本质上是一个对象
			}
		});
		// 事件源绑定事件监听2
		source.addEventListener(new JohnsonEventListener() {
			public void onAction(JohnsonEventObject eventObject) {
				JohnsonEventSource source2 = (JohnsonEventSource) eventObject.getSource();
				source2.sourceFunction("事件监听器 2 监听到事件--事件类型: " + String.valueOf(eventObject.getEventType()));
			}
		});
		// 启动事件
		source.event1();
		source.event2();
		source.event3();
	}
}

4.内部类作为事件监听器:

import event.JohnsonEventListener;
import event.JohnsonEventObject;
import event.JohnsonEventSource;

/**
 * 内部类作为事件监听器
 *
 * Created by Xuyh at 2016/08/05 下午 03:26.
 */
public class JohnsonMain {
	public static void main(String args[]) {
		eventTest();
	}

	/**
	 * 定义监听器类实现接口方式
	 */
	public static void eventTest() {
		System.out.println("定义监听器类实现接口方式实现监听");
		JohnsonEventSource source = new JohnsonEventSource();
		// 事件源绑定事件监听1
		source.addEventListener(new ExampleListener(1));
		// 事件源绑定事件监听2
		source.addEventListener(new ExampleListener(2));
		// 启动事件
		source.event1();
		source.event2();
		source.event3();
	}

	public static class ExampleListener implements JohnsonEventListener {
		private int number;

		public ExampleListener(int number) {
			this.number = number;
		}

		public void onAction(JohnsonEventObject eventObject) {
			JohnsonEventSource source = (JohnsonEventSource) eventObject.getSource();
			source.sourceFunction("事件监听器 " + number + " 监听到事件--事件类型: " + String.valueOf(eventObject.getEventType()));
		}
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章