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

需求说明

如下是一个简单的测试对话框,我们希望当”起始日期”按钮为勾选时,数据对象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);
        }

ISideEffect

在这个场景中,是两个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);

ComputedValue

但是,上面的代码只是实现了单向的数据绑定,如果希望在上图中按”恢复缺省值”时,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<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

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();
                }
            }
        });
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏青蛙要fly的专栏

项目需求讨论: 文字显示排版— Html格式

我们看到,我用红框框出来的地方 1.直接使用系统自带的AlertDialog的提示框,我们看到了我们更新提示里面的具体内容是(-Bug修改 -新增更新提示);...

23520
来自专栏DT乱“码”

基于springMVC拦截器实现操作日志统计

1.spring配置文件配置。  <!-- 拦截器 --> <mvc:interceptors> <!-- 日志拦截器 --> <bean cl...

26370
来自专栏24k

web3j调用合约的两种方式以及eth转账

17620
来自专栏跟着阿笨一起玩NET

LINQ 从 CSV 文件生成 XML

本文参考:http://msdn.microsoft.com/zh-cn/library/bb387090.aspx

9010
来自专栏androidBlog

装饰者模式及其应用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

34320
来自专栏码匠的流水账

kafka stream errorlog报警实例

log4j-core-2.7-sources.jar!/org/apache/logging/log4j/core/appender/mom/kafka/Kaf...

14410
来自专栏DT乱“码”

接口测试类(http,post请求)参数 json格式

package RMI; import java.io.BufferedReader; import java.io.DataOutputStream; im...

24890
来自专栏码匠的流水账

聊聊spring cloud gateway的PreserveHostHeaderGatewayFilter

本文主要研究下spring cloud gateway的PreserveHostHeaderGatewayFilter

14620
来自专栏码匠的流水账

聊聊pg jdbc的queryTimeout及next方法

本文主要介绍一下pg jdbc statement的queryTimeout及resultSet的next方法

38810
来自专栏跟着阿笨一起玩NET

C# EPL USB 指令打印

15610

扫码关注云+社区

领取腾讯云代金券