从ListView中获取所选项目CheckBoxListCell

时间:2017-05-10 12:07:48

标签: java listview javafx listviewitem

我想为每个项目创建一个简单ListView CheckBox。这已经完成了。现在我正在寻找一种从这个ListView获取所有选定项目的方法。

我已经发现我可以使用方法setCellFactory()在单独的Collection中选择它们时添加项目,并在取消选择它们时将其删除。但我认为这是一种丑陋的方式。

ListView<String> listView = new ListView<>();
    String[] toppings = {"Cheese", "Pepperoni", "Black Olives"};
    listView.getItems().addAll(toppings);
    listView.setCellFactory(CheckBoxListCell.forListView(new Callback<String, ObservableValue<Boolean>>() {
        @Override
        public ObservableValue<Boolean> call(String item) {
        BooleanProperty observable = new SimpleBooleanProperty();
        observable.addListener((obs, wasSelected, isNowSelected)
            -> System.out.println("Check box for " + item + " changed from " + wasSelected + " to " + isNowSelected)
        );
        return observable;
        }
}));

如何从ListView获取所选项目的列表?

3 个答案:

答案 0 :(得分:3)

如果向模型类添加布尔属性,例如:

public class Topping {

    private final String name ;

    private final BooleanProperty selected = new SimpleBooleanProperty();

    public BooleanProperty selectedProperty() {
        return selected ;
    }

    public final boolean isSelected() {
        return selectedProperty().get();
    }

    public final void setSelected(boolean selected) {
        selectedProperty().set(selected);
    }

    public Topping(String name) {
        this.name = name ;
    }

    public String getName() {
        return name ;
    }

    @Override
    public String toString() {
        return getName(); 
    }
}

并在复选框列表单元格中使用它:

listView.setCellFactory(CheckBoxListCell.forListView(Topping::selectedProperty));

然后您可以创建一个包含所有选定浇头的过滤列表:

ListView<Topping> listView = new ListView<>();
listView.getItems().addAll(new Topping("Cheese"), new Topping("Pepperoni"),
    new Topping("Black Olives"));

ObservableList<Topping> selectedToppings = 
    listView.getItems().filtered(Topping::isSelected);

现在selectedToppings将始终包含在列表视图中选中复选框的配件。

答案 1 :(得分:3)

使用这种方式

public void start(Stage primaryStage) {
        try {
            ListView<String> listView = new ListView<>();
            Button button = new Button("Get");
            List<String> list = new ArrayList<>();
            String[] toppings = { "Cheese", "Pepperoni", "Black Olives" };
            listView.getItems().addAll(toppings);
            listView.setCellFactory(CheckBoxListCell.forListView(new Callback<String, ObservableValue<Boolean>>() {
                @Override
                public ObservableValue<Boolean> call(String item) {
                    BooleanProperty observable = new SimpleBooleanProperty();
                    observable.addListener((obs, wasSelected, isNowSelected) -> {
                        if (isNowSelected) {
                            list.add(item);
                        } else {
                            list.remove(item);
                        }
                    });
                    return observable;
                }
            }));

            button.setOnAction(e -> {
                for (int i = 0; i < list.size(); i++) {
                    System.out.println(list.get(i));
                }
            });

            VBox root = new VBox();
            root.setAlignment(Pos.CENTER);
            root.getChildren().addAll(listView, button);
            Scene scene = new Scene(root, 300, 250);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

答案 2 :(得分:0)

除非selected属性是模型的一部分,否则您现在将用户交互需求与模型混合在一起,我会尽量避免。

例如,如果您要创建两个列表来从一个或另一个中移动项目,您是否仍然使用此属性或者该列表中的包含对您来说是否足够?

在你的(披萨?)示例中,一次确认给用户的订单应该只包含所选择的配料,如果您的披萨订单包含所有可能的配料并且厨房将不得不迭代,那么这将是一个奇怪的模型列表,以找到所需的浇头。这强烈表明选择它的事实不是模型的一部分,而是用户交互项目。

为避免混用用户界面和模型,您可以使用tf merge commandCheckListView ControlsFXCheckModel库不仅允许您查询已检查的项目,还可以对其进行操作如果你的逻辑要求这样做。