jface databinding:部分实现POJO对象的监测
来源:互联网 发布:缅甸听音乐的软件 编辑:程序博客网 时间:2024/05/01 10:44
在前一篇博文《jface databinding/PojoBindable实现对POJO对象的支持
》中,已经知道直接对POJO对象进行修改,是不能被绑定的UI组件知道的,在上一篇文章中虽然说到PojoBindable这个项目可以解决这个问题,但这个项目并不成熟,所以我没有采用这个方案,而且如果要改造所有的POJO类支持PropertyChangeSupport又实在太麻烦了。
仔细想想我的需求,退而求其次,不一定要直接修改POJO对象,就能实现数据同步可以不?
冷静回头再看相关的资料并做了一些试验,发现原来IObservableValue对象本身就有setValue方法用于修改被监控的对象的值,而且会通知到观察对象。
DataBindingContext bindingContext = new DataBindingContext(); // Text对象的text属性的IObservableValue 对象 IObservableValue observeTextMyNametextObserveWidget = WidgetProperties.text(SWT.Modify).observe(myNametext); // Person对象name属性的IObservableValue 对象(Person是个实现了属性get/set方法的POJO类) namePersonObserveValue = PojoProperties.value("name").observe(person); // 数据绑定 bindingContext.bindValue(observeTextMyNametextObserveWidget, namePersonObserveValue, null, null); // 调用IObservableValue.setValue方法修改数据对象的值,Text的内容会同步更新 namePersonObserveValue.setValue("word"); // 直接调用Person.setName方法来修改数据对象,Text不同步更新。 person.setName("word")
这不就行了?将POJO对象封装起来提供IObservableValue,所有的Set方法IObservableValue.setValue方法来实现,后续修改POJO对象改为调用这个封装对象的Set方法,不就可以实现POJO对象的数据的监控了吗?
关键是在我这个项目里这样做的成本并不高,只是后续要改变一下对POJO对象的访问方式而已。于是根据这个思路,我写了一个稍通用化的POJO封装类来实现这个想法儿:
分两个类
ObservablePojoType 对POJO类进行可监控封装,为类的每个属性创建对应的IBeanValueProperty
ObservablePojoObject 对POJO对象进行可监控封装,为对象的每个属性创建对应的IObservableValue, 提供 setValue,getValue方法实现对POJO对象进行访问
ObservablePojoType.java
package testwb;import java.beans.PropertyDescriptor;import java.util.HashMap;import java.util.Map;import java.util.Set;import org.eclipse.core.databinding.beans.IBeanValueProperty;import org.eclipse.core.databinding.beans.PojoProperties;import org.eclipse.core.databinding.observable.value.IObservableValue;import net.gdface.utils.Assert;import net.gdface.utils.BeanPropertyUtils;/** * 对POJO类进行可监控封装,为POJO类的每个属性创建对应的{@link IBeanValueProperty} * @see {@link PojoProperties#value(String)} * @see {@link IBeanValueProperty#observe(Object)} * @author guyadong * * @param <T> 封装的POJO类 */public class ObservablePojoType<T> { private final Class<T> pojoType; private Map<String,IBeanValueProperty> ivalueProperties=new HashMap<String, IBeanValueProperty>(); private final Map<String, PropertyDescriptor> propertyDescriptors; public ObservablePojoType(Class<T> pojoType) { if(null==pojoType) throw new NullPointerException(); this.pojoType=pojoType; // 返回所有可读写的属性 propertyDescriptors=BeanPropertyUtils.getProperties(pojoType, 3); } public ObservablePojoType(T pojo) { this((Class<T>) pojo.getClass()); } /** * 返回POJO类的所有属性名 * @return */ public Set<String> getPropertyNames() { return propertyDescriptors.keySet(); } /** * 返回source对象的指定属性(propertyName)的{@link IObservableValue}对象 * @param source 监控目标对象 * @param propertyName 属性名 * @return */ public IObservableValue<T> observe(T source,String propertyName) { if(null==source) throw new NullPointerException(); if(null==propertyName||propertyName.empty()) throw new IllegalArgumentException(); if(!propertyDescriptors.containsKey(propertyName)) throw new IllegalArgumentException(String.format("invalid propertyName:%s",propertyName)); if(!ivalueProperties.containsKey(propertyName)){ ivalueProperties.put(propertyName, PojoProperties.value(propertyName)); } return ivalueProperties.get(propertyName).observe(source); } /** * 返回指定对象的监控对象{@link ObservablePojoObject} * @param source * @return */ public ObservablePojoObject<T> observe(T source){ return new ObservablePojoObject<T>(source,this); } public PropertyDescriptor[] getPropertyDescriptors() { return propertyDescriptors.values().toArray(new PropertyDescriptor[0]); }}
ObservablePojoObject.java
package testwb;import java.beans.PropertyDescriptor;import java.util.HashMap;import java.util.Map;import org.eclipse.core.databinding.observable.value.IObservableValue;import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper;/** * 对POJO对象进行可监控封装,为对象的每个属性创建对应的{@link IObservableValue}<br> * {@link #setValue(String, Object)}和 {@link #getValue(String)}实现对POJO对象进行访问<br> * 当调用 {@link #setValue(String, Object)}改变对象的属性值时,会自动通知监控对象<br> * * 这里将普通的Java bean(有get/set方法但没有通过PropertyChangeSupport实现属性监控)定义为POJO对象 * @author guyadong * * @param <T> 封装的POJO类 */public class ObservablePojoObject<T> { private final T pojo; private final ObservablePojoType<T> pojoType; /** * 每个属性对应的{@link IObservableValue} */ private final Map<String,IObservableValue> observableValues=new HashMap<String, IObservableValue>(); public ObservablePojoObject(T pojo,ObservablePojoType<T> pojoType) { if(null==pojo) throw new NullPointerException(); this.pojo = pojo; this.pojoType = null==pojoType?new ObservablePojoType<T>((Class<T>) pojo.getClass()):pojoType; } public ObservablePojoObject(T pojo) { this(pojo,null); } /** * 返回指定属性对应的{@link IObservableValue}对象 * @param propertyName * @return */ public IObservableValue getObservableProperty(String propertyName){ if(!pojoType.getPropertyNames().contains(propertyName)) throw new IllegalArgumentException(String.format("invalid propertyName:%s",propertyName)); if(!observableValues.containsKey(propertyName)){ observableValues.put(propertyName, pojoType.observe(pojo, propertyName)); } return observableValues.get(propertyName); } /** * 设置指定属性的值 * @param propertyName * @param value */ public void setValue(String propertyName,Object value){ getObservableProperty(propertyName).setValue(value); } /** * 获取指定属性的值 * @param propertyName * @return */ public Object getValue(String propertyName){ return getObservableProperty(propertyName).getValue(); } public T getPojo() { return pojo; } /** * 用from对象更新当前监控对象的所有属性 * @param from * @return * @see #setValue(String, Object) * @see {@link BeanPropertyHelper#readProperty(Object, PropertyDescriptor)} */ public ObservablePojoObject<T> updateFrom(T from){ if(null==from) throw new NullPointerException(); for(PropertyDescriptor propertyDescriptor:pojoType.getPropertyDescriptors()){ setValue(propertyDescriptor.getName(), BeanPropertyHelper.readProperty(from, propertyDescriptor)); } return this; }}
测试代码:
TestPojoBinding4.java
package testwb;import org.eclipse.jface.dialogs.Dialog;import org.eclipse.jface.dialogs.IDialogConstants;import org.eclipse.swt.graphics.Point;import org.eclipse.swt.widgets.Composite;import org.eclipse.swt.widgets.Control;import org.eclipse.swt.widgets.Shell;import org.eclipse.swt.SWT;import org.eclipse.swt.widgets.Text;import org.eclipse.core.databinding.DataBindingContext;import org.eclipse.core.databinding.observable.value.IObservableValue;import org.eclipse.jface.databinding.swt.WidgetProperties;import org.eclipse.swt.widgets.Display;import org.eclipse.core.databinding.observable.Realm;import org.eclipse.jface.databinding.swt.DisplayRealm;import org.eclipse.swt.widgets.Button;import org.eclipse.swt.events.SelectionAdapter;import org.eclipse.swt.events.SelectionEvent;public class TestPojoBinding4 extends Dialog { /** * 数据对象定义 * @author guyadong * */ public class Person { private String name; public Person(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; System.out.printf("updated %s\n",this.name); } } private DataBindingContext m_bindingContext; /** * 成员变量:数据对象 */ protected Person personBak=new Person("hello!"); protected Person person=new Person("hello!"); private Text myNametext; /** * 将person封装成可监控的ObservablePojoObject对象 */ private final ObservablePojoObject<Person> observablePersion=new ObservablePojoObject<Person>(person);; /** * Create the dialog. * @param parentShell */ public TestPojoBinding4(Shell parentShell) { super(parentShell); } /** * Create contents of the dialog. * @param parent */ @Override protected Control createDialogArea(Composite parent) { Composite container = (Composite) super.createDialogArea(parent); container.setLayout(null); Button btnNewButton = new Button(container, SWT.NONE); btnNewButton.addSelectionListener(new SelectionAdapter() { @SuppressWarnings("unchecked") @Override public void widgetSelected(SelectionEvent e) { // 调用 ObservablePojoObject.setValue方法修改 person的name属性 observablePersion.setValue("name", "word"); } }); btnNewButton.setBounds(38, 154, 80, 27); btnNewButton.setText("测试"); myNametext = new Text(container, SWT.BORDER); myNametext.setBounds(38, 27, 80, 23); Button btnNewButton_1 = new Button(container, SWT.NONE); btnNewButton_1.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { // 修改 person的name属性 observablePersion.updateFrom(personBak); } }); btnNewButton_1.setBounds(132, 154, 80, 27); btnNewButton_1.setText("恢复"); return container; } /** * Create contents of the button bar. * @param parent */ @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); m_bindingContext = initDataBindings(); } /** * Return the initial size of the dialog. */ @Override protected Point getInitialSize() { return new Point(362, 298); } public static void main(String[] args) { Display display = Display.getDefault(); Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() { public void run() { try { TestPojoBinding4 setting = new TestPojoBinding4(null); setting.open(); } catch (Exception e) { e.printStackTrace(); } } }); } protected DataBindingContext initDataBindings() { DataBindingContext bindingContext = new DataBindingContext(); IObservableValue observeTextMyNametextObserveWidget = WidgetProperties.text(SWT.Modify).observe(myNametext); // 数据绑定 bindingContext.bindValue(observeTextMyNametextObserveWidget, observablePersion.getObservableProperty("name"), null, null); return bindingContext; }}
- jface databinding:部分实现POJO对象的监测
- jface databinding/PojoBindable实现对POJO对象的支持
- jface databinding:List,Set,Map对象的Observable代理封装
- jface databinding:使用CheckboxTableViewer实现表中(Set)对象与CheckTable中选中条目数据绑定
- jface databinding: Radio Button group及ISideEffect绑定数据对象的例子
- jface databinding:更简单的ISideEffect实现多目标单边数据绑定塈其原理分析
- jface databinding:重写doSetValue方法ComputedValue实现双向多对一的数据绑定
- jface databinding:label provider 实现多列表格(Table)数据绑定的两个途径
- jface databinding: 创建readonly(只读)可观察对象(observable)
- jface databinding:可多选的widget List组件selection项目与java.util.List对象的双向数据绑定
- jface databinding:延迟计算--ComputedValue和WritableList使用的例子
- Swt/Jface listviewer的实现
- Swt/Jface listviewer的实现
- jface的dialog实现非模态
- Swt/Jface listviewer的实现
- SSH:如何让Hibernate的HQL只返回部分属性的对象(POJO)集合?
- jface databinding:构建一个改进版的通用型数值验证器StringToNumberValidator
- 10.POJO对象的状态
- Define nested schema in Mongoose
- Linux/UNIX 定时任务 cron 详解
- MySQL分组获取前条记录
- tableViewCell的线左对齐
- fragment与activity及两个fragment之间的跳转实现
- jface databinding:部分实现POJO对象的监测
- PE文件结构详解--基本概念
- 近百个免费API接口分享 调用完全不限次数
- class org.bouncycastle.asn1.ASN1Primitive overrides final method equals.(Ljava/lang/Object;)Z
- 分布式系统唯一ID生成方案汇总
- 《设计模式之禅》读书笔记
- ThreadPoolExecutor参数说明
- 判断网络状态工具类
- MongoDB connection timeout