前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【插件开发】—— 11 窃听风云(Java事件监听原理-GEF实例讲解)

【插件开发】—— 11 窃听风云(Java事件监听原理-GEF实例讲解)

作者头像
用户1154259
发布2018-01-17 16:30:45
7470
发布2018-01-17 16:30:45
举报

前文回顾: 1 插件学习篇 2 简单的建立插件工程以及模型文件分析 3 利用扩展点,开发透视图 4 SWT编程须知 5 SWT简单控件的使用与布局搭配 6 SWT复杂空间与布局搭配 7 SWT布局详解 8 IPreferenceStore使用详解 9 编辑器代码着色 10 JFace开发

  事件的监听,是插件开发中的重要环节,每一次的点击或者按键都有可能触发某种事件的响应,那么是如何实现的呢?

  对于某种被监听模型,通常需要添加一个监听队列

  监听者需要通过某种方式,加入到这个监听队列中

  当这个模型在特定的情况下触发监听事件后,会产生一个事件的响应,这个响应使得监听队列中的每个监听者都触发响应的操作

  例如下面这个小例子:

代码语言:javascript
复制
class FocusedCountry{
    List<IListener> listener = new ArrayList();
    public void addListener(IListener lis){
        listener.add(lis);
    }
    //移除监听者
    public void removeListener(IListener lis){
        listener.remove(lis);
    }
    //触发监听事件
    protected void fireChange(String message){
        for(IListener lis : listener){
            lis.noticedChange(message);
        }
    }
}

  这个被监听的对象,有一个监听队列,所有对它感兴趣的人都会加入到这个监听队列中。因此主要有三个函数,加入到队列中,从队列离开,以及本身的一个触发函数。

代码语言:javascript
复制
interface IListener{
    public void noticedChange(String message);
}

class DevelopedCountry implements IListener{
    public void noticedChange(String message) {
        System.out.println("noticed the change:"+message);
    }
}

  上面实现了一个监听的接口,只要实现了这个接口的类,都可以添加到队列中。

代码语言:javascript
复制
public class ListenTest {
    public static void main(String[] args) {
        DevelopedCountry America = new DevelopedCountry();
        FocusedCountry China = new FocusedCountry();
        FocusedCountry NorthKorea = new FocusedCountry();
        China.addListener(America);
        NorthKorea.addListener(America);
        China.fireChange("登月!");
        NorthKorea.fireChange("原子弹造好了,该去哪扔呢!");
    }
}

  调用结果如下,所有的事件都被监听者接收到了。

代码语言:javascript
复制
noticed the change:登月!
noticed the change:原子弹造好了,该去哪扔呢!

  那么GEF中是如何使用的呢?

  GEF是一种MVC标准的架构,它的模型负责实现这个监听队列,而Control负责接收监听,进行响应,从而改变View的模型

  因此,一般的Model都会继承一个自定义的虚类,这个虚类中包含了一个监听队列,以及上面提到的三种函数。

代码语言:javascript
复制
public class AbstractModel implements Serializable{
 
 private PropertyChangeSupport listeners = new PropertyChangeSupport(this);

 public void addPropertyChangeListener(PropertyChangeListener listener) {
  listeners.addPropertyChangeListener(listener);
 }

 public void firePropertyChange(String propName, Object oldValue,Object newValue) {
  listeners.firePropertyChange(propName, oldValue, newValue);
 }

 public void removePropertyChangeListener(PropertyChangeListener listener) {
  listeners.removePropertyChangeListener(listener);
 }
}

  继承这个类后,需要某些事件进行触发监听,一般情况下,模型都会对应一些属性视图,属性视图需要继承IPropertySource接口。并重写下面的方法。

代码语言:javascript
复制
 public IPropertyDescriptor[] getPropertyDescriptors() {
  return new IPropertyDescriptor[] {
    new PropertyDescriptor(P_TABLE_NAME, "table_name"),
 }

 public Object getPropertyValue(Object id) {
  if (id == P_TABLE_NAME) {
   return getPhysicalName();
  }
  return null;
 }


 public boolean isPropertySet(Object id) {
  if (id == P_TABLE_NAME) {
   return true;
  }
  return false;
 }


 public void setPropertyValue(Object id, Object value) {
  if (id == P_TABLE_NAME) {
   seName((String) value);
  }
 }

  属性视图上的属性发生改变时,一般是在Set值的时候会触发这个firechange,最后触发到listners里面的firePropertyChange函数。

代码语言:javascript
复制
 public void setXXXlName(String xxxName) {
      this.xxxName = xxxName;
      firePropertyChange(P_XXX_NAME, null, xxxName);
 }

  这里是一个插件开发遗留的习惯,就是会把每一个事件使用一个static的字符串进行标记。函数会产生一个PropertyChange的事件。

  这样模型部分的监听就搞定了,下面要进行的是监听者的添加了。

  这里监听者需要实现PropertyChangeListener接口,并在适合的时机添加到监听队列中,由于这部分的代码在Editpart中,GEF的每一个Editpart都对应了一个Model,因此通过简单的getModel方法就可以获取它对应的模型对象,再调用模型对象的addListener等方法添加到监听队列中就OK了。

代码语言:javascript
复制
public void activate() {
  if (isActive()) {
   return;
  }
  super.activate();
  ((TableModel) getModel()).addPropertyChangeListener(this);
 }

 public void deactive() {
  if (!isActive()) {
   return;
  }
  super.deactivate();
  ((TableModel) getModel()).removePropertyChangeListener(this);
 }

  一般来说都是在这两个函数内,因为这两个函数相当于处于 一般函数的 构造函数 和 析构函数的 执行位置。

  添加完监听队列,需要实现一下PropertyChangeListener里面的PropertyChange方法,这个方法传递一个参数,通过这个参数可以获取上面最开始设定的字符串,从而判断是模型的哪个时间发生了响应。

代码语言:javascript
复制
 public void propertyChange(PropertyChangeEvent evt) {
  if (evt.getPropertyName().equals(TableModel.P_TABLE_NAME))
   refreshVisuals();
   ... 
 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014-11-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  •   例如下面这个小例子:
  •   那么GEF中是如何使用的呢?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档