У меня очень сложное табличное представление со столбцами, сделанными из разных cellFactories. Один набор столбцов может быть comboBox или TextField. Моя главная проблема заключается в том, что переход от одной ячейки к другой не работает. Переход от textField к textField работает, но как только я нажимаю comboBox, блок получает фокус, но как только элемент выбран, блок закрывается, и навигация по ячейке никуда не ведет.
Я пробовал несколько вещей, проблема действительно обнаружилась, пытаясь заставить comboBox реагировать на события keyPress. В tableView вам все еще нужно щелкнуть мышью, чтобы открыть ComboBox и сделать выбор.
открытый класс CustomFieldTableCell расширяет TableCell {
private final TextField textField = new TextField();
private final ComboBox<String> comboBox = new ComboBox<>();
private boolean isPredefined = false;
private boolean isCustomReqField = false; //else it's a custom result field
private final StringConverter<T> converter ;
private TableView<S> tableView = null;
public CustomFieldTableCell(StringConverter<T> converter) {
this.converter = converter ;
itemProperty().addListener((obx, oldItem, newItem) -> {
if (newItem == null) {
setText(null);
setGraphic(null);
} else {
List<String> predefinedValues = new ArrayList<>();
if (isCustomReqField) {
RequirementField reqField = DiscusController.getInstance().getRequirementField(getTableColumn().getText());
if (reqField != null) {
isPredefined = reqField.getFieldType() == RequirementField.FieldType.PREDEFINED;
predefinedValues = reqField.getPredefinedValues();
}
} else {
ResultField resultField = DiscusController.getInstance().getResultsController().getResultField(getTableColumn().getText());
if (resultField != null) {
isPredefined = resultField.getFieldType() == ResultField.FieldType.PREDEFINED;
predefinedValues = resultField.getPredefinedValues();
}
}
if (isPredefined) {
setGraphic(comboBox);
comboBox.getItems().clear();
comboBox.getItems().add(" ");
comboBox.getItems().addAll(predefinedValues);
comboBox.getSelectionModel().select(converter.toString(newItem));
} else {
textField.setText(converter.toString(newItem));
setGraphic(textField);
}
setText(converter.toString(newItem));
}
});
setContentDisplay(ContentDisplay.TEXT_ONLY);
textField.setOnAction(evt -> {
commitEdit(this.converter.fromString(textField.getText()));
});
textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (! isNowFocused) {
commitEdit(this.converter.fromString(textField.getText()));
}
});
comboBox.setOnAction(evt -> {
commitEdit(this.converter.fromString(comboBox.getValue()));
});
comboBox.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (! isNowFocused) {
commitEdit(this.converter.fromString(comboBox.getValue()));
}
});
comboBox.setOnKeyPressed(event -> {
String s = DropdownUtils.jumpToCombo(event.getText(), comboBox.getValue(), comboBox.getItems());
if (s != null) {
comboBox.setValue(s);
}
if (event.getCode() == KeyCode.ENTER) {
if (isPredefined) {
commitEdit(this.converter.fromString(comboBox.getValue()));
} else {
commitEdit(this.converter.fromString(textField.getText()));
}
int increment = event.isShiftDown() ? -1 : 1;
int index = getTableRow().getIndex() + increment;
getTableView().edit(index, getTableColumn());
getTableView().scrollTo(index - 1);
} else if (event.getCode() == KeyCode.ESCAPE) {
cancelEdit();
} else if (event.getCode() == KeyCode.TAB) {
if (isPredefined) {
commitEdit(this.converter.fromString(comboBox.getValue()));
} else {
commitEdit(this.converter.fromString(textField.getText()));
}
if (tableView != null) {
TableColumn nextColumn = getNextColumn(!t.isShiftDown(), this.getTableColumn());
if (nextColumn != null) {
getTableView().edit(getTableRow().getIndex(), nextColumn);
}
}
}
});
textField.setOnKeyPressed(t -> {
if (t.getCode() == KeyCode.ENTER) {
if (isPredefined) {
commitEdit(this.converter.fromString(comboBox.getValue()));
} else {
commitEdit(this.converter.fromString(textField.getText()));
}
int increment = t.isShiftDown() ? -1 : 1;
int index = getTableRow().getIndex() + increment;
getTableView().edit(index, getTableColumn());
getTableView().scrollTo(index - 1);
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
} else if (t.getCode() == KeyCode.TAB) {
if (isPredefined) {
commitEdit(this.converter.fromString(comboBox.getValue()));
} else {
commitEdit(this.converter.fromString(textField.getText()));
}
if (tableView != null) {
TableColumn nextColumn = getNextColumn(!t.isShiftDown(), this.getTableColumn());
if (nextColumn != null) {
getTableView().edit(getTableRow().getIndex(), nextColumn);
}
}
}
});
}
public CustomFieldTableCell(TableView tableView, boolean isCustomReqField) {
this((StringConverter<T>) IDENTITY_CONVERTER);
this.tableView = tableView;
this.isCustomReqField = isCustomReqField;
}
public static <S> CustomFieldTableCell<S, String> createTextFieldComboCell(TableView<S> table, boolean isCustomReqField) {
return new CustomFieldTableCell<>(table, isCustomReqField);
}
// set the text of the text field and display the graphic
@Override
public void startEdit() {
super.startEdit();
textField.setText(converter.toString(getItem()));
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
if (isPredefined) {
comboBox.requestFocus();
} else {
textField.requestFocus();
}
}
// revert to text display
@Override
public void cancelEdit() {
super.cancelEdit();
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
// commits the edit. Update property if possible and revert to text display
@Override
public void commitEdit(T item) {
// This block is necessary to support commit on losing focus, because the baked-in mechanism
// sets our editing state to false before we can intercept the loss of focus.
// The default commitEdit(...) method simply bails if we are not editing...
if (! isEditing() && item != null && !item.equals(getItem())) {
TableView<S> table = getTableView();
if (table != null) {
TableColumn<S, T> column = getTableColumn();
CellEditEvent<S, T> event = new CellEditEvent<>(table,
new TablePosition<S,T>(table, getIndex(), column),
TableColumn.editCommitEvent(), item);
Event.fireEvent(column, event);
}
}
super.commitEdit(item);
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
private TableColumn<S, ?> getNextColumn(boolean forward, TableColumn currentCol) {
List<TableColumn<S, ?>> columns = new ArrayList<>();
for (TableColumn column : tableView.getColumns()) {
columns.addAll(getLeaves(column));
}
//There is no other column that supports editing.
if (columns.size() < 2) {
return null;
}
int currentIndex = -1;
for (int i = 0; i < columns.size(); i++) {
if (columns.get(i) == currentCol) {
currentIndex = i;
break;
}
}
int nextIndex = currentIndex;
if (forward) {
nextIndex++;
if (nextIndex > columns.size() - 1) {
nextIndex = 0;
}
} else {
nextIndex--;
if (nextIndex < 0) {
nextIndex = columns.size() - 1;
}
}
return columns.get(nextIndex);
}
. , .
}
Я ищу способ перехода от ячейки к ячейке независимо от того, является ли ячейка textField или ComboBox.