上一篇博文《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;
}
}