1. 程式人生 > >jface databinding:使用CheckboxTableViewer實現表中(Set)物件與CheckTable中選中條目資料繫結

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