By default, pressing ENTER on a TextFieldTableCell
puts the cell into editing mode and draws a textField in the cell. How do I prevent this? I would only like the cell to enter Editing mode if a digit key is pressed. If ENTER is pressed, then it should simply select the cell below.
What I have tried:
tableView.setOnKeyReleased(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
TablePosition tp;
if(event.getCode().isDigitKey()) {
lastKey = event.getText();
tp = tableView.getFocusModel().getFocusedCell();
tableView.edit(tp.getRow() , tp.getTableColumn());
}
if(tableView.getEditingCell() == null && event.getCode() == KeyCode.ENTER) {
event.consume();
tableView.getSelectionModel().selectBelowCell();
}
}
});
The cell still enters Editing mode.
An alternative to manually install filters/handlers on the table is to tweak the table's InputMap. Beware: that's private api, requires access to internal packages (inputmap and behavior) and reflective grabbing of the behavior from the skin. Hopefully, those packages will make it into public scope soon.
The basic approach is
In code:
TableViewSkin<?> skin = (TableViewSkin<?>) table.getSkin();
// use your favorite utility method to reflectively access the private field
TableViewBehavior<?> listBehavior = (TableViewBehavior<?>) FXUtils.invokeGetFieldValue(
TableViewSkin.class, skin, "behavior");
InputMap<?> map = listBehavior.getInputMap();
// remove old mapping for enter
Optional<Mapping<?>> mapping = map.lookupMapping(new KeyBinding(ENTER));
map.getMappings().remove(mapping.get());
// add new mapping for enter
map.getMappings().add(new KeyMapping(KeyCode.ENTER, e -> table.getSelectionModel().selectBelowCell()));
// add mappings for digits
EventHandler<KeyEvent> handler = e -> {
TablePosition<T, ?> pos = table.getFocusModel().getFocusedCell() ;
if (pos != null ) {
table.edit(pos.getRow(), pos.getTableColumn());
}
};
List<KeyMapping> digitMappings = Arrays.stream(KeyCode.values())
.filter(c -> c.isDigitKey())
.map(c -> new KeyMapping(c, handler))
.collect(Collectors.toList());
map.getMappings().addAll(digitMappings);
Obviously, this requires that the table's skin is available and that it is of type TableViewSkin. To use, it can be invoked in a listener to the table's skin property:
table.skinProperty().addListener(c -> {
tweakInputMap(table);
});
Should work in fx versions >= fx9 (my context is fx17/18 dev) and requires add-exports of inputmap/behavior packages at compile time and add-opens of these packages at runtime.