javajavafxjavafx-tableview

Javafx tableview on checkbox uncheck, disable button on same row but different column


Below image explains how I have populated my table: enter image description here

As you can see, I need to disable the Installments column button once the Collected column checkbox of related row is unchecked and vise versa.

Here is my approach so far :

colected_column.setCellValueFactory((TableColumn.CellDataFeatures<Member, CheckBox> param) -> {
        Member mRow = param.getValue(); // type objects contained within the TableView
        CheckBox checkBox = new CheckBox();
        checkBox.selectedProperty().addListener((ov, old_val, new_val) -> {

            // javafx.scene.control.Button typed ObservableValue returns as cell value
            Button button = installments_column.getCellData(mRow);
            button.setDisable(!new_val);
        });

      ...
      return new SimpleObjectProperty<>(checkBox);
}

But this approach does not meet the requirement, button stays enable all the time. Any help would be appreciable. Thank you.

enter image description here


Solution

  • Don't put nodes in your item class. This way you ruin the main benefit of TableView: limiting the amount of nodes to the one it needs to display the content.

    You should better use a BooleanProperty in your Member object, use CheckBoxTableCell to display the CheckBoxes and use custom cells for the installments column:

    TableColumn<Member, Boolean> colected_column = ...;
    
    colected_column.setCellValueFactory((TableColumn.CellDataFeatures<Member, Boolean> param) -> {
        Member mRow = param.getValue(); // type objects contained within the TableView
        return nRow.collectedProperty();
    });
    colected_column.setCellFactory(CheckBoxTableCell.forTableColumn(colected_column));
    
    TableColumn<Member, Boolean> installmentsColumn = ...;
    installmentsColumn.setCellValueFactory(cd -> cd.getValue().collectedProperty());
    installmentsColumn.setCellFactory(column -> new TableCell<Member, Boolean>() {
    
        private final Button button = new Button("View Info");
    
        {
            button.setOnAction(evt -> {
                Member member = (Member) getTableRow().getItem();
    
                // TODO: handle button click
            });
        }
    
        @Override
        protected void updateItem(Boolean item, boolean empty) {
            super.updateItem(item, empty);
    
            if (empty || item == null) {
                setGraphic(null);
            } else {
                setGraphic(button);
                button.setDisable(!item);
            }
        }
    });
    
    public class Member {
        private final BooleanProperty collected = new SimpleBooleanProperty(true);
    
        public void setCollected(boolean value) {
            collected.set(value);
        }
    
        public boolean isCollected() {
            return collected.get();
        }
    
        public BooleanProperty collectedProperty() {
            return collected;
        }
    
        ...
    }