My application has an object containing multiple ObjectProperty<Enum> fields. I am trying to write a helper method that does the following:
- Accept any type of
ObjectProperty<Enum>as a parameter - Display a
ChoiceDialogpopup, allowing the user to select a different text value for theenum - Update the value of the
enumin the passedObjectPropertyitself
I am not very familiar with generics at all, but I believe the following might work (no compiler errors):
public static <E extends Enum<E>> boolean editEnumProperty(String prompt,
ObjectProperty<Class<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);
// Currently, this displays the enum NAME in the ComboBox, rather than it's text value
dialog.getItems().setAll(FXCollections.observableArrayList(property.get().getEnumConstants()));
Stage dialogStage = (Stage) dialog.getDialogPane().getScene().getWindow();
dialogStage.getIcons().add(ImageHelper.appIcon());
Optional<E> result = dialog.showAndWait();
if (result.isPresent()) {
Utility.printTempMsg(result.toString());
Utility.printTempMsg(Enum.valueOf(property.get(), result.toString()).toString());
}
return true;
}
However, I am not sure how to pass the ObjectProperty to this method. When trying to pass my property through as follows, I'm getting a compiler error:
linkEditRequestSource.setOnAction(event ->
editEnumProperty(
"Select new Request Source:",
simpleObject.requestSourceProperty(), // <-- no instance(s) of type variable(s) E exist so that RequestSource conforms to Class<E>
lblRequestSource.getScene().getWindow()
)
);
I also do not know how to then set the value of the ObjectProperty after the user has selected one.
Below is a non-working MCVE:
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceDialog;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.Window;
import java.util.Optional;
enum RequestSource {
ACQUIRED("Acquisition"),
MANUAL("Manually Entered"),
MANAGER("Manager Reported");
private final String text;
RequestSource(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
public class GenericEnumProperty extends Application {
public static void main(String[] args) {
launch(args);
}
public static <E extends Enum<E>> boolean editEnumProperty(String prompt,
ObjectProperty<Class<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(FXCollections.observableArrayList(property.get().getEnumConstants()));
Optional<E> result = dialog.showAndWait();
if (result.isPresent()) {
// This should actually set the value of the underlying object's ObjectProperty<RequestSource> to
// the new value selected in the ComboBox
System.out.println(Enum.valueOf(property.get(), result.toString()).toString());
// Will use this value to track which properties have been modified
return true;
}
return false;
}
@Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
// Label to display current value of RequestSource
Label lblRequestSource = new Label();
// Create a new object
SimpleObject simpleObject = new SimpleObject(RequestSource.ACQUIRED);
// Bind the property value to the label
lblRequestSource.textProperty().bind(simpleObject.requestSourceProperty().asString());
// Hyperlink to open value editor
Hyperlink linkEditRequestSource = new Hyperlink("Request Source:");
linkEditRequestSource.setOnAction(event ->
editEnumProperty(
"Select new Request Source:",
simpleObject.requestSourceProperty(), // <-- no instance(s) of type variable(s) E exist so that RequestSource conforms to Class<E>
lblRequestSource.getScene().getWindow()
)
);
root.getChildren().add(
new HBox(5, linkEditRequestSource, lblRequestSource)
);
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Sample");
primaryStage.show();
}
}
class SimpleObject {
private final ObjectProperty<RequestSource> requestSourceProperty = new SimpleObjectProperty<>();
public SimpleObject(RequestSource source) {
this.requestSourceProperty.set(source);
}
public RequestSource getRequestSourceProperty() {
return requestSourceProperty.get();
}
public void setRequestSourceProperty(RequestSource requestSourceProperty) {
this.requestSourceProperty.set(requestSourceProperty);
}
public ObjectProperty<RequestSource> requestSourceProperty() {
return requestSourceProperty;
}
}
So really there are a few related questions here:
- How can I pass a generic
ObjectProperty<Enum>to the method? - Is it possible to display the enum's text values instead of the enum name?
- How do I set the value of the
Propertyafter the user has selected a new one?