如何保持"空"在JavaFx中我的组合框列表中选择?

时间:2014-06-14 08:11:45

标签: combobox javafx

在我的应用程序中,我hava combobox从数据库中获取了一些值(一些实时更新列表)。此ComboBox列表每1分钟更新一次。 列表没有空值。当我将此列表设置为ComboBox ..

ComboBox box = new ComboBox(items);

..有一个额外的“空”行,这是完全正常的,因为选择了非值。 在我选择一些值之后,我的“空”值从列表中消失。 我的主要问题是如何将此值保留在列表中?

为什么这是一个问题......

  1. 在数据库中选择Scenerio值,首次启动应用程序
    1. 列表已加载(已选择空值)。
    2. 选择了值。
    3. 在第一次后台刷新期间,空值消失,并且组合框值被选择为n + 1,选择下一个值。
  2. 如果我想选择空值,我必须从选择模型中选择所有clearSelection /通过一些额外的控制。

2 个答案:

答案 0 :(得分:0)

虽然这是一个老问题,但我花了很多时间试图解决应用程序中的同一问题,并认为我也可以在这里添加解决方案。

一种可能的解决方法是创建一个额外的列表,其中包含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将进行相应更新,同时将第一项也留空。最重要的是,您的原始列表不会被占位符对象污染,这些占位符对象可能会导致应用程序其他部分出现问题。

这也将与其他对象一起使用,假设您向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);

虽然这种方法并非您所需要的,但我相信这是无需实施自定义组合框即可获得的结果。

答案 1 :(得分:-1)

您只需要添加" "作为其中一项,然后选择它,这真的很容易:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class ComboBoxSample extends Application {
    public static void main(String[] args) {
        launch(args);
    }
    @Override public void start(Stage stage) {
        stage.setTitle("ComboBoxSample");
        Scene scene = new Scene(new Group(), 450, 250);
        final ComboBox<String> fooComboBox = new ComboBox<String>();
        fooComboBox.getItems().addAll(
            "     ",
            "foo",
            "bar",
            "FooBar"
        );
        fooComboBox.setValue("     ");
        HBox box = new HBox();
        box.getChildren().add(fooComboBox);
        Group root = (Group)scene.getRoot();
        root.getChildren().add(box);
        stage.setScene(scene);
        stage.show();
    }    
}

使用Person类的示例:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class ComboBoxSample extends Application {



    ObservableList<Person> people =
            FXCollections.observableArrayList(
                new Person(null,null),
                new Person("Paul", "Mc"),
                new Person("Bill", "Apple"),
                new Person("Foo", "Bar")

            );

    @Override
    public void start(Stage primaryStage) {

        final ComboBox comboBox = new ComboBox(people);
        comboBox.getSelectionModel().selectFirst(); //select the first element

        comboBox.setCellFactory(new Callback<ListView<Person>,ListCell<Person>>(){

            @Override
            public ListCell<Person> call(ListView<Person> p) {

                final ListCell<Person> cell = new ListCell<Person>(){

                    @Override
                    protected void updateItem(Person t, boolean bln) {
                        super.updateItem(t, bln);

                        if(t != null){
                            setText(t.toString());
                        }else{
                            setText(null);
                        }
                    }

                };

                return cell;
            }
        });

        final Label label = new Label();

        Button btn = new Button();
        btn.setText("Read comboBox");
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if(!(comboBox.getValue().toString()==null))
                    label.setText("selected: " + comboBox.getValue());
                else
                    label.setText("null");
            }
        });

        VBox vBox = new VBox();
        vBox.setPadding(new Insets(5, 5, 5, 5));
        vBox.setSpacing(5);
        vBox.getChildren().addAll(label, comboBox, btn);

        StackPane root = new StackPane();
        root.getChildren().add(vBox);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Combo!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

班级人员:

public class Person {
    private String firstName;
    private String lastName;
    public Person(String first, String last){
        this.lastName = last;
        this.firstName = first;
    }
    public String getName() {
        return firstName;
    }
    public void setName(String name) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public void setFullName(String first, String last){
        this.lastName = last;
        this.firstName = first;
    }
    @Override
    public String toString() {
        if(firstName != null)
            return "" + firstName + " " + lastName;
        else 
            return null;
    }
}