如果您有一个ListView<String>,那么ListView 中的每个项目都是一个String,而CheckBoxListCell.forListView(...) 方法需要一个Callback<String, ObservableValue<Boolean>>。
在 Java 8 之前的想法中,Callback<String, ObservableValue<Boolean>> 是定义单个方法的接口,
public ObservableValue<Boolean> call(String s) ;
因此,您需要实现该接口的东西,然后传入该类型的对象。
documentation 还告诉您如何使用该回调:
一个回调,给定一个类型为 T 的对象(这是一个取出的值
ListView.items 列表),将返回一个
ObservableValue 表示给定项目是否是
选择与否。这个 ObservableValue 将被双向绑定
(意味着单元格中的 CheckBox 将设置/取消设置此属性
基于用户交互,CheckBox 将反映
ObservableValue,如果它在外部发生变化)。
(因为你有一个ListView<String>,这里T是String。)所以,对于列表视图中的每个元素(每个元素都是一个String),回调用于确定一个@987654337 @ 双向绑定到复选框的状态。 IE。如果选中该复选框,则该属性设置为true,如果未选中,则设置为false。相反,如果以编程方式将属性设置为true(或false),则复选框被选中(或未选中)。
这里的典型用例是ListView 中的项目类型将BooleanProperty 作为其状态的一部分。因此,您通常会将其与某种表示您的数据的自定义类一起使用,如下所示与内部 Item 类一起使用:
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.cell.CheckBoxListCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ListViewWithCheckBox extends Application {
@Override
public void start(Stage primaryStage) {
ListView<Item> listView = new ListView<>();
for (int i=1; i<=20; i++) {
Item item = new Item("Item "+i, false);
// observe item's on property and display message if it changes:
item.onProperty().addListener((obs, wasOn, isNowOn) -> {
System.out.println(item.getName() + " changed on state from "+wasOn+" to "+isNowOn);
});
listView.getItems().add(item);
}
listView.setCellFactory(CheckBoxListCell.forListView(new Callback<Item, ObservableValue<Boolean>>() {
@Override
public ObservableValue<Boolean> call(Item item) {
return item.onProperty();
}
}));
BorderPane root = new BorderPane(listView);
Scene scene = new Scene(root, 250, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final BooleanProperty on = new SimpleBooleanProperty();
public Item(String name, boolean on) {
setName(name);
setOn(on);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final BooleanProperty onProperty() {
return this.on;
}
public final boolean isOn() {
return this.onProperty().get();
}
public final void setOn(final boolean on) {
this.onProperty().set(on);
}
@Override
public String toString() {
return getName();
}
}
public static void main(String[] args) {
launch(args);
}
}
如果您真的拥有ListView<String>,则并不清楚您通过单击复选框设置的属性是什么。但是没有什么可以阻止你在回调中创建一个只是为了绑定到复选框的选中状态:
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.cell.CheckBoxListCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ListViewWithStringAndCheckBox extends Application {
@Override
public void start(Stage primaryStage) {
ListView<String> listView = new ListView<>();
for (int i = 1; i <= 20 ; i++) {
String item = "Item "+i ;
listView.getItems().add(item);
}
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 ;
}
}));
BorderPane root = new BorderPane(listView);
Scene scene = new Scene(root, 250, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
请注意,在这种情况下,BooleanPropertys 可能会被频繁地创建和丢弃。这在实践中可能不是问题,但它确实意味着具有专用模型类的第一个版本可能会表现得更好。
在 Java 8 中,您可以简化代码。因为Callback 接口只有一个抽象方法(使其成为函数接口),您可以将Callback<Item, ObservableValue<Boolean>> 视为一个函数,它接受Item 并生成ObservableValue<Boolean>。所以第一个例子中的单元工厂可以写成lambda expression:
listView.setCellFactory(CheckBoxListCell.forListView(item -> item.onProperty()));
或者,更简洁地使用method references:
listView.setCellFactory(CheckBoxListCell.forListView(Item::onProperty));