Свойство, которое необходимо передать в метод generi c, должно быть ObjectProperty<E>
, а не ObjectProperty<Class<E>>
. Затем вы можете сделать:
public static <E extends Enum<E>> boolean editEnumProperty(String prompt,
ObjectProperty<E> property,
Window owner) {
// Create the dialog to ask for a new enum value
ChoiceDialog<E> dialog = new ChoiceDialog<>();
dialog.setTitle("Edit Value");
dialog.setHeaderText(null);
dialog.setContentText(prompt);
dialog.initOwner(owner);
dialog.getItems().setAll(property.get().getDeclaringClass().getEnumConstants());
Optional<E> result = dialog.showAndWait();
boolean changed = result.isPresent();
result.ifPresent(property::set);
return changed ;
}
Теперь ваш примерный код работает как есть.
Здесь есть одно предостережение: если property.get()
возвращает null
, тогда это приведет к нулю исключение указателя в
dialog.getItems().setAll(property.get().getDeclaringClass().getEnumConstants());
Если вы хотите поддерживать "неустановленные" свойства, значение которых равно null, я думаю, вам понадобится дополнительный параметр в методе для представления типа:
public static <E extends Enum<E>> boolean editEnumProperty(String prompt,
Class<E> enumType,
ObjectProperty<E> property,
Window owner) {
// Create the dialog to ask for a new enum value
ChoiceDialog<E> dialog = new ChoiceDialog<>();
dialog.setTitle("Edit Value");
dialog.setHeaderText(null);
dialog.setContentText(prompt);
dialog.initOwner(owner);
dialog.getItems().setAll(enumType.getEnumConstants());
Optional<E> result = dialog.showAndWait();
boolean changed = result.isPresent();
result.ifPresent(property::set);
return changed ;
}
В этом случае вам просто нужна эта небольшая модификация:
linkEditRequestSource.setOnAction(event ->
editEnumProperty(
"Select new Request Source:",
RequestSource.class,
simpleObject.requestSourceProperty(),
lblRequestSource.getScene().getWindow()
)
);
Ваш единственный оставшийся вопрос:
Можно ли отображать текстовые значения перечисления вместо имени перечисления?
Поскольку не все перечисления имеют метод getText()
, нет особенно простого способа подключиться к определенному вами методу getText()
для отображения значений перечисления. Как правило, вы можете предложить необязательный параметр Function<E, String>
с помощью перегрузки:
public static <E extends Enum<E>> boolean editEnumProperty(
String prompt,
ObjectProperty<E> property,
Window owner) {
return editEnumProperty(prompt, property, Object::toString, owner);
}
public static <E extends Enum<E>> boolean editEnumProperty(
String prompt,
ObjectProperty<E> property,
Function<? super E, String> displayText,
Window owner) {
// now what...?
}
, но поскольку нет доступа (насколько я могу судить) к полю выбора (или полю со списком?), Отображаемому ChoiceDialog
, нет очевидного способа настроить способ отображения текста.
На этом этапе вы можете использовать собственную версию ChoiceDialog
(получение доступа к всплывающему элементу управления); например:
public static <E extends Enum<E>> boolean editEnumProperty(String prompt, ObjectProperty<E> property,
Function<? super E, String> displayText, Window owner) {
Dialog<E> dialog = new Dialog<>();
ChoiceBox<E> choice = new ChoiceBox<>();
choice.setConverter(new StringConverter<E>() {
@Override
public String toString(E object) {
return displayText.apply(object);
}
@Override
public E fromString(String string) {
// Not actually needed...
return null;
}
});
choice.getItems().setAll(property.get().getDeclaringClass().getEnumConstants());
choice.getSelectionModel().select(property.get());
dialog.getDialogPane().setContent(new HBox(5, new Label(prompt), choice));
dialog.getDialogPane().getButtonTypes().setAll(ButtonType.CANCEL, ButtonType.OK);
dialog.setResultConverter(button ->
button == ButtonType.OK ? choice.getSelectionModel().getSelectedItem() : null
);
return dialog.showAndWait().map(value -> {
property.set(value);
return true ;
}).orElse(false);
}
или вы можете попробовать уродливый хак вроде этого, который сохраняет строковые значения и соответствующие значения eval в Map
:
public static <E extends Enum<E>> boolean editEnumProperty(String prompt, ObjectProperty<E> property,
Function<? super E, String> displayText, Window owner) {
// Create the dialog to ask for a new enum value
ChoiceDialog<String> dialog = new ChoiceDialog<>();
dialog.setTitle("Edit Value");
dialog.setHeaderText(null);
dialog.setContentText(prompt);
dialog.initOwner(owner);
Map<String, E> displayValueLookup = Stream.of(property.get().getDeclaringClass().getEnumConstants())
.collect(Collectors.toMap(displayText, Function.identity()));
dialog.getItems().setAll(displayValueLookup.keySet());
return dialog.showAndWait()
.map(displayValueLookup::get)
.map(value -> {
property.set(value);
return true ;
})
.orElse(false);
}
и теперь курс
linkEditRequestSource.setOnAction(event -> editEnumProperty(
"Select new Request Source:",
simpleObject.requestSourceProperty(),
RequestSource::getText,
lblRequestSource.getScene().getWindow()));