从 ListView 中获取选定的项目 |复选框列表单元格
Getting selected Items from a ListView | CheckBoxListCell
我想为每个项目创建一个简单的 ListView
和 CheckBox
。这已经完成了。现在我正在寻找一种方法来从此 ListView 中获取所有选定的项目。
我发现我可以使用方法 setCellFactory()
在单独的集合中选择项目时添加项目,并在未选择项目时删除项目。但我认为这是一种丑陋的方式。
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
中获取所选项目的列表?
如果您向模型 class 添加布尔值 属性,例如:
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
将始终准确包含在列表视图中选中复选框的浇头。
这样使用
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();
}
}
除非 selected
属性 是您模型的一部分,否则您现在将用户交互需求与您的模型混合在一起,我会尽量避免这种情况。
例如,如果您要创建两个列表,并在其中将项目从一个列表移到另一个列表,您是否仍会使用此 属性 或包含在该列表中就足够了?
在您的(比萨饼?)示例中,一旦向用户确认的订单应仅包含已选择的浇头,如果您的比萨饼订单包含所有可能的浇头并且厨房必须迭代,这将是一个奇怪的模型在列表中找到所需的浇头。这强烈表明它被选中的事实不是模型的一部分,而是用户交互项。
为避免混淆用户界面和模型,您可以使用 CheckListView of the ControlsFX 库,它有一个 CheckModel
,它不仅允许您查询选中的项目,还可以在您的逻辑需要时操作它这样做。
我想为每个项目创建一个简单的 ListView
和 CheckBox
。这已经完成了。现在我正在寻找一种方法来从此 ListView 中获取所有选定的项目。
我发现我可以使用方法 setCellFactory()
在单独的集合中选择项目时添加项目,并在未选择项目时删除项目。但我认为这是一种丑陋的方式。
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
中获取所选项目的列表?
如果您向模型 class 添加布尔值 属性,例如:
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
将始终准确包含在列表视图中选中复选框的浇头。
这样使用
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();
}
}
除非 selected
属性 是您模型的一部分,否则您现在将用户交互需求与您的模型混合在一起,我会尽量避免这种情况。
例如,如果您要创建两个列表,并在其中将项目从一个列表移到另一个列表,您是否仍会使用此 属性 或包含在该列表中就足够了?
在您的(比萨饼?)示例中,一旦向用户确认的订单应仅包含已选择的浇头,如果您的比萨饼订单包含所有可能的浇头并且厨房必须迭代,这将是一个奇怪的模型在列表中找到所需的浇头。这强烈表明它被选中的事实不是模型的一部分,而是用户交互项。
为避免混淆用户界面和模型,您可以使用 CheckListView of the ControlsFX 库,它有一个 CheckModel
,它不仅允许您查询选中的项目,还可以在您的逻辑需要时操作它这样做。