purring pigeon
purring pigeon

Reputation: 4209

Prevent TAB from landing on a CheckBoxTableCell<> in JavaFX 8

I have a TableView in JavaFX 8, which is editable. One of the fields is a CheckBoxTableCell.

I have noticed that the TAB key lands on the first CheckBoxTableCell in the grid and gets stuck there. I don't want this behavior. I like to navigate to the cell with the keyboard and activate with the SPACE. However I need tab to ignore this field - since it gets stuck.

I tried the following:

booleanColumn.setCellFactory (to -> {
   CheckBoxTableCell<DTO, Boolean> cell = CheckBoxTableCell<>();
   cell.setFocusTraversable(false);
   return cell;
}

This however has no affect on the focus of the field, since it's editable, it lands on that control and gets stuck.

If I change to:

cell.setDisable(true);

Then TAB will skip the field, but I can land on the column with the arrow keys. However I can't select the checkbox with the mouse.

I am at a loss as what to do.

Thanks.

Upvotes: 1

Views: 998

Answers (1)

Jos&#233; Pereda
Jos&#233; Pereda

Reputation: 45456

The workaround to get the TAB key working first implies consuming the event so the default TableView traversal engine doesn't process it, and selecting the next or previous cell instead.

This will move the selection from cell to cell:

table.getSelectionModel().setCellSelectionEnabled(true);

table.setOnKeyPressed(keyEvent -> {
    switch (keyEvent.getCode()){
        case TAB: {
            keyEvent.consume();
            if (keyEvent.isShiftDown()) {
                personTable.getSelectionModel().selectPrevious();
            } else {
                personTable.getSelectionModel().selectNext();
            }
            break;
        }
    }
});

But it won't be enough to get the CheckBox focused, and the space key can't be used to select it. So a second step is required to move the focus from the selected cell to the inner checkbox.

When the cell gets the focus, its node will request it.

booleanColumn.setCellFactory (param -> {
    CheckBoxTableCell<DTO, Boolean> cell = new CheckBoxTableCell<>();
    cell.focusedProperty().addListener((obs, ov, nv) -> {
        if (nv && cell.getGraphic() != null) {
            cell.getGraphic().requestFocus();
        }
    });
    return cell;
});

Notice you can't have both the cell and it's checkbox focused at the same time, so the cell will appear grey (selected but not focused), unless you modify its css.

Upvotes: 3

Related Questions