Вы не должны использовать входные события для запуска прослушивания изменений в состоянии CheckBox
.Вместо этого добавьте прослушиватель к свойству CheckBox.selected
.
Кроме того, вам необходимо реализовать способ восстановления состояния CheckBox
, поскольку для "проверенной строки" могут использоваться разные TableCell
s.Используйте некоторую наблюдаемую структуру данных для хранения такого рода информации и используйте прослушиватель для обновления состояния CheckBox
es:
TableView<Integer> table = new TableView<>();
for (int i = 0; i < 100; i++) {
table.getItems().add(i);
}
TableColumn<Integer, Number> column = new TableColumn<>();
column.setCellValueFactory(cd -> new SimpleIntegerProperty(cd.getValue()));
// property to store the checked row item or null, if no row is checked
final ObjectProperty<Integer> selectedValue = new SimpleObjectProperty<>();
TableColumn<Integer, Void> checkBoxColumn = new TableColumn<>();
checkBoxColumn.setCellFactory(col -> new TableCell<Integer, Void>() {
private final CheckBox checkBox = new CheckBox();
private final ChangeListener<Boolean> selectionListener = (o, oldValue, newValue) -> {
if (newValue) {
// use the row item as selected item, when checkbox is selected
selectedValue.set((Integer) getTableRow().getItem());
} else {
// clear selected item, when checkbox is unselected
selectedValue.set(null);
}
};
private final ChangeListener<Integer> listener = (o, oldValue, newValue) -> {
if (!isEmpty()) {
// update state without triggering the listener
checkBox.selectedProperty().removeListener(selectionListener);
if (newValue == null) {
checkBox.setSelected(false);
checkBox.setDisable(false);
} else {
boolean match = newValue.equals(getTableView().getItems().get(getIndex()));
checkBox.setSelected(match);
checkBox.setDisable(!match);
}
checkBox.selectedProperty().addListener(selectionListener);
}
};
{
// listener should not prevent garbage collection of cell
selectedValue.addListener(new WeakChangeListener<>(listener));
checkBox.selectedProperty().addListener(selectionListener);
setAlignment(Pos.CENTER);
}
@Override
protected void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
setGraphic(checkBox);
listener.changed(null, null, selectedValue.get());
}
}
});
table.getColumns().addAll(column, checkBoxColumn);