现在的位置: 首页 > 综合 > 正文

java事件处理机制 自定义事件

2013年03月18日 ⁄ 综合 ⁄ 共 16337字 ⁄ 字号 评论关闭

ava中的事件机制的参与者有3种角色:

  1.event object:事件状态对象,用于listener的相应的方法之中,作为参数,一般存在与listerner的方法之中

  2.event source:具体的事件源,比如说,你点击一个button,那么button就是event source,要想使button对某些事件进行响应,你就需要注册特定的listener。

  3.event listener:具体的对监听的事件类,当它监听到event object产生的时候,它就调用相应的方法,进行处理。

  先看看jdk提供的event包:

  public interface EventListener:所有事件侦听器接口必须扩展的标记接口。

  public class EventObject extends Object implements Serializable

  所有事件状态对象都将从其派生的根类。 所有 Event 在构造时都引用了对象 "source",在逻辑上认为该对象是最初发生有关 Event 的对象。

  在Java2处理事件时,没有采用dispatchEvent()-postEvent()-handleEvent()方式,采用了监听器类,每个事件类都有相关联的监听器接口。事件从事件源到监听者的传递是通过对目标监听者对象的Java方法调用进行的。

  对每个明确的事件的发生,都相应地定义一个明确的Java方法。这些方法都集中定义在事件监听者(EventListener)接口中,这个接口要继承 java.util.EventListener。 实现了事件监听者接口中一些或全部方法的类就是事件监听者。

  伴随着事件的发生,相应的状态通常都封装在事件状态对象中,该对象必须继承自java.util.EventObject。事件状态对象作为单参传递给应响应该事件的监听者方法中。发出某种特定事件的事件源的标识是:遵从规定的设计格式为事件监听者定义注册方法,并接受对指定事件监听者接口实例的引用。

  首先问个问题:您熟悉java.util.EventObject 和java.util.EventListener两个类以及他们已有的子类吗?

  如果你已经能够熟练使用jdk为我们提供的事件监听器,并且很熟悉MouseEvent, KeyEvent, WindowEvent等等这些jdk为我们准备好的事件,那么想必你对java的事件机制已经有所理解。但是也许你还是觉得虽然用起来没什么问题,但是原理还是有些糊涂,那么下面我们再进一步自己实现这些事件和监听器,即自定义事件。

  其实自定义事件在java中很有用处,我们有的时候想让自己的程序产生一个事件,但有不希望(或者不可能)用鼠标,键盘之类的输入设备进行操作,比如你写一个应用程序,在这个程序中一旦收到邮件就对邮件进行相关处理,对于“收到邮件”这个事件,jdk中就没有定义。对于这样的事件,以及对于这样的事件的监听器,我们只能自己动手完成了。

那么下面就以实例开始我们这个“创新”的过程:首先,类EventObject作为父类用来生成我们自己的事件类,接口EventListener用来实现我们自己的监听器;剩下的事情就是如何注册这些事件以及测试他们了。

  (1)通过DoorEvent.java文件创建DoorEvent类,这个类继承EventObject。

  /**

  * 定义事件对象,必须继承EventObject

  */

  package test;

  import java.util.EventObject;

  public class DoorEvent extends EventObject {

  private String doorState = "";//表示门的状态,有“开”和“关”两种

  public DoorEvent(Object source, String doorState) {

  super(source);

  this.doorState = doorState;

  }

  public void setDoorState(String doorState) {

  this.doorState = doorState;

  }

  public String getDoorState() {

  return this.doorState;

  }

  }

  (2)定义新的事件监听接口,该接口继承自EventListener;该接口包含对doorEvent事件的处理程序:

  /**

  * 定义监听接口,负责监听DoorEvent事件

  */

  package test;

  import java.util.EventListener;

  public interface DoorListener extends EventListener {

  public void doorEvent(DoorEvent event);

  }

  通过上面的接口我们再定义事件监听类,这些类具体实现了监听功能和事件处理功能。

  /**

  * 该类为 门1监听接口的实现,做具体的开门,关门动作

  */

  package test;

  public class DoorListener1 implements DoorListener {

  public void doorEvent(DoorEvent event) {

  if(event.getDoorState()!=null&&event.getDoorState().equals("open"))

  {

  System.out.println("门1打开");

  }

  else

  {

  System.out.println("门1关闭");

  }

  }

  }

  /**

  * 该类为 门2监听接口的实现,做具体的开门,关门,以及开灯,关灯动作

*/

  package test;

  public class DoorListener2 implements DoorListener {

  public void doorEvent(DoorEvent event) {

  if(event.getDoorState()!=null&&event.getDoorState().equals("open"))

  {

  System.out.println("门2打开,同时打开走廊的灯");

  }

  else

  {

  System.out.println("门2关闭,同时关闭走廊的灯");

  }

  }

  }

  (3)通过DoorManager.java创造一个事件源类,它用一个Collection listeners对象来存储所有的事件监听器对象,存储方式是通过addDoorListener(..)这样的方法。 notifyListeners(..)是触发事件的方法,用来通知系统:事件发生了,你调用相应的处理函数吧。

  /**

  * 事件源对象,在这里你可以把它想象成一个控制开门关门的遥控器,

  * (如果是在swing中,就类似一个button)

  */

  package test;

  import java.util.*;

  public class DoorManager {

  private Collection listeners;

  /**

  * 添加事件

  * @param listener DoorListener

  */

  public void addDoorListener(DoorListener listener) {

  if (listeners == null) {

  listeners = new HashSet();

  }

  listeners.add(listener);

  }

  /**

  * 移除事件

  * @param listener DoorListener

  */

  public void removeDoorListener(DoorListener listener) {

  if (listeners == null)

  return;

  listeners.remove(listener);

  }

  /**

  * 触发开门事件

  */

  protected void fireWorkspaceOpened() {

  if (listeners == null)

  return;

  DoorEvent event = new DoorEvent(this, "open");

  notifyListeners(event);

  }

  /**

  * 触发关门事件

  */

  protected void fireWorkspaceClosed() {

  if (listeners == null)

return;

  DoorEvent event = new DoorEvent(this, "close");

  notifyListeners(event);

  }

  /**

  * 通知所有的DoorListener

  */

  private void notifyListeners(DoorEvent event) {

  Iterator iter = listeners.iterator();

  while (iter.hasNext()) {

  DoorListener listener = (DoorListener) iter.next();

  listener.doorEvent(event);

  }

  }

  }

  (4)好了,最后写一个测试程序测试一下我们自定义的事件吧,这段程序应该不难理解吧:)

  /**

  * 主程序,就想象成要开门的哪个人

  */

  package test;

  public class DoorMain {

  public static void main(String []args)

  {

  DoorManager manager = new DoorManager();

  manager.addDoorListener(new DoorListener1());//给门1增加监听器

  manager.addDoorListener(new DoorListener2());//给门2增加监听器

  //开门

  manager.fireWorkspaceOpened();

  System.out.println("我已经进来了");

  //关门

  manager.fireWorkspaceClosed();

  }

  }

  运行DoorMain

  门1打开

  门2打开,同时打开走廊的灯

  我已经进来了

  门1关闭

  门2关闭,同时关闭走廊的灯

  下面我们看一个jdk内部是如何处理事件机制的,你可以和上面的自定义事件做一个比较,你会高兴的发现机制是一样的。

  /**

  * java swing的监听器,实现ActionListener接口,注意参数:(事件状态类:ActionEvent)

  *

  */

  package test;

  import java.awt.*;

  import java.awt.event.*;

  import javax.swing.*;

  class SimpleListener implements ActionListener {

  /*

  * 利用该类来监听事件源产生的事件,利用响应机制

  */

  public void actionPerformed(ActionEvent e) {

  String buttonName = e.getActionCommand();

if (buttonName.equals("按钮1"))

  System.out.println("按钮1 被点击");

  }

  }

  public class ActionTest {

  private static JFrame frame; // 定义为静态变量以便main使用

  private static JPanel myPanel; // 该面板用来放置按钮组件

  private JButton button1; // 这里定义按钮组件

  public ActionTest() { // 构造器, 建立图形界面

  // 新建面板

  myPanel = new JPanel();

  // 新建按钮

  button1 = new JButton("按钮1"); // 新建按钮1

  // 建立一个actionlistener让按钮1注册,以便响应事件

  SimpleListener ourListener = new SimpleListener();

  button1.addActionListener(ourListener);

  myPanel.add(button1); // 添加按钮到面板

  }

  public static void main(String s[]) {

  ActionTest gui = new ActionTest(); // 新建Simple1组件

  frame = new JFrame("Simple1"); // 新建JFrame

  // 处理关闭事件的通常方法

  frame.addWindowListener(new WindowAdapter() {

  public void windowClosing(WindowEvent e) {

  System.exit(0);

  }

  });

  frame.getContentPane().add(myPanel);

  frame.pack();

  frame.setVisible(true);

  }

  }

  在这里,我们再看一下java中的事件机制的参与者的3种角色:

  我们定义了一个SimpleListener 实现ActionListener接口,

  1.event object:事件状态对象,用于listener的相应的方法之中。用了jdk提供的ActionEvent,不需要我们自己定义。

  2.event source:具体的事件源,就是哪个button,,注册特定的SimpleListener。

  3.event listener:具体的对监听的事件类,当它监听到event

  object产生的时候,它就调用相应的方法,进行处理。这里是我们自己定义的SimpleListener。

  是不是和上面自定义的事件在机制上完全一致呢?Yes

  ---------------------------------------------------------------------------------------------------------------------------

这里你也许会问,为什么event object不需要我们自己定义呢?你可以想一下,这是一个表示“事件状态变化”的类,你能扑获“鼠标变化”

  吗?这好象和平台有关的低层编码了,所有所不可能扑获,也没有必要去扑获,这些jdk已经给我们实现了。简单的看一下ActionEvent这个类

  ,它继承了java.awt.AWTEvent, 在这个类的构造方法源码如下:

  static {

  /* ensure that the necessary native libraries are loaded */

  Toolkit.loadLibraries();

  if (!GraphicsEnvironment.isHeadless()) {

  initIDs();

  }

  }

  我们在看jdk官方的解释:

  Toolkit是 Abstract Window Toolkit 的所有实际实现的抽象超类。Toolkit 的子类被用于将各种组件绑定到特定本机工具包实现。大多数应

  用程序不应直接调用该类中的任何方法。Toolkit 定义的方法是“胶合剂”,将 java.awt 包中与平台无关的类与 java.awt.peer 中的对应物

  连接起来。Toolkit 定义的一些方法能直接查询本机操作系统。

JAVA自定义事件小例子(转)

package demo;

import java.util.EventObject;

/**
* Title: 事件处理类,继承了事件基类
* Description:
* Copyright: Copyright (c) 2005
* Company: cuijiang
* @author not attributable
* @version 1.0
*/
public class DemoEvent extends EventObject
{
   private Object obj;
   private String sName;
   public DemoEvent(Object source,String sName)   {
     super(source);
     obj = source;
     this.sName=sName;
   }
   public Object getSource()
   {
     return obj;
   }
   public void say()
   {
     System.out.println("这个是 say 方法...");
   }

   public String getName()
   {
     return sName;
   }
}


package demo;

import java.util.EventListener;

/**
* Title: 监听器接口
* Description:
* Copyright: Copyright (c) 2005
* Company: cuijiang
* @author not attributable
* @version 1.0
*/
public interface DemoListener extends EventListener{
   public void demoEvent(DemoEvent dm);
}

package demo;
import java.util.*;

/**
* Title: 使用事件的类
* Description: 该类实现了监听器的添加和监听器方法的执行,并且实现了由于属性的改变而执行事件
* Description: 在添加、删除、执行监听器的时候都要注意同步问题
* Copyright: Copyright (c) 2005
* Company: cuijiang
* @author not attributable
* @version 1.0
*/
public class DemoSource{
   private Vector repository = new Vector();
   private DemoListener dl;
   private String sName="";

   public DemoSource()
   {
   }

   //注册监听器,如果这里没有使用Vector而是使用ArrayList那么要注意同步问题
   public void addDemoListener(DemoListener dl)
   {
     repository.addElement(dl);//这步要注意同步问题
   }

   //如果这里没有使用Vector而是使用ArrayList那么要注意同步问题
   public void notifyDemoEvent(DemoEvent event) {
     Enumeration enum = repository.elements();//这步要注意同步问题
     while(enum.hasMoreElements())
     {
       dl = (DemoListener)enum.nextElement();
       dl.demoEvent(event);
     }
   }

   //删除监听器,如果这里没有使用Vector而是使用ArrayList那么要注意同步问题
   public void removeDemoListener(DemoListener dl)
   {
     repository.remove(dl);//这步要注意同步问题
   }

   /**
    * 设置属性
    * @param str1 String
    */
   public void setName(String str1)
   {
     boolean bool=false;
     if(str1==null && sName!=null) bool=true;
     else if(str1!=null && sName==null) bool=true;
     else if(!sName.equals(str1)) bool=true;

     this.sName=str1;

     //如果改变则执行事件
     if(bool) notifyDemoEvent(new DemoEvent(this,sName));
   }

   public String getName()
   {
     return sName;
   }
}

package demo;

import java.lang.Thread;

/**
* Title: 测试类
* Description: 测试了由于改变属性而引起的事件发生
* Copyright: Copyright (c) 2005
* Company: cuijiang
* @author not attributable
* @version 1.0
*/
public class TestDemo
     implements DemoListener {
   private DemoSource ds;

   public TestDemo()
   {
     ds=new DemoSource();
     ds.addDemoListener(this);
     System.out.println("添加监听器完毕");
     try {
       Thread.sleep(3000);
       //改变属性,触发事件
       ds.setName("改变属性,触发事件");
     }
     catch (InterruptedException ex) {
       ex.printStackTrace();
     }

     ds.addDemoListener(this);
     System.out.println("添加监听器完毕2");
     try {
       Thread.sleep(3000);
       //改变属性,触发事件
       ds.setName("改变属性,触发事件2");
     }
     catch (InterruptedException ex) {
       ex.printStackTrace();
     }

     ds.removeDemoListener(this);
     System.out.println("添加监听器完毕3");
     try {
       Thread.sleep(3000);
       //改变属性,触发事件
       ds.setName("改变属性,触发事件3");
     }
     catch (InterruptedException ex) {
       ex.printStackTrace();
     }


   }

   public static void main(String args[])
   {

     new TestDemo();
   }

   /**
    * demoEvent
    *
    * @param dm DemoEvent
    * @todo Implement this test.DemoListener method
    */
   public void demoEvent(DemoEvent dm) {
     System.out.println("事件处理方法");
     System.out.println(dm.getName());
     dm.say();
   }
}

  --sunfruit

    用户自定义事件

   

User defined Event listeners java

All of us who have used java.awt.event package in either applets
or in Frames or in swing JFrame, shall agree to the fact that event
propagation and listener concept is very very useful for capturing
any action initiated either by user or by system, should be caught
at the right place and without unneccessarily wasting time traversing
through all the way from begining to end of source code just to know
any takers for this event.

This concept is implemented in form of MouseEvent, KeyEvent, WindowEvent so on so forth.

JDK has given us a handle for creating our own event object and as well
as event handling framework using java.util.EventObject and java.util.EventListener.

You can imagine a scenario whereby you have to write an application, in
which a email notification feature in a forum.

Whenever a special event takes place , then your have to notify all the users
who have registered themselves for this program.

One solution is to use a Database and query all the users from the table
and send notification to each and every user.
But this is more of Database centric approach like old days thick client
and server model.

Think about the overhead on database and instead another solution is
to create an event notification framework, whereby you have to create
your own version of Event Object and Event Listeners.

Event object represents the special event and all the users who register
themselves for the event implements this Event listener.

Let us take a more deeper plunge into this:

1. Create a Demo event by creating a DemoEvent.java file that
extends to java.util.EventObject.

This class has a constructor that takes the event originator object (DemoSource).
and a method getSource(), that gives the reference to the object that originated
this event.

DemoEvent.java


package demo.listener;

import java.util.EventObject;

public class DemoEvent extends EventObject
{
	Object obj;
	public DemoEvent(Object source)
	{
		super(source);
		obj = source;

	}
	public Object getSource()
	{
		return obj;
	}
	public void say()
	{
		System.out.println("This is say method...");
	}

}

2. Create the source of event notification file DemoSource.java
It has a java.util.Vector that acts like a repository for storing all the
listeners to the events this source provides.

It has two other common method such as addListener(..) is to add any
new user to this event.

And notifyDemoEvent(..) is to alert all the users about this perticular event
occurance.

DemoEvent.java


package demo.listener;
import java.util.*;

public class DemoSource
{
	private Vector repository = new Vector();
	DemoListener dl;
	public DemoSource()
	{

	}
	public void addDemoListener(DemoListener dl)
	{
		repository.addElement(dl);
	}
	public void notifyDemoEvent()
	{
		Enumeration enum = repository.elements();
		while(enum.hasMoreElements())
		{
			dl = (DemoListener)enum.nextElement();
			dl.demoEvent(new DemoEvent(this));
		}
	}
}

3. Define a listener interface that extends to java.util.EventListener
and contains the method for invoking the Event, here it is demoEvent(DemoEvent de).

DemoListener.java


package demo.listener;

import java.util.EventListener;

public interface DemoListener extends EventListener
{
	public void demoEvent(DemoEvent dm);

}

4. Define all the users, who want to listen to this events.
These objects should implement DemoListener, to be able to
capture the event propagated from DemoSource.java.

Listener1.java


package demo.listener;

public class Listener1 implements DemoListener
{
	public void demoEvent(DemoEvent de)
	{
		System.out.println("Inside listener1...");
	}
}

Listener2.java


package demo.listener;

public class Listener2 implements DemoListener
{
	public void demoEvent(DemoEvent de)
	{
		System.out.println("Inside listener2...");
	}
}

Listener3.java


package demo.listener;

public class Listener3 implements DemoListener
{
	public void demoEvent(DemoEvent de)
	{
		System.out.println("Inside listener3...");
	}
}

5. Now it time to write the client for testing this Framework.
Create a client such as TestDemo.java and create a DemoSource
object and all the users such as Listener1, Listener2, Listener3.
And add all these listeners to the demo source by using the addDemoListener(..).
When the notifyDemoEvent(..) is called on the demo source object,
the event gets notified to all the users (listener1, listener2, listener3)
and  the  output comes out to be

Inside listener1...
Inside listener2...
Inside listener3...

TestDemo.java


package demo.listener;

public class TestDemo
{
	DemoSource ds;

	public TestDemo()
	{
		try{
			ds = new DemoSource();
			Listener1 l1 = new Listener1();
			Listener2 l2 = new Listener2();
			Listener3 l3 = new Listener3();

			ds.addDemoListener(l1);
			ds.addDemoListener(l2);
			ds.addDemoListener(l3);

			ds.notifyDemoEvent();

		}catch(Exception ex){ex.printStackTrace();}
	}

	public static void main(String args[])
	{
		new TestDemo();
	}
}

java中的事件机制的参与者有3种角色:

1.event object:就是事件产生时具体的“事件”,用于listener的相应的方法之中,作为参数,一般存在于listerner的方法之中

2.event source:具体的接受事件的实体,比如说,你点击一个button,那么button就是eventsource,这样你必须使button对某些事件进行响应,你就需要注册特定的listener,比如说MouseEvent之中的MouseClicked方法,这时它就必须有了add方法

3.event listener:具体的进行监听的事件类,当有其对应的event object产生的时候,它就调用相应的方法,进行处理。在windows程序设计里边这种响应使用callback机制来实现的

 

首先,定义事件,使其继承java.util.EventObject类。(jdk使用1.6)

 

public class RunPerformEvent extends EventObject {

    /**
     * 序列化版本号
     */
    private static final long serialVersionUID = 1L;
   
    private Object objsource;
    private Object message;
   
    public RunPerformEvent(Object source,Object message) {
        super(source);
        // TODO Auto-generated constructor stub
        this.objsource = source;
        this.message = message;
    }
   
    public Object getObjsource() {
        return objsource;
    }

    public void setObjsource(Object objsource) {
        this.objsource = objsource;
    }

    public Object getMessage() {
        return message;
    }

    public void setMessage(Object message) {
        this.message = message;
    }
}

 

其次,定义事件监听实现 java.util.EventListener,包含对RunPerformEvent 事件的处理

 

public interface IRunPerformEventListener extends EventListener{
    void runMessageChanged(RunPerformEvent event); //自定义的实现方法
}

 

第三,定义事件监听管理类,实现对监听的添加,删除和启动

 

import java.util.ArrayList;
import java.util.List;
import com.szl.listenner.iface.IRunPerformEventListener;
import com.szl.listenner.model.RunPerformEvent;

public class ManagerListener {

    private List<IRunPerformEventListener> listeners = null;
   
    public ManagerListener()
    {
        this.listeners = new ArrayList<IRunPerformEventListener>();
    }   
   
    //添加一个监听
    public void addRunPerformEventListener(IRunPerformEventListener e)
    {
        this.listeners.add(e);
    }
   
    //删除一个监听
   
    public void deleteRunPerformEventListener(IRunPerformEventListener e)
    {
        this.listeners.remove(e);
    }
   
    //激活监听事件
    public void fireRunPerformEventListener(RunPerformEvent event)
    {
        for(IRunPerformEventListener listener : this.listeners)
        {
            listener.runMessageChanged(event);
        }
    }
}

 

第四步,添加监听事件,并调用测试

public class UseEventListener {
   
    ManagerListener ml;
    public UseEventListener()
    {
        ml =  new ManagerListener();
        ml.addRunPerformEventListener(new EventInterface());//添加自定义事件
    }
   
    //执行自定义事件的方法
    public void testListener(String str){
        ml.fireRunPerformEventListener(new RunPerformEvent(this,str)); //this 指本类,是将本类注入监听器
    }
   
    //内部类,实现监听
    private class EventInterface implements IRunPerformEventListener
    {
        public void runMessageChanged(RunPerformEvent event) {
            // TODO Auto-generated method stub
            do_runMessageChanged_actionevent(event);
        }
    }

    //触发自定义事件
    protected void do_runMessageChanged_actionevent(final RunPerformEvent e)
    {
        System.out.println("执行事件方法!"+e.getMessage());
    }
   
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        UseEventListener useEvent = new UseEventListener();
        useEvent.testListener("事件传过来的参数");
    }
}

 

ok。至此已写好一个自定义事件监听的例子。(好好学习,天天向上,一天一点进步!)

抱歉!评论已关闭.