如下是一个简单的测试对话框,我们希望当”起始日期”按钮为勾选时,数据对象dataBean的date属性为日期组件DateTime选择的值,否则为null.
先给出DateBean的类定义
// 具备PropertyChangeSupport支持的JavaBean
public class DateBean{
private PropertyChangeSupport support=new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
support.firePropertyChange(propertyName, oldValue, newValue);
}
Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
System.out.printf("date=%s\n", date);
firePropertyChange("date", this.date, this.date = date);
}
在这个场景中,是两个widget组件的状态绑定到一个数据对象的属性
实现上面的需求,参考我之前的博文《jface databinding:更简单的ISideEffect实现多目标单边数据绑定塈其原理分析》,可以很简单的实现。
DateTime dateTime=new DateTime(container, SWT.BORDER);
Button chkDateEnable=new Button(container, SWT.CHECK);
//。。。。。
DataBindingContext bindingContext = new DataBindingContext();
// 创建dateTime日期组件的观察对象
IObservableValue observeSelectionDateTimeObserveWidget = WidgetProperties.selection().observe(dateTime);
// 创建chkDateEnable按钮的观察对象
IObservableValue observeSelectionChkDateEnableObserveWidget = WidgetProperties.selection().observe(chkDateEnable);
// 创建ISideEffect实现dateTime+chkDateEnable->dateBean.date的单向数据绑定
ISideEffect.create(()->{
return (boolean)observeSelectionChkDateEnableObserveWidget.getValue()?(Date)observeSelectionDateTimeObserveWidget.getValue():null;
}, dateBean::setDate);
但是,上面的代码只是实现了单向的数据绑定,如果希望在上图中按”恢复缺省值”时,dateBean.date修改后,界面的chkDateEnable和dateTime组件也同步更新,就不能使用ISideEffect了。
我们知道ComputedValue也可以实现单向的多对一数组绑定,
关于ComputedValue,我在另一篇博文中有更详细的介绍《jface databinding:延迟计算–ComputedValue和WritableList使用的例子》
但ComputedValue并没有实现doSetValue方法,所以如果对ComputedValue对象执行setValue方法会抛出UnsupportedOperationException异常,所以ComputedValue是单向的绑定。但是如果我们实现了doSetValue方法,就可以实现双向的数据绑定。
DateTime dateTime=new DateTime(container, SWT.BORDER);
Button chkDateEnable=new Button(container, SWT.CHECK);
//。。。。。
DataBindingContext bindingContext = new DataBindingContext();
// 创建dateTime日期组件的观察对象
IObservableValue observeSelectionDateTimeObserveWidget = WidgetProperties.selection().observe(dateTime);
// 创建chkDateEnable按钮的观察对象
IObservableValue observeSelectionChkDateEnableObserveWidget = WidgetProperties.selection().observe(chkDateEnable);
// 创建ComputedValue对象
IObservableValue observableDate = new ComputedValue(){
// 重写doSetValue,
// 当value为null时,chkDateEnable不勾选,dateTime设置为disable
// value不为null时,chkDateEnable勾选,dateTime设置为enable,并将dateTime组件的日期设置为value的日期
@Override
protected void doSetValue(Date value) {
chkDateEnable.setSelection(null!=value);
dateTime.setEnabled(null!=value);
if(null!=value){
Calendar calendar = Calendar.getInstance();
calendar.setTime(value);
dateTime.setDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONDAY), calendar.get(Calendar.DAY_OF_MONTH));
}
}
@Override
protected Date calculate() {
// 根据chkDateEnable的selection状态,返回Date对象
// chkDateEnable.selection为true时,返回dateTime的值,设置dateTime为enable
// chkDateEnable.selection为false时,返回null,设置dateTime为disable
boolean selection = (boolean)observeSelectionChkDateEnableObserveWidget.getValue();
dateTime.setEnabled(selection);
return selection?(Date)observeSelectionDateTimeObserveWidget.getValue():null;
}
};
// 对observableDate对象与dateBean.date属性进行数据绑定
bindingContext.bindValue(observableDate, dateDateBeanObserveValue, null, null);
TestComputedValue2 .java
package testwb;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Calendar;
import java.util.Date;
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.widgets.DateTime;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.sideeffect.ISideEffect;
import org.eclipse.core.databinding.observable.value.ComputedValue;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.swt.DisplayRealm;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
public class TestComputedValue2 extends Dialog {
private DataBindingContext m_bindingContext;
public class DateBean{
private PropertyChangeSupport support=new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
support.firePropertyChange(propertyName, oldValue, newValue);
}
Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
System.out.printf("date=%s\n", date);
firePropertyChange("date", this.date, this.date = date);
}
}
private DateBean dateBean=new DateBean();
private DateTime dateTime;
private Button chkDateEnable;
/** * Create the dialog. * @param parentShell */
public TestComputedValue2(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);
dateTime = new DateTime(container, SWT.BORDER);
dateTime.setBounds(86, 95, 88, 24);
chkDateEnable = new Button(container, SWT.CHECK);
chkDateEnable.setBounds(10, 99, 70, 17);
chkDateEnable.setText("起始日期");
Button btnNewButton = new Button(container, SWT.NONE);
btnNewButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
dateBean.setDate(new Date());
}
});
btnNewButton.setBounds(10, 167, 80, 27);
btnNewButton.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(450, 300);
}
protected DataBindingContext initDataBindings() {
DataBindingContext bindingContext = new DataBindingContext();
//
IObservableValue observeSelectionDateTimeObserveWidget = WidgetProperties.selection().observe(dateTime);
IObservableValue observeSelectionChkDateEnableObserveWidget = WidgetProperties.selection().observe(chkDateEnable);
IObservableValue dateDateBeanObserveValue = BeanProperties.value("date").observe(dateBean);
//bindingContext.bindValue(observeSelectionDateTimeObserveWidget, dateDateBeanObserveValue, null, null);
/*IObservableValue observableDate = ComputedValue.create(()->{ return chkDateEnable.getSelection()?(Date)observeSelectionDateTimeObserveWidget.getValue():null; });*/
// 创建ComputedValue对象
IObservableValue observableDate = new ComputedValue(){
// 重写doSetValue,
// 当value为null时,chkDateEnable不勾选,dateTime设置为disable
// value不为null时,chkDateEnable勾选,dateTime设置为enable,并将dateTime组件的日期设置为value的日期
@Override
protected void doSetValue(Date value) {
chkDateEnable.setSelection(null!=value);
dateTime.setEnabled(null!=value);
if(null!=value){
Calendar calendar = Calendar.getInstance();
calendar.setTime(value);
dateTime.setDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONDAY), calendar.get(Calendar.DAY_OF_MONTH));
}
}
@Override
protected Date calculate() {
// 根据chkDateEnable的selection状态,返回Date对象
// chkDateEnable.selection为true时,返回dateTime的值,设置dateTime为enable
// chkDateEnable.selection为false时,返回null,设置dateTime为disable
boolean selection = (boolean)observeSelectionChkDateEnableObserveWidget.getValue();
dateTime.setEnabled(selection);
return selection?(Date)observeSelectionDateTimeObserveWidget.getValue():null;
}
};
// 对observableDate对象与dateBean.date属性进行数据绑定
bindingContext.bindValue(observableDate, dateDateBeanObserveValue, null, null);
/*ISideEffect.create(()->{ return (boolean)observeSelectionChkDateEnableObserveWidget.getValue()?(Date)observeSelectionDateTimeObserveWidget.getValue():null; }, dateBean::setDate);*/
//
return bindingContext;
}
public static void main(String[] args) {
Display display = Display.getDefault();
Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() {
public void run() {
try {
TestComputedValue2 setting = new TestComputedValue2(null);
setting.open();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}