如何在 JavaFx 中将"empty"选择保留在我的组合框列表中?



在我的应用程序中,我有一个组合框,它从数据库中持有一些值(一些实时更新的列表)。这个组合框列表每1分钟更新一次。列表没有空值。当我将这个列表设置为ComboBox.

ComboBox box = new ComboBox(items);

. .有一个额外的"空"行,这是完全没有问题的,因为非值被选中。就在我选择一些值之后,我的"空"值从列表中消失了。我的主要问题是如何保持这个值在列表上?

为什么这是个问题…

  1. 场景值在数据库中被选中,第一个应用程序启动
    1. 列表被加载(选择空值)。
  2. 第一次背景刷新时,空值消失,组合框值被选择为n+1,选择下一个值。
  • 如果我想选择空值,我必须从选择模型中清除所有选择/通过一些额外的控制。
  • 虽然这是一个老问题,但我花了相当多的时间试图在我的应用程序中解决同样的问题,并认为我不妨在这里添加我的解决方案。

    一个可能的解决方法是创建一个额外的列表,其中包含null和您希望可选择的项目。

    ObservableList<String> selectableActivities = FXCollections.observableArrayList("a", "b", "c");
    ObservableList<String> selectableActivitiesWithNull = FXCollections.observableArrayList();;
    selectableActivitiesWithNull.add(null);
    selectableActivitiesWithNull.addAll(selectableActivities);
    

    为了支持原始列表的更新,您需要一个ListChangeListener来根据原始列表的更改更新额外的列表。

    selectableActivities.addListener((ListChangeListener<String>)(change -> {
        while (change.next()) {
            if (change.wasPermutated()) {
                selectableActivitiesWithNull.sort((a, b) -> {
                    return Integer.compare(selectableActivities.indexOf(a), selectableActivities.indexOf(b));
                });
            } else if (change.wasRemoved()) {
                selectableActivitiesWithNull.remove(change.getFrom()+1, change.getTo()+2);
            } else if (change.wasAdded()) {
                selectableActivitiesWithNull.addAll(change.getFrom()+1, selectableActivities.subList(change.getFrom(), change.getTo()));
            } else if (change.wasUpdated()) {
                for (int i = change.getFrom(); i < change.getTo(); ++i) {
                    selectableActivitiesWithNull.set(i+1, selectableActivities.get(i));
                }
            }
        }
    }));
    

    最后你使用额外的列表为ComboBox项目。

    ComboBox<String> combobox = new ComboBox<String>();
    combobox.setItems(selectableActivitiesWithNull);
    

    现在您可以像往常一样修改原始列表,并且ComboBox将相应地更新,同时也有一个空选择作为第一项。最重要的是,您的原始列表不会被占位符对象污染,而占位符对象可能会在应用程序的其他部分引起问题。

    这也将与其他对象一起工作,假设您向组合框添加了适当的StringConverter。注意,如果使用上述方法,转换器还必须能够处理空值。

    StringConverter<Object> activityConverter = new StringConverter<Object>() {
        @Override
        public String toString(Object object) {
            return object != null ? object.toString() : "";
        }
        @Override
        public ActivityDataRow fromString(String string) {
            return null;
        }
    };
    combobox.setConverter(activityConverter);
    

    虽然这种方法不完全是您想要的,但我相信这是您可以在不实现自定义组合框的情况下得到的。

    最新更新