序列化问题不会阻止您在模型类UserVillage 中使用JavaFX 属性。我建议使用这些属性并通过定义readObject 和writeObject 方法来自定义序列化机制。这是一个这样定义的类的演示:
public class Item implements Serializable {
private StringProperty name ;
private IntegerProperty value ;
private BooleanProperty active ;
public Item(String name, int value, boolean active) {
this.name = new SimpleStringProperty(name) ;
this.value = new SimpleIntegerProperty(value);
this.active = new SimpleBooleanProperty(active);
}
public final StringProperty nameProperty() {
return this.name;
}
public final java.lang.String getName() {
return this.nameProperty().get();
}
public final void setName(final java.lang.String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
public final BooleanProperty activeProperty() {
return this.active;
}
public final boolean isActive() {
return this.activeProperty().get();
}
public final void setActive(final boolean active) {
this.activeProperty().set(active);
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(getName());
out.writeInt(getValue());
out.writeBoolean(isActive());
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
this.name = new SimpleStringProperty((String)in.readObject());
this.value = new SimpleIntegerProperty(in.readInt());
this.active = new SimpleBooleanProperty(in.readBoolean());
}
// Quick test:
public static void main(String[] args) throws IOException, ClassNotFoundException {
Item testItem = new Item("Item", 42, true);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(testItem);
oos.close();
byte[] bytes = out.toByteArray();
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
Item result = (Item) in.readObject();
System.out.println(result.getName());
System.out.println(result.getValue());
System.out.println(result.isActive());
}
}
通过这种方法,CheckBoxTableCell 将自动绑定到PropertyValueFactory 返回的属性。
另一种方法是创建一个BooleanProperty,专门用于绑定到复选框选中状态。请注意,根据Javadocs,因为CheckBoxTableCell 永远不会进入或离开编辑状态,所以永远不会调用编辑回调onEditCommit 等:
请注意,CheckBoxTableCell 将 CheckBox 呈现为“实时”,这意味着
CheckBox 始终是交互式的,可以通过以下方式直接切换
用户。这意味着没有必要让细胞进入它的
编辑状态(通常由用户双击单元格)。一个
这样做的副作用是通常的编辑回调(例如
编辑提交)将不会被调用。如果您想收到通知
变化,建议直接观察布尔属性
由 CheckBox 操作。
这是一个使用这种技术的演示。同样,我并不真正推荐这种方法,因为您最终会创建一堆BooleanPropertys,它们很快就可以进行垃圾收集。预期的方法是让模型使用 JavaFX 属性。
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TableViewCheckBoxTest extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
table.setEditable(true);
table.getColumns().add(createColumn("Name", "name"));
table.getColumns().add(createColumn("Value", "value"));
TableColumn<Item, Boolean> activeCol = createColumn("Active", "active");
table.getColumns().add(activeCol);
activeCol.setCellFactory(col -> {
CheckBoxTableCell<Item, Boolean> cell = new CheckBoxTableCell<>(index -> {
BooleanProperty active = new SimpleBooleanProperty(table.getItems().get(index).isActive());
active.addListener((obs, wasActive, isNowActive) -> {
Item item = table.getItems().get(index);
item.setActive(isNowActive);
});
return active ;
});
return cell ;
});
Button listActiveButton = new Button("List active");
listActiveButton.setOnAction(e ->
table.getItems().stream()
.filter(Item::isActive)
.map(Item::getName)
.forEach(System.out::println));
IntStream.rangeClosed(1, 100)
.mapToObj(i -> new Item("Item "+i, i, false))
.forEach(table.getItems()::add);
BorderPane root = new BorderPane(table, null, null, listActiveButton, null) ;
BorderPane.setAlignment(listActiveButton, Pos.CENTER);
BorderPane.setMargin(listActiveButton, new Insets(10));
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private <S,T> TableColumn<S,T> createColumn(String title, String propertyName) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(new PropertyValueFactory<>(propertyName));
return col;
}
public static class Item implements Serializable {
private String name ;
private int value ;
private boolean active ;
public Item(String name, int value, boolean active) {
this.name = name ;
this.value = value ;
this.active = active ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}
public static void main(String[] args) {
launch(args);
}
}