通过程序添加或移除事件监听器

有两种方法通过程序添加或移除事件监听器。

声明一个成员

当用你自己的类重定义(overriding)一个组件后,你可以声明一个成员函数成为事件监听器。

在一个ZUML页面中,你可以使用use属性来指定你想使用的类,即用它去替换默认类。如下所示,它使用了MyWindow来替换默认的org.zkoss.zul.Window [31]

<window use="MyWindow">
...
</window>

然后你淂实现MyWindow.java同过继承默认的类,就像下面一样:

public class MyWindow extends org.zkoss.zul.Window {
   public void onOK() { //add an event listener
      ...//handles the onOK event (sent when ENTER is pressed)
   }
}

如果你想获得关于事件的更多信息,你可以按如下方式声明:

public void onOK(org.zkoss.zk.ui.event.KeyEvent event) {
...
}

public void onOK(org.zkoss.zk.ui.event.Event event) {
...
}

不同的事件或许与不同的事件对象相关联。参考附录C(Append C)来获取更多的细节。

动态地添加与移除事件监听器

开发人员可以使用org.zkoss.zk.ui.Component接口中的addEventListeneremoveEventListener方法来动态地添加或移除事件监听器。如下所示,动态添加的事件监听器必须实现org.zkoss.zk.ui.event.EventListener接口。

void init(Component comp) {
   ...
   comp.addEventListener("onClick", new MyListener());
   ...
}
class MyListener implements org.zkoss.zk.ui.event.EventListener {
   public void onEvent(Event event) throws UiException {
      ...//processing the event
   }
}

延期事件监听器

默认情况下,当客户端的事件被触发时就会被送到服务器。但是,许多事件仅用于维持服务器端的现状,而不是向客户端提供视觉响应(visual response)。换句话说,这些监听器的事件并不需要马上被送出。相反,它们应该仅被提交一次,以降低客户端和服务器端的来往,以提高服务器的性能。为求描述方便,我们称它们为延期事件监听器(Deferrable Event Listeners)。

为了使一个事件监听延期,必须实现org.zkoss.zk.ui.event.Deferrable接口(和 EventListener)并且使用isDeferrable方法返回true,就像下面一样。

public class DeferrableListener implements EventListener, Deferrable {
   private boolean _modified;
   public void onEvent(Event event) {
      _modified = true;
   }
   public boolean isDeferrable() {
      return true;
   }
}

当客户端的一个事件(例如,选择一个列表项目(list item))被触发时,如果没有为其注册事件监听器或仅有延期(deferrable)的监听器被注册,ZK不会将事件送出。

一方面,如果至少有一个非延期(non-deferrable)监听器,事件会被马上送到服务器端,和所有的队列事件(queued events)一起。没有事件会丢失,到达顺序是保存好的。

[提示]:当有非延期监听器为用户提供视觉响应,可以使用使用延期的(deferrable)事件监听器维持(maintaining)服务器状态。

为页面动态地添加和移除事件监听器

开发人员可以为页面(org.zkoss.zk.ui.Page)动态地添加和移除事件监听器。一旦被添加,所有被指定名字的事件会被送到指定页面的任何组件,这些页面将会被送到监听器。

所有的页面级(page-level)事件监听器都是非即时。换言之,isArap方法被忽略了。

一个典型的例子是使用页面级事件监听器来维护修改标志(modification flag),如下:

public class ModificationListener implements EventListener, Deferrable {
   private final Window _owner;
   private final Page _page;
   private boolean _modified;

   public ModificationListener(Window owner) {
      //Note: we have to remember the page because unregister might
      //be called after the owner is detached
      _owner = owner;
      _page = owner.getPage();
      _page.addEventListener("onChange", this);
      _page.addEventListener("onSelect", this);
      _page.addEventListener("onCheck", this);
   }
   /** Called to unregister the event listener.
    */
   public void unregister() {
      _page.removeEventListener("onChange", this);
      _page.removeEventListener("onSelect", this);
      _page.removeEventListener("onCheck", this);
   }
   /** Returns whether the modified flag is set.
    */
   public boolean isModified() {
      return _modified;
   }
   //-- EventListener --//
   public void onEvent(Event event) throws UiException {
      _modified = true;
   }
   //-- Deferrable --//
   public boolean isDeferrable() {
      return true;
   }
}

[注]: 在事例中是否实现Deferrable接口是可选的,因为页面的事件监听器总是假定为延期的,与是否实现Deferrable接口无关。

调用顺序

调用事件监听器的顺序如下。假定接收的是onClick事件。

  1. 如果监听器实现了org.zkoss.zk.ui.event.Express接口,依次为添加到目标组件(targeting component)的onClick事件调用事件监听器。按照添加的顺序调用。

  2. 调用目标组件的onClick属性指定的脚本语言。

  3. 如果监听器没有实现org.zkoss.zk.ui.event.Express接口,依次为添加到目标组件的onClick事件调用事件监听器。按照添加的顺序调用。

  4. 调用目标组件的onClick成员方法。

  5. 依次为添加到目标组件所属页面的的onClick事件调用事件监听器。按照添加的顺序调用。

org.zkoss.zk.ui.event.Express接口是一个装饰器(decorative interface),用来改变调用事件监听器的优先级。注意,如果事件监听器被添加到页面,而不是组件,这个接口是没有意义的。

中止调用序列

你可以通过调用org.zkoss.zk.ui.event.Event类中的stopPropagation方法来中止调用序列。一旦事件监听器调用了这个方法,之后所有的事件监听器将会被忽略。



[31] 默认的类定义在 in zul.jar中的lang.xml .