jface databinding:使用CheckboxTableViewer实现表中(Set)对象与CheckTable中选中条目数据绑定

上一篇博文《jface databinding:可多选的widget List组件selection项目与java.util.List对象的双向数据绑定》讲述了如何实现List组件的多选项与List数据绑定的问题。 实际使用中觉得用List组件来给用户做多选,用户体验不太好,比如用户可能不知道按下shift或ctrl键才能多选。经过比对,还是觉得用checkTable来实现比较好, 如下图,左上是一个Table组件(CHECK),勾选不同的名字,希望数据对象(ObservableSet)的内容也同步改变,显示在下面的Label组件中。按右侧的”添加”,”删除”,”清除”按钮改变ObservableSet的内容时,Table也同步改变。

要实现这个需求,用jface提供的JFace Viewers实现数据绑定非常方便,JFace Viewers为Table,Tree等复杂组件提供了一个方便的开发框架,如下图对于每一种复杂组件都有对应的Viewer类,实现本文需求所需要的京是红框标的CheckboxTableViewer。

以下是实现的核心代码:

        WritableSet<String> observableSet=new WritableSet<String>();
        // 创建checkboxTableViewer对象
        checkboxTableViewer = CheckboxTableViewer.newCheckList(container, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI);
        Table table = checkboxTableViewer.getTable();
        // 设置初始的表内容
        WritableSet<String> input=new WritableSet<String>();
        input.addAll(Arrays.asList("tom","jerry","donald","snow white"));
        // 设置ContentProvider,ContentProvider会将input内容显示在Table中
        // 如果不执行此步,则下一步会抛出异常
        checkboxTableViewer.setContentProvider(new ObservableSetContentProvider());
        // 将input设置为checkboxTableViewer的输入,input的变化会同步到Table中
        checkboxTableViewer.setInput(input);
        // 创建数据绑定上下文
        DataBindingContext bindingContext = new DataBindingContext();
        // 调用ViewerProperties.checkedElements方法对checkboxTableViewer创建已选中项目观察对象
        IViewerObservableSet observeCheckedSetCheckboxTableViewer = ViewerProperties.checkedElements(String.class).observe(checkboxTableViewer);
        // 将CheckTable与数据对象observableSet绑定
        bindingContext.bindSet(observeCheckedSetCheckboxTableViewer, observableSet, null, null);
        // 将observableSet内容绑定到Label组件,当observableSet内容变化时,lblSelected显示会自动更新
        ISideEffect.create(
                observableSet::size, (s)->{
                    lblSelected.setText(String.join(",", observableSet));
            });

完整的测试代码: TestTableSelected .java

package testwb;

import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.set.WritableSet;
import org.eclipse.core.databinding.observable.sideeffect.ISideEffect;
import org.eclipse.jface.databinding.swt.DisplayRealm;
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.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.SWT;
import org.eclipse.jface.viewers.CheckboxTableViewer;

import java.util.Arrays;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.jface.databinding.viewers.IViewerObservableSet;
import org.eclipse.jface.databinding.viewers.ObservableSetContentProvider;
import org.eclipse.jface.databinding.viewers.ViewerProperties;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

public class TestTableSelected extends Dialog {
    private DataBindingContext m_bindingContext;
    private WritableSet<String> observableSet=new WritableSet<String>();
    private CheckboxTableViewer checkboxTableViewer;
    private Label lblSelected;
    /**
     * Create the dialog.
     * @param parentShell
     */
    public TestTableSelected(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);
        observableSet.add("tom");

        checkboxTableViewer = CheckboxTableViewer.newCheckList(container, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI);
        Table table = checkboxTableViewer.getTable();
        WritableSet<String> input=new WritableSet<String>();
        input.addAll(Arrays.asList("tom","jerry","donald","snow white"));
        checkboxTableViewer.setContentProvider(new ObservableSetContentProvider());
        checkboxTableViewer.setInput(input);
        table.setBounds(29, 42, 183, 85);
        table.pack();

        Button btnAdd = new Button(container, SWT.NONE);
        btnAdd.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                observableSet.add("jerry");
            }
        });
        btnAdd.setBounds(267, 42, 80, 27);
        btnAdd.setText("添加");

        Button btnDelete = new Button(container, SWT.NONE);
        btnDelete.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                observableSet.remove("tom");
            }
        });
        btnDelete.setBounds(267, 84, 80, 27);
        btnDelete.setText("删除");

        Button btnClear = new Button(container, SWT.NONE);
        btnClear.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                observableSet.clear();
            }
        });
        btnClear.setBounds(267, 126, 80, 27);
        btnClear.setText("清除");
        lblSelected = new Label(container, SWT.NONE);
        lblSelected.setBounds(29, 182, 449, 36);

        Label lblNewLabel_1 = new Label(container, SWT.NONE);
        lblNewLabel_1.setBounds(29, 163, 61, 17);
        lblNewLabel_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(494, 333);
    }
    public static void main(String[] args) {
        Display display = Display.getDefault();
        Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() {
            public void run() {
                try {
                    TestTableSelected testTable = new TestTableSelected(null);
                    testTable.open();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    protected DataBindingContext initDataBindings() {
        DataBindingContext bindingContext = new DataBindingContext();
        //
        IViewerObservableSet observeCheckedSetCheckboxTableViewer = ViewerProperties.checkedElements(String.class).observe(checkboxTableViewer);
        bindingContext.bindSet(observeCheckedSetCheckboxTableViewer, observableSet, null, null);
        //
        ISideEffect.create(
                observableSet::size, (s)->{
                    lblSelected.setText(String.join(",", observableSet));
            });
        return bindingContext;
    }
}

参考资料: 《Data Binding for JFace Viewers》

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术博客

Entity Framework CodeFirst尝试

Code First模式我们称之为“代码优先”模式,是从EF4.1开始新建加入的功能。使用Code First模式进行EF开发时开发人员只需要编写对应的数据类(...

773
来自专栏技术之路

常用的user32API说明

整理了一下常用的user32API说明  还有软件Microsoft Spy++供大家下载  Spyv10.00.30319.rar using System;...

6027
来自专栏Java编程技术

Spring&Mybaits数据库配置解惑

一般我们会在datasource.xml中进行如下配置,但是其中每个配置项原理和用途是什么,并不是那么清楚,如果不清楚的话,在使用时候就很有可能会遇到坑,所以下...

962
来自专栏xingoo, 一个梦想做发明家的程序员

【插件开发】—— 5 SWT控件以及布局使用

前文回顾: 1 插件学习篇 2 简单的建立插件工程以及模型文件分析 3 利用扩展点,开发透视图 4 SWT编程须知   经过前几篇的介绍,多少对S...

1779
来自专栏林德熙的博客

wpf DoEvents 用法原理存在的坑推荐方法

如果在执行一段卡UI的代码,这时如何让UI响应。如果存在代码需要获得依赖属性,那么代码就需要在UI线程执行,但是这时就会卡UI,为了让UI响应,所以就需要使用D...

841
来自专栏Android机动车

Android 5.0以上系统常用控件着色指南

当我们新建一个项目的时候,都会给Application或者某些Activity设置theme:

692
来自专栏我的博客

安卓开发之SQLite数据库操作

一、SQLiteDatabase对象 获取SQLiteDatabase对象可以使用SQLiteOpenHelper或者使用静态方法获取(具体内容可以参考开发手册...

33512
来自专栏GopherCoder

『Golang 内置模块库 template 』

3774
来自专栏移动端开发

Android学习--还有一些小技巧

      通过上面的这些文章,就把简单的安卓项目总结了一遍,当然你说懂这些就可以做Android开发的话还是不行的,欠缺的还有很多,但欠缺的这些我们有只能在工...

863
来自专栏林德熙的博客

win10 uwp listView 绑定前一项 WPF 绑定前一项UWP 绑定前一项

大神问,如何在 ListView 绑定前一项,于是我下面告诉大家如何在 ListView 绑定前一项

461

扫码关注云+社区