我想为每个项目创建一个简单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
获取所选项目的列表?
答案 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 command库CheckListView ControlsFX,CheckModel
库不仅允许您查询已检查的项目,还可以对其进行操作如果你的逻辑要求这样做。