自定义事件和事件监听器。。。

原创 2006年05月26日 15:55:00

问题是这样来的:

       CSCW系统一致性算法的问题,必须实现所有客户端在服务器上对应的各个线程之间能进行通信,管道的方法是行不通,我的导师的指导说可以通过共享区的方法来实现各个线程的通信,比如把要传递给其他线程的消息放在某个共享区,然后其他的线程到这个共享区来读取。问题是,这个所有线程都会对这个共享区 进行读/写操作,而且当一个线程往这个共享区里写入一个对象时,又必须保证其他的所有的线程都已经读到了这个对象后,这个共享区的对象才能再次被改变,别的线程才能往里面写东西,这设计到生产者和消费者的问题,实现起来也是相当复杂,因为这个共享区的信息读取是非常频繁的。最后在我同学刘少林建议我通过自定义事件来实现,我通过网上找资料,查看JTextArea、DocumentEvent、AbstractDocument.DefaultDocumentEvent的源码,最后终于搞定了。。。实现如下:

     事件的组成
    如果想要自定义一个事件,则必须提供一个事件的监听接口以及一个事件类。在JAVA中监听接口继承java.util.EventListener,事件类继承java.util.EventObject.

  下面是我自定义的事件类:MyDocumentEvent.java

package server;

import java.util.EventObject;
import javax.swing.*;

public class MyDocumentEvent extends EventObject {
      private JTextArea jTextArea;//共享区
      private long id;//标识字段
      private int offset;//起始位置
      private int length;//长度,用来标识插入的String的长度或删除的String的长度
      private String type;//“insert”,"remove"
      public MyDocumentEvent(int offs, int len, long id, JTextArea jTextArea,String type) {
            super(jTextArea);
            this.jTextArea = jTextArea;
            this.offset=offs;
            this.length=len;
            this.id = id;
            this.type=type;
      }
      public Object getSource() {
            return jTextArea;
      }
      public void getMsg(){
            System.out.println("这个是由 "+id+" 执行的操作。。。");
      }
      public int getOffset() {//得到起始的位置
           return offset;
       }
       public int getLength() {//得到长度
           return length;
       }
      public long getId() {//得到标识
            return id;
      }
}

下面是自定义的监听接口

package server;

import java.util.EventListener;

public interface MyDocumentListener extends EventListener{
      public void insertUpdate(MyDocumentEvent event);//当JTextArea即共享区进行insert操作时就执行
      public void removeUpdate(MyDocumentEvent event);//当JTextArea即共享区进行remove操作时就执行

}

下面是共享区JTextAreaSource.java的代码,继承JTextArea

package server;

import javax.swing.*;
import java.util.*;

class JTextAreaSource extends JTextArea {
      public JTextAreaSource() {
            super();
      }

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

      //如果这里没有使用Vector而是使用ArrayList的话,要注意同步问题
      public void notifyDocumentInsertUpdate(MyDocumentEvent event) {
            Enumeration enum1 = repository.elements(); //这步要注意同步问题
            while (enum1.hasMoreElements()) {
                  dl = (MyDocumentListener) enum1.nextElement();
                  dl.insertUpdate(event);//当进行insert操作,就调用用户的insertUpdate()方法
            }
      }

      public void notifyDocumentRemoveUpdate(MyDocumentEvent event) {
            Enumeration enum1 = repository.elements(); //这步要注意同步问题
            while (enum1.hasMoreElements()) {
                  dl = (MyDocumentListener) enum1.nextElement();
                  dl.removeUpdate(event);当进行remove操作,就调用用户的removeUpdate()方法
            }
      }

      //删除监听器,如果这里没有使用Vector而是使用ArrayList那么要注意同步问题
      public void removeDemoListener(MyDocumentListener dl) {
            repository.remove(dl); //这步要注意同步问题
      }     
      public synchronized void  insert(int offs,String str,long id) {
            this.insert(str,offs);

           //id就是用户的标识
            notifyDocumentInsertUpdate(new MyDocumentEvent(offs,str.length(),id,this,"insert"));
      }
    
      public synchronized void  remove(int offs ,int end,long id) {
            this.replaceRange("",offs,end);
            notifyDocumentRemoveUpdate(new MyDocumentEvent(offs,end-offs,id,this,"remove"));
      }

      private Vector repository = new Vector();//用来存储所有的监听者
      private MyDocumentListener dl;     
      private long id;//用户标识
      private int offset;
      private int length;

}


下面是测试的代码Test.java

package server;

import java.lang.Thread;

public class Test   implements MyDocumentListener {
   private JTextAreaSource jt;

   public Test()
   {
      jt=new JTextAreaSource();
      jt.addMyDocumentListener(this);
      System.out.println("添加监听器完毕");
      try {
         Thread.sleep(3000);
        //在0位置插入"我是谁。。。。",并把自己的标识2202008传过去
         jt.insert(0,"我是谁。。。。",2202008);
    }
    catch (InterruptedException ex) {
       ex.printStackTrace();
    }

    //jt.addMyDocumentListener(this);
    System.out.println("添加监听器完毕2");
    try {
       Thread.sleep(3000);
       //删除0位置后的两个字符,并把自己的标识2202008传过去
       jt.remove(0,2,2202008);
    }
    catch (InterruptedException ex) {
       ex.printStackTrace();
    }

    //jt.addMyDocumentListener(this);
    System.out.println("添加监听器完毕3");
    try {
       Thread.sleep(3000);
       //在位置5插入"实现了自定义事件",并把自己的标识2202008传过去
       jt.insert(5,"实现了自定义事件",2202008);
    }
    catch (InterruptedException ex) {
       ex.printStackTrace();
    }

  }

   public static void main(String args[])
   {
     new Test();
   }
    //下面的方法,就是监听接口中的方法,有共享区调用
   public void insertUpdate(MyDocumentEvent event){
    event.getMsg();
    System.out.println("在位置"+event.getOffset()+"处插入长度为"+event.getLength()+"的字符");
    System.out.println("文本的内容为"+jt.getText());  
    System.out.println();
   }
     public void removeUpdate(MyDocumentEvent event){
       event.getMsg();
       System.out.println("在位置"+event.getOffset()+"删除长度为"+event.getLength()+"的字符");
       System.out.println("文本的内容为"+jt.getText());
       System.out.println();
     }
}


代码上都有详细的注释。。。。

相关文章推荐

cocos2dx 使用lua自定义事件

cocos2dx 在C++或lua中派发自定义事件,并lua中响应自定义事件,
  • cyloser
  • cyloser
  • 2016年11月20日 10:40
  • 1401

Cocos2d-x 3.9 Lua 自定义事件

Cocos2d-x 3.9 自定义事件

自定义事件监听器示例

监听器是一个实现特定接口的普通java程序,这个程序专门用于监听一个java对象的方法调用或属性的改变,当被监听对象发生上述事件后,监听器某个方法将被立即执行。 监听器机制: 1、设计三个要素 ...

java自定义事件与监听器

  • 2014年04月11日 10:08
  • 2KB
  • 下载

观察者模式高级应用--自定义Swing事件监听器

先抛出问题: 因为之前看到的实现很复杂,通过先将面板B中数据发送到服务器,服务器校验完成后然后存储,然后通过ActiveMQ将消息发布到所有的客户端,告诉他们有了新的数据。terrible! ...
  • Crabime
  • Crabime
  • 2017年01月21日 09:37
  • 1126

一个Java写的自定义的事件监听器例子

这几天我正在学Java编程,所以自己做了一个小程序,是关于事件监听器的。虽然没有那些程序员、工程师做的好,但经过一番努力和思考,总会有进步的。此程序如果有不足之处,还希望各位朋友们多多指点。下面是程序...

【JAVA语言程序设计基础篇】--事件驱动程序设计--定义监听器的另一种方式

package chapter16; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.e...

javascript之自定义事件

  • 2012年08月27日 09:48
  • 1KB
  • 下载

Android为自定义控件添加事件

1)文章简介 创建自定义控件并为它添加一个自定义事件 当用户单击自定义控件中的“测试”按钮时触发按钮自定义事件 2)定义一个layout(activity_custom.xml)作为自定义控件的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:自定义事件和事件监听器。。。
举报原因:
原因补充:

(最多只允许输入30个字)