Posted on 2007-04-13 09:22
chenweicai 閱讀(10338)
評論(14) 編輯 收藏
java中的事件機制的參與者有3種角色:
1.event object:就是事件產(chǎn)生時具體的“事件”,用于listener的相應(yīng)的方法之中,作為參數(shù),一般存在與listerner的方法之中
2.event source:具體的接受事件的實體,比如說,你點擊一個button,那么button就是event source,這樣你必須使button對某些事件進(jìn)行相應(yīng),你就需要注冊特定的listener,比如說MouseEvent之中的MouseClicked方法,這是他就必須有了add方法
3.event listener:具體的對監(jiān)聽的事件類,當(dāng)有其對應(yīng)的event object產(chǎn)生的時候,它就調(diào)用相應(yīng)的方法,進(jìn)行處理。在windows程序設(shè)計里邊這種相應(yīng)使用callback機制來實現(xiàn)的
-
先看看jdk提供的event包:
-
public interface EventListener:所有事件偵聽器接口必須擴展的標(biāo)記接口。
-
public class EventObject extends Object implements Serializable
所有事件狀態(tài)對象都將從其派生的根類。 所有 Event 在構(gòu)造時都引用了對象 "source",在邏輯上認(rèn)為該對象是最初發(fā)生有關(guān) Event 的對象。
在Java2處理事件時,沒有采用dispatchEvent()-postEvent()-handleEvent()方式,采用了監(jiān)聽器類,每個事件類都有相關(guān)聯(lián)的監(jiān)聽器接口。事件從事件源到監(jiān)聽者的傳遞是通過對目標(biāo)監(jiān)聽者對象的Java方法調(diào)用進(jìn)行的。
對每個明確的事件的發(fā)生,都相應(yīng)地定義一個明確的Java方法。這些方法都集中定義在事件監(jiān)聽者(EventListener)接口中,這個接口要繼承 java.util.EventListener。 實現(xiàn)了事件監(jiān)聽者接口中一些或全部方法的類就是事件監(jiān)聽者。
伴隨著事件的發(fā)生,相應(yīng)的狀態(tài)通常都封裝在事件狀態(tài)對象中,該對象必須繼承自java.util.EventObject。事件狀態(tài)對象作為單參傳遞給應(yīng)響應(yīng)該事件的監(jiān)聽者方法中。發(fā)出某種特定事件的事件源的標(biāo)識是:遵從規(guī)定的設(shè)計格式為事件監(jiān)聽者定義注冊方法,并接受對指定事件監(jiān)聽者接口實例的引用。
開始之前首先問個問題:您熟悉java.util.EventObject 和java.util.EventListener兩個類以及他們已有的子類嗎?
如果你已經(jīng)能夠熟練使用jdk為我們提供的事件監(jiān)聽器,并且很熟悉MouseEvent, KeyEvent, WindowEvent等等這些jdk為我們準(zhǔn)備好的事件,那么想必你對java的事件機制已經(jīng)有所理解。但是也許你還是覺得雖然用起來沒什么問題,但是原理還是有些糊涂,那么下面我們再進(jìn)一步自己實現(xiàn)這些事件和監(jiān)聽器,我們把這個取名為自定義事件。
其實自定義事件在java中很有用處,我們有的時候想讓自己的程序產(chǎn)生一個事件,但有不希望(或者不可能)用鼠標(biāo),鍵盤之類的輸入設(shè)備進(jìn)行操作,比如你寫一個應(yīng)用程序,在這個程序中一旦收到郵件就對郵件進(jìn)行相關(guān)處理,對于“收到郵件”這個事件,jdk中就沒有定義。對于這樣的事件,以及對于這樣的事件的監(jiān)聽器,我們只能自己動手完成了。
那么下面就以實例開始我們這個“創(chuàng)新”的過程:首先,我們要明確jdk中需要的資源:類EventObject作為父類用來生成我們自己的事件類,接口EventListener用來實現(xiàn)我們自己的監(jiān)聽器;剩下的事情就是如何注冊這些事件以及測試他們了。
(1) 通過DemoEvent.java文件創(chuàng)建DemoEvent類,這個類繼承EventObject。這個類的構(gòu)造函數(shù)的參數(shù)傳遞了產(chǎn)生這個事件的事件源(比如各種控件),方法getSource用來獲得這個事件源的引用。
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) 定義新的事件監(jiān)聽接口,該接口繼承自EventListener;該接口包含對DemeEvent事件的處理程序:
DemoListener.java
package demo.listener;
import java.util.EventListener;
public interface DemoListener extends EventListener
{
public void demoEvent(DemoEvent dm);
}
|
通過上面的接口我們再定義事件監(jiān)聽類,這些類具體實現(xiàn)了監(jiān)聽功能和事件處理功能。回想一下上文中那四種實現(xiàn)方式,我們這里不正是使用了其中的第三種——外部類寫法的方式嗎?
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...");
}
}
|
(3) 通過DemeSource..ava文件創(chuàng)造一個事件源類,它用一個java.utile.Vector對象來存儲所有的事件監(jiān)聽器對象,存儲方式是通過addListener(..)這樣的方法。notifyDemeEvent(..)是觸發(fā)事件的方法,用來通知系統(tǒng):事件發(fā)生了,你調(diào)用相應(yīng)的處理函數(shù)(回調(diào)函數(shù))吧。
DemoSource.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));
}
}
}
|
(4) 好了,最后寫一個測試程序測試一下我們自定義的事件吧,這段程序應(yīng)該不難理解吧:)
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.addDemoListener(new DemoListener(){ public void demoEvent(DemoEvent event){ System.out.println("Method come from 匿名類..."); } });
ds.notifyDemoEvent();
}catch(Exception ex)
{ex.printStackTrace();}
}
public static void main(String args[])
{
new TestDemo();
}
}
|