JavaFX EditCommit on Boolean TableCells

57 Views Asked by At

I develop a JavaFX application containing a table. The related data model has a number of fields of type BooleanProperty. What I am after is I need to distinguish between the setup when the tables' setItems() is called and when the model is altered by the user, in order to track whether the data needs to be saved at a later point in time. I understand that there is no setOnEditCommit() for checkboxes in tables. Therefore I tried a few things. The simplest one was

   metronomColumn.setCellValueFactory(p -> {
        hasUnsavedChanges=true;
        return p.getValue().withMetronomProperty();
   });      
   metronomColumn.setCellFactory( tc -> new CheckBoxTableCell<>());

but hasUnsavedChanges=true; is called also on setItems(). So I tried to move it from the CellValueFactory to the CellFactory

   metronomColumn.setCellValueFactory(p -> p.getValue().withMetronomProperty());
   metronomColumn.setCellFactory( tc -> {
        CheckBoxTableCell<Exercise, Boolean> cbCell = new CheckBoxTableCell<>();
        cbCell.setSelectedStateCallback(i -> {
            hasUnsavedChanges=true;
            return exerciseTable.getItems().get(i).withMetronomProperty();
        });
        return cbCell;
    });        

but here hasUnsavedChanges=true; is also called on setItems(). Hence I tried the following which doesn't work at all, since the listener is never called

    metronomColumn.setCellValueFactory(p -> p.getValue().withMetronomProperty());       
    metronomColumn.setCellFactory( tc -> {
        CheckBoxTableCell cbCell = new CheckBoxTableCell<>();
        cbCell.selectedProperty().addListener((ov, oldVal, newVal) -> {
            hasUnsavedChanges=true;
        });
        return cbCell;
    });

How can I seperate changes from the setItems() setup and user triggered once? Thank you in advance.

1

There are 1 best solutions below

0
James_D On BEST ANSWER

Don't use the table at all for this: just listen to the data.

Create your list with an extractor. Then changes to any of the properties will fire an event on the list:

ObservableList<Exercise> tableItems = FXCollections.observableArrayList(
    e -> new Observable[] {e.withMetronomProperty()});
tableItems.addAll(...);

tableView.setItems(tableItems);

tableItems.addListener((ListChangeListener.Change<? extends Exercise> change) -> 
    hasUnsavedChanges = true);

You can create the extractor with as many properties as you need:

ObservableList<Exercise> tableItems = FXCollections.observableArrayList(
    e -> new Observable[] {e.withMetronomProperty(), e.someOtherProperty()});