1

i have a TableView with the first column with a check box.

I managed to show the checkbox correctly and make it editable, but when i click on the checkbox to check or uncheck, the checkBox changes but it does not update my model.

This is how i did it:

TableColumn<ContasReceber, Boolean> myCheckBoxColumn = (TableColumn<ContasReceber, Boolean>) tabelaContas.getColumns().get(0);
myCheckBoxColumn.setCellFactory(p -> new CheckBoxTableCell<>());
myCheckBoxColumn.setOnEditCommit(evt -> evt.getRowValue().setChecked(evt.getNewValue()));//It never executes the method setChecked when i click on the checkBox to change it's values.
Mateus Viccari
  • 7,389
  • 14
  • 65
  • 101

3 Answers3

5

CheckBoxTableCell is really designed to map to a BooleanProperty in the table model (and in general tables work best with such models). The JavaDocs for CheckBoxTableCell explicitly state that

the usual editing callbacks (such as on edit commit) will not be called

If you want to use a CheckBox in a table cell where the model does not use a BooleanProperty, the best bet is probably to create your own table cell:

myCheckBoxColumn.setCellFactory(p -> {
    CheckBox checkBox = new CheckBox();
    TableCell<ContasReceber, Boolean> cell = new TableCell<ContasReceber, Boolean>() {
        @Override
        public void updateItem(Boolean item, boolean empty) {
            if (empty) {
                setGraphic(null);
            } else {
                checkBox.setSelected(item);
                setGraphic(checkBox);
            }
        }
    };
    checkBox.selectedProperty().addListener((obs, wasSelected, isSelected) -> 
        ((ContasReceber)cell.getTableRow().getItem()).setChecked(isSelected));
    cell.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    cell.setAlignment(Pos.CENTER);
    return cell ;
});
cece2048
  • 1,121
  • 2
  • 11
  • 17
James_D
  • 201,275
  • 16
  • 291
  • 322
1

I found i way of doing it myself, it's quite simple as i answered in this other question: There is a very simple way of doing this, you don't need to modify your model class with SimpleBooleanProperty or whatever, just follow these steps:

1 - Suppose you have a "Person" object with a isUnemployed method:


public class Person {
    private String name;
    private Boolean unemployed;

    public String getName(){return this.name;}
    public void setName(String name){this.name = name;}
    public Boolean isUnemployed(){return this.unemployed;}
    public void setUnemployed(Boolean unemployed){this.unemployed = unemployed;}
}

2 - Create the callback class


import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;

public class PersonUnemployedValueFactory implements Callback, ObservableValue> {
    @Override
    public ObservableValue call(TableColumn.CellDataFeatures param) {
        Person person = param.getValue();
        CheckBox checkBox = new CheckBox();
        checkBox.selectedProperty().setValue(person.isUnemployed());
        checkBox.selectedProperty().addListener((ov, old_val, new_val) -> {
            person.setUnemployed(new_val);
        });
        return new SimpleObjectProperty(checkBox);
    }
}

3 - Bind the callback to the table column

If you use FXML, put the callback class inside your column:

<TableView fx:id="personList" prefHeight="200.0" prefWidth="200.0">
    <columns>
        <TableColumn prefWidth="196.0" text="Unemployed">
            <cellValueFactory>
                <PersonUnemployedValueFactory/> <!--This is how the magic happens-->
            </cellValueFactory>
        </TableColumn>

        ...
    </columns>
</TableView>

Don't forget to import the class in your FXML:

<?import org.yourcompany.yourapp.util.PersonUnemployedValueFactory?>

Without FXML, do it like this:

TableColumn<Person, CheckBox> column = (TableColumn<Person, CheckBox>) personTable.getColumns().get(0);
column.setCellValueFactory(new PersonUnemployedValueFactory());

4 - That's it

Everything should work as expected, with the value being set to the backing bean when you click on the checkbox, and the checkbox value correctly being set when you load the items list in your table.

Community
  • 1
  • 1
Mateus Viccari
  • 7,389
  • 14
  • 65
  • 101
0

Try to create the Column using the following code:

 checkBoxesCol = new TableColumn<ContasReceber, Boolean>("CheckBox Col");
 checkBoxesCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ContasReceber, Boolean>, ObservableValue<Boolean>>() {

                @Override
                public ObservableValue<Boolean> call(CellDataFeatures<ContasReceber, Boolean> param) {
                    return param.getValue().checkedProperty();
                }
            });
 checkBoxesCol.setCellFactory(CheckBoxTableCell.forTableColumn(checkBoxesCol));

The update of the value is automatic(No need for setOnEditCommit )

javaHunter
  • 1,097
  • 6
  • 9
  • But this way i have to tie my model with JavaFX code? Can't i just use a simple Boolean variable instead of SimpleBooleanProperty? – Mateus Viccari Dec 10 '14 at 11:53
  • Try wrapping the boolean vaiable with ReadOnlyBooleanWrapper inside cellValueFactory callback in the code above. – javaHunter Dec 10 '14 at 12:21
  • 1
    The above works for me but it doesn't update the value if I click on the checkbox in the tableview. What am I doing wrong? I have it defined in my model as SimpleBooleanProperty – John Smith Mar 08 '17 at 14:57