I think your solution seems far more complicated than using setOnEditCommit. For example (using the usual contact table type example that Oracle uses), given a standard Person JavaBean:
public class Person {
private String firstName ;
private String lastName ;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return firstName + " " + lastName ;
}
}
This code creates an editable table that updates the Java beans:
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
TableView<Person> table = new TableView<>();
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn());
firstNameCol.setOnEditCommit(
event -> event.getRowValue().setFirstName(event.getNewValue()));
firstNameCol.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().getFirstName()));
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
lastNameCol.setCellFactory(TextFieldTableCell.forTableColumn());
lastNameCol.setOnEditCommit(
event -> event.getRowValue().setLastName(event.getNewValue()));
lastNameCol.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().getLastName()));
table.getColumns().addAll(firstNameCol, lastNameCol);
table.setEditable(true);
Button button = new Button("Show data");
button.setOnAction(event -> table.getItems().forEach(System.out::println));
HBox controls = new HBox(5, button);
root.setCenter(table);
root.setBottom(controls);
table.getItems().addAll(
new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Brown")
);
Scene scene = new Scene(root, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This code also avoids any non-public API classes. I agree that the builder classes are a little more elegant, but they have been deprecated for good reason.
Additionally, this also avoids reflection, unlike the WritablePropertyValueFactory class (or the PropertyValueFactory API class), so it likely performs better.