Я думаю, для этого вам необходимо создать общую модель Parameter
и использовать ее как тип для вашей таблицы. Вы можете сделать его абстрактным и определить абстрактный метод getEditor()
(или, возможно, делегировать фабрику редактора другому классу, но я постараюсь сделать это максимально простым). Затем определите подклассы, которые при необходимости создают разные редакторы.
Это может выглядеть примерно так:
public abstract class Parameter<T> {
private final BooleanProperty editable = new SimpleBooleanProperty();
private final ObjectProperty<T> value = new SimpleObjectProperty<>();
private final String name ;
public Parameter(String name, T value, boolean editable) {
this.name = name ;
setValue(value);
setEditable(editable);
}
public Parameter(String name, T value) {
this(name, value, true);
}
public String getName() {
return name ;
}
public ObjectProperty<T> valueProperty() {
return value ;
}
public T getValue() {
return valueProperty().get();
}
public void setValue(T value) {
valueProperty().set(value);
}
public BooleanProperty editableProperty() {
return editable ;
}
public boolean isEditable() {
return editableProperty().get() ;
}
public void setEditable(boolean editable) {
editableProperty().set(editable);
}
public abstract Node getEditor() ;
}
Тогда вы могли бы иметь простую реализацию, как это для «свободных» строк:
public class StringParameter extends Parameter<String> {
private final TextField editor ;
public StringParameter(String name, String value) {
super(name, value);
editor = new TextField();
editor.textProperty().bindBidirectional(valueProperty());
}
@Override
public Node getEditor() {
return editor ;
}
}
и, возможно, что-то вроде этого для блесны:
public class BoundIntegerParameter extends Parameter<Integer> {
private final Spinner<Integer> editor ;
public BoundIntegerParameter(int min, int max, String name, int value) {
super(name, value);
editor = new Spinner<>(min, max, value);
editor.setEditable(true);
editor.getValueFactory().valueProperty().bindBidirectional(valueProperty());
}
@Override
public Node getEditor() {
return editor ;
}
}
Для «фиксированного списка» вы можете аналогичным образом реализовать FixedStringParameter
, который взял список строк и чей метод getEditor
вернул ComboBox
. Другой подход для фиксированных вариантов может быть использование Enum
типов: это может выглядеть как
public class EnumParameter<E extends Enum<E>> extends Parameter<E> {
private final ComboBox<E> editor ;
public EnumParameter(String name, E value) {
super(name, value);
editor = new ComboBox<>();
@SuppressWarnings("unchecked")
Class<E> type = (Class<E>) value.getClass();
E[] values = type.getEnumConstants() ;
editor.getItems().setAll(values);
editor.valueProperty().bindBidirectional(valueProperty());
}
@Override
public Node getEditor() {
return editor ;
}
}
Теперь для реализации ячеек для столбца значения, вам нужно немного хитрости.Это похоже на работу:
public class ParameterValueEditingCell extends TableCell<Parameter<?>, Object> {
@Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
setText(null);
Parameter<?> param = getTableView().getItems().get(getIndex());
setGraphic(param.getEditor());
} else {
setText(item.toString());
setGraphic(null);
}
}
}
@Override
public void startEdit() {
// check if current parameter is editable and bail if not:
int index = getIndex();
if (index < 0 || index >= getTableView().getItems().size()) {
return ;
}
if (! getTableView().getItems().get(index).isEditable()) {
return ;
}
super.startEdit();
setText(null);
setGraphic(getTableView().getItems().get(getIndex()).getEditor());
}
@Override
public void cancelEdit() {
super.cancelEdit();
Object item = getItem();
setText(item == null ? null : item.toString());
setGraphic(null);
}
}
Наконец, вы можете установить вещи, как
TableView<Parameter<?>> table = new TableView<>();
table.setEditable(true);
TableColumn<Parameter<?>, Object> valueColumn = new TableColumn<>("Value");
// I can't see any way to set this up without the ugly (unchecked) cast
// Any ideas?
valueColumn.setCellValueFactory(cellData -> (ObservableValue<Object>)cellData.getValue().valueProperty());
valueColumn.setCellFactory(tc -> new ParameterValueEditingCell());
Я сделал полный пример here
Вам нужен мобильный завод и обычай 'реализации TableCell'. В зависимости от точных требований (например, если и когда свойство «редактируемого» и список допустимых значений для любого данного элемента могут измениться), это может быть довольно просто или достаточно сложно. –