PropertyChangeSupport的使用

PropertyChangeSupport的使用,有这么几个类是相关的PropertyChangeEvent、PropertyChangeListener;

 

看一个小的例子:

 

public class A_listViewerExample {

	public static void main(String[] args) {
		Display display = Display.getDefault();
		Shell shell = new Shell(display);
		shell.setSize(400, 400);
		shell.setLayout(new FillLayout());

		ListViewer viewer = new ListViewer(shell, SWT.BORDER);
		viewer.setLabelProvider(new LabelProvider());
		viewer.setContentProvider(new ContentProvider());
		viewer.setInput(getData());
		((ListModel)viewer.getInput()).printInfo();
		shell.open();

		viewer.add(new UserModel("3","Ascos"));
		((ListModel)viewer.getInput()).add(new UserModel("4","Jack"));
		((ListModel)viewer.getInput()).printInfo();
//		viewer.refresh();
		
		while (!shell.isDisposed())
			if (!display.readAndDispatch())
				display.sleep();
	}

	private static Object getData() {
		ListModel input = new ListModel();
		input.add(new UserModel("1","Chris"));
		input.add(new UserModel("2","Leon"));
		return input;
	}
}

class LabelProvider implements ILabelProvider {
	public Image getImage(Object element) {
		return Display.getCurrent().getSystemImage(SWT.ICON_WORKING);
	}

	public String getText(Object element) {
		if(element instanceof UserModel)
			return ((UserModel)element).getName();
		return element.toString();
	}

	public boolean isLabelProperty(Object element, String property) {
		return false;
	}

	public void dispose() {}
	public void addListener(ILabelProviderListener listener) {}
	public void removeListener(ILabelProviderListener listener) {}
}

class ContentProvider implements IStructuredContentProvider, PropertyChangeListener {
	private ListViewer viewer;
	public Object[] getElements(Object inputElement) {
		if(inputElement instanceof ListModel)
			return ((ListModel)inputElement).elements();
		return null;
	}

	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		this.viewer = (ListViewer) viewer;
		if (oldInput instanceof ListModel)
			((ListModel) oldInput).removePropertyChangeListener(this);
		if (newInput instanceof ListModel)
			((ListModel) newInput).addPropertyChangeListener(this);
	}

	public void propertyChange(PropertyChangeEvent event) {
		if(event.getPropertyName().equals(ListModel.ADD_ELEMENT))
			viewer.add(event.getNewValue());
		if(event.getPropertyName().equals(ListModel.REMOVE_ELEMENT))
			viewer.remove(event.getNewValue());
	}
	
	public void dispose() {}
}

class ListModel {
	public static final String ADD_ELEMENT 		= "add Element";
	public static final String REMOVE_ELEMENT 	= "remove Element";

	private PropertyChangeSupport delegate;
	private Vector<Object> content;

	public ListModel() {
		content = new Vector<Object>();
		delegate = new PropertyChangeSupport(this);
	}

	public void addPropertyChangeListener(PropertyChangeListener listener) {
		delegate.addPropertyChangeListener(listener);
	}
	public void removePropertyChangeListener(PropertyChangeListener listener) {
		delegate.removePropertyChangeListener(listener);
	}

	public void firePropertyChange(PropertyChangeEvent event) {
		delegate.firePropertyChange(event);
	}

	public void add(Object element) {
		if (content.add(element))
			firePropertyChange(new PropertyChangeEvent(this, ADD_ELEMENT, null,	element));
	}

	public void remove(Object element) {
		if (content.remove(element))
			firePropertyChange(new PropertyChangeEvent(this, REMOVE_ELEMENT, null, element));
	}

	public Object[] elements() {
		return content.toArray();
	}

	public void printInfo() {
		for(Object o : content) {
			if(o instanceof UserModel) {
				UserModel user = (UserModel)o;
				System.out.println("The user id is "+user.getId() + ", and name is " + user.getName());
			}
		}
	}
}

class UserModel {
	private String id;
	private String name;

	public UserModel(String id, String name) {
		this.id = id;
		this.name = name;
	}

	public void setId(String id) {
		this.id = id;
	}
	public void setName(String name) {
		this.name = name;
	}

	public String getId() {
		return id;
	}
	public String getName() {
		return name;
	}

 


 

一个简单的Jface的ListViewer的例子,这是一个PropertyChangeSupport的典型的在GUI的中的应用,在GUI中有一个普遍的问题,就是数据和图形同步的问题,如上面的例子ListViewer,【viewer.add(new UserModel("3","Ascos"));】这个就是仅仅在图像中的增加了数据项,而在对应的数据原型上面listModel上面根本没有增加数据项,这个带来了一个问题,就是图形显示的和底层数据的不一致的问题,这样的话,要是GUI一但刷新的画,就会出现问题了,应该通常的数据刷新都是GUI根据底层数据来刷新,就发现刷新完的GUI数据项“Ascos”不见了。上面的例子,可以将【viewer.refresh();】这个注释的语句打开就可以测试一下。

 

为了保持数据和GUI的同步,只有Data.add同时View.add,还要Data.remove的同时View.remove;这个办法能够解决上面的数据和GUI显示同步的问题,但是对于后期的维护和功能的扩展是非常不方便的,如考虑GUI的常常出现的一种扩展的需求,如上面的List的例子,现在老板觉得是不是table的显示或者tree或者tabletree或者graphics的显示是不是更好一些呢,于是有了view1、view2、view3、在没有一个数据add的地方,加上对view的add,remove的地方也是。这样的修改,常常出现遗漏和错误。

 

应该PropertyChangeSupport,就可以解决上面的问题,数据看成是属性的提供方,所有的view都看着做是,这个属性的监听方,这样不管你加入多少的view,在创建view的时候,就注册到属性提供方中去,然后数据的变化就会。

 

其实,这个也很好的实现了GUI中的基本思想就MVC的思想,M就是基本的数据单元,V就是各种View,C就是逻辑业务单元的处理,这个负责M的创建也就是Data的创建,增加,删除等操作,V自动对应到Data模型,是多么完美的事情啊。

 

不过,这种属性监听的模式,和观察者的模式,非常的相似,观察者=监听者;被观察者=背监听者=管理者;
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 Java 中的注解来简化监听器的注册过程。具体来说,可以使用 `@java.beans.PropertyChangeListener` 注解来标记一个方法,使其成为数据更新时的监听器。当数据对象的属性发生变化时,注解标记的方法会自动被触发,执行相应的逻辑。 以下是一个示例代码,演示如何使用注解来实现数据更新时的监听器: ```java import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; public class DataModel { private String data; private PropertyChangeSupport support = new PropertyChangeSupport(this); public void setData(String newData) { String oldData = this.data; this.data = newData; support.firePropertyChange("data", oldData, newData); } public void addPropertyChangeListener(PropertyChangeListener listener) { support.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { support.removePropertyChangeListener(listener); } } public class DataListener { @PropertyChangeListener public void onDataChanged(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("data")) { String newData = (String) evt.getNewValue(); System.out.println("Data updated: " + newData); } } } public class Main { public static void main(String[] args) { DataModel dataModel = new DataModel(); DataListener listener = new DataListener(); dataModel.addPropertyChangeListener(listener); dataModel.setData("Hello, World!"); // Output: Data updated: Hello, World! } } ``` 在上面的代码中,我们创建了一个 `DataModel` 类表示需要监听的数据对象,它使用 `PropertyChangeSupport` 类来管理监听器。在 `setData` 方法中,我们使用 `support.firePropertyChange` 方法触发数据更新事件,同时指定更新前后的数据值。在 `DataListener` 类中,我们使用 `@PropertyChangeListener` 注解标记了一个名为 `onDataChanged` 的方法,用于响应数据更新事件。在 `Main` 类中,我们创建了一个 `DataModel` 对象和一个 `DataListener` 对象,并将监听器添加到数据对象上。当我们调用 `setData` 方法更新数据时,注解标记的方法会自动被触发,输出更新后的数据值。 需要注意的是,使用注解的方式来实现数据更新时的监听器需要满足以下条件: 1. 监听器方法必须使用 `public` 访问修饰符。 2. 监听器方法必须接收一个类型为 `PropertyChangeEvent` 的参数。 3. 监听器方法必须使用 `@java.beans.PropertyChangeListener` 注解标记。 4. 监听器方法的名称可以任意指定,但建议以 `on` 开头,以表明其是一个事件响应方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值