前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jface databinding:重写doSetValue方法ComputedValue实现双向多对一的数据绑定

jface databinding:重写doSetValue方法ComputedValue实现双向多对一的数据绑定

作者头像
10km
发布2018-01-03 11:56:48
8470
发布2018-01-03 11:56:48
举报
文章被收录于专栏:10km的专栏10km的专栏

需求说明

如下是一个简单的测试对话框,我们希望当”起始日期”按钮为勾选时,数据对象dataBean的date属性为日期组件DateTime选择的值,否则为null.

先给出DateBean的类定义

代码语言:javascript
复制
    // 具备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);
        }

ISideEffect

在这个场景中,是两个widget组件的状态绑定到一个数据对象的属性

实现上面的需求,参考我之前的博文《jface databinding:更简单的ISideEffect实现多目标单边数据绑定塈其原理分析》,可以很简单的实现。

代码语言:javascript
复制
    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);

ComputedValue

但是,上面的代码只是实现了单向的数据绑定,如果希望在上图中按”恢复缺省值”时,dateBean.date修改后,界面的chkDateEnable和dateTime组件也同步更新,就不能使用ISideEffect了。

我们知道ComputedValue也可以实现单向的多对一数组绑定,

关于ComputedValue,我在另一篇博文中有更详细的介绍《jface databinding:延迟计算–ComputedValue和WritableList使用的例子》

但ComputedValue并没有实现doSetValue方法,所以如果对ComputedValue对象执行setValue方法会抛出UnsupportedOperationException异常,所以ComputedValue是单向的绑定。但是如果我们实现了doSetValue方法,就可以实现双向的数据绑定。

代码语言:javascript
复制
    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<Date> observableDate = new ComputedValue<Date>(){
        // 重写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

代码语言:javascript
复制
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<Date> observableDate = ComputedValue.create(()->{
            return chkDateEnable.getSelection()?(Date)observeSelectionDateTimeObserveWidget.getValue():null;
        });*/
        // 创建ComputedValue对象
        IObservableValue<Date> observableDate = new ComputedValue<Date>(){
            // 重写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();
                }
            }
        });
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年01月01日,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求说明
  • ISideEffect
  • ComputedValue
  • 完整示例代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档