【问题标题】:How to handle empty selection in a JFace bound combobox?如何处理 JFace 绑定组合框中的空选择?
【发布时间】:2012-09-27 02:17:03
【问题描述】:

我正在我的 eclipse-rcp 应用程序中开发一个搜索对话框。

在搜索对话框中,我有一个组合框,如下所示:

comboImp = new CCombo(grpColSpet, SWT.BORDER | SWT.READ_ONLY);
comboImp.setBounds(556, 46, 184, 27);
comboImpViewer = new ComboViewer(comboImp);
comboImpViewer.setContentProvider(new ArrayContentProvider());
comboImpViewer.setInput(ImpContentProvider.getInstance().getImps());
comboImpViewer.setLabelProvider(new LabelProvider() {
    @Override
    public String getText(Object element) {
        return ((Imp)element).getImpName();
    }
});

Imp 是一个数据库实体,ManyToOne 是被搜索的主要实体,ImpContentProvider 是通过 jpa/hibernate 与嵌入式 sqlite 数据库对话的模型类。

这个组合框应该包含Imp的所有实例,但也让空选择;它的值绑定到一个服务 bean,如下所示:

IObservableValue comboImpSelectionObserveWidget = 
    ViewersObservables.observeSingleSelection(comboImpViewer);
IObservableValue filterByImpObserveValue = 
    BeansObservables.observeValue(searchPrep, "imp");
bindingContext.bindValue(comboImpSelectionObserveWidget, filterByImpObserveValue
    , null, null);

只要用户单击组合,就会进行选择(第一个元素):我可以看到对我在查看器上添加的选择侦听器的调用。我的问题是:

  • 做出选择后,如何让用户改变主意并在组合框中有一个空选择?我应该将 Imp 的“假”空实例添加到 ImpContentProvider 返回的列表中吗?还是我应该实现ArrayContentProvider 的替代方案?

另外一个相关问题是:

  • 为什么在组合上调用 deselectAll()clearSelection() 不会为绑定的 bean 设置空值?

【问题讨论】:

  • 有趣!!..看起来是个问题。对于您的问题,您可以在 Bean 中将“imp”值设置为 null 吗?它将清除组合查看器选择,因为它绑定到组合查看器选择
  • 如果我在 bean 中将“imp”设置为 null,则组合正确设置为空选择;但是我想要一种 gui 方式将其设置为空(除了我已经拥有的“清除表单”按钮)。
  • 正确。尝试在 Comboviewer 上设置空选择,它将触发带有 null 值的 selectionevent。
  • @sambi reddy 抱歉,我无法理解您的最后评论。让我澄清一下:我希望用户单击组合中的一个空项目,使选择为空,bean 属性为空。 (我已经可以通过编程方式完成,但我需要在 gui 中完成)

标签: java data-binding combobox eclipse-rcp jface


【解决方案1】:

ComboViewer.setSelection(StructuredSelection.EMPTY) 将触发选择事件并将“imp”设置为空。我认为只有在从下拉列表中手动选择时才会触发组合小部件选择事件。

使用转换器

定义空选择obj,比如说EMPTYEnum(在标签提供者中显示空字符串)

您可以为目标模型定义UpdateValueStrategy,并在绑定可观察对象时设置IConverter。 在转换器中,您可以将 EMPTYEnum 转换为 null。

IConverter:
fromType: Object.class
toType: Object.class

public Object convert(Object fromObject)
{
    if(fromObject instanceof EMPTYEnum)
    {
        return null;
    }
    return fromObject;
}

【讨论】:

  • +1 指出应该在查看器上而不是在包含的组合上设置选择。但是,我的问题是:在下拉列表中放置什么(沿着来自 db 的实体实例)让用户单击这个空选择并触发事件?
  • 感谢我们越来越近了!哪个组件应该有来自数据库的实体列表的枚举?我觉得在 ImpContentProvider 中添加它是不雅的。
  • 我建议扩展内容提供者并覆盖 getElements() 并在输入不为空时添加 EmptyEnum 作为第一个元素。我假设您正在单独的 Eclipse 作业或线程中获取数据库内容,以免阻塞 UI。
  • 是的;你会从哪里开始扩展?或者你的意思是在一个新类中实现 IStructuredContentProvider ?因为 ArrayContentProvider 有“这个类不打算被客户端子类化”的限制
  • 是的。使用 IStructuredContentProvider。在 getElements() 方法中,如果您的输入不为空,则添加 EmptyEnum 作为第一个元素。
【解决方案2】:

制作LabelProvider并处理空值

public String getText(Object element) {
    if (element == null) { 
        return "Choose one"; 
    }
    return super.getText(element);
}

在索引 0 处插入空值并处理空选择

    combo.setInput(yourItems);
    combo.insert(null, 0);
    combo.getCCombo().select(0);
    combo.addPostSelectionChangedListener(new ISelectionChangedListener() {
        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            if (combo.getCCombo().getSelectionIndex() == -1) {
                combo.getCCombo().select(0);
            }
        }
    });

绑定 ComboViewer ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-15
    • 2017-12-03
    相关资源
    最近更新 更多