Reputation: 6394
I created a simple dialog with radio buttons
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.image.Image?>
<Dialog fx:id="dialog"
fx:controller="myapp.AddDialogController"
xmlns:fx="http://javafx.com/fxml">
<dialogPane>
<DialogPane prefWidth="400.0" prefHeight="300.0">
<stylesheets>
<URL value="@/css/styles.css" />
</stylesheets>
<content>
<VBox>
<fx:define>
<ToggleGroup fx:id="myToggleGroup"/>
</fx:define>
<children>
<RadioButton text="Comment" toggleGroup="$myToggleGroup"/>
<RadioButton text="Survey" toggleGroup="$myToggleGroup"/>
<RadioButton text="Suggestion" toggleGroup="$myToggleGroup"/>
</children>
</VBox>
</content>
</DialogPane>
</dialogPane>
</Dialog>
And I create it like this:
private String convertDialogResult(ButtonType buttonType) {
if (buttonType == ButtonType.OK) {
return "A";
} else {
return null;
}
}
private Dialog<String> createAddDialog() throws ApplicationException {
try {
Dialog<NodeViewModel> dialog = FXMLLoader.load(getClass().getResource("/fxml/add_dialog.fxml"));
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
dialog.setResultConverter(this::convertDialogResult);
return dialog;
} catch (IOException e) {
throw new ApplicationException(e);
}
}
But now I'd like not to return "A" all the time, but "A" if "Comment" is selected, "B" if "Survey" is selected, etc.
How can I do it?
Upvotes: 2
Views: 1829
Reputation: 159291
So you have a controller: myapp.AddDialogController
and in that you will have defined @FXML ToggleGroup #myToggleGroup
. So the controller knows about the toggle group associated with the radio buttons in your dialog.
Instead of using the static FXMLLoader load function, instead create a new FXMLLoader and use a (non-static) load function from that. Once you do that, you can get a reference to the controller out of the loader instance. The technique for getting the controller reference from the controller is demonstrated in the answer to: Passing Parameters JavaFX FXML.
Once you have a reference to your controller, you can pass that as an additional parameter to your convertDialogResult
function. In that function, instead of just returning the character A, you can instead return a mapping from the selected toggle in the toggle group (which you find out by querying a new method you add to Controller getSelectedToggle
) to the String you wish (for instance "Comment"). You don't even really need to maintain a mapping in code if it is sufficient to just invoke getText() on the selected toggle button.
However, in the end, I think the preferred option, rather than externalizing some of the dialog logic from the controller as you have done, would be instead to encapsulate some of the logic inside the controller similar to below:
myapp/add-dialog.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.VBox?>
<Dialog fx:id="dialog"
fx:controller="myapp.AddDialogController"
xmlns:fx="http://javafx.com/fxml">
<dialogPane>
<DialogPane prefWidth="400.0" prefHeight="300.0">
<content>
<VBox>
<fx:define>
<ToggleGroup fx:id="myToggleGroup"/>
</fx:define>
<RadioButton text="Comment" toggleGroup="$myToggleGroup"/>
<RadioButton text="Survey" toggleGroup="$myToggleGroup"/>
<RadioButton text="Suggestion" toggleGroup="$myToggleGroup"/>
</VBox>
</content>
</DialogPane>
</dialogPane>
</Dialog>
myapp/AddDialogController.java
package myapp;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.*;
public class AddDialogController {
@FXML private ToggleGroup myToggleGroup;
@FXML private Dialog<String> dialog;
public void initialize() {
dialog.getDialogPane().getButtonTypes().addAll(
ButtonType.OK, ButtonType.CANCEL
);
Node okButton = dialog.getDialogPane().lookupButton(ButtonType.OK);
okButton.disableProperty().bind(
Bindings.isNull(
myToggleGroup.selectedToggleProperty()
)
);
dialog.setResultConverter(this::convertDialogResult);
}
private String convertDialogResult(ButtonType buttonType) {
if (ButtonType.OK.equals(buttonType)) {
return getSelectedToggleValue();
} else {
return null;
}
}
private String getSelectedToggleValue() {
RadioButton selectedRadio = (RadioButton) myToggleGroup.getSelectedToggle();
if (selectedRadio == null) {
return null;
}
return selectedRadio.getText();
}
}
myapp/DialogDisplayApp.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.IOException;
public class DialogDisplayApp extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"add-dialog.fxml"
)
);
stage.setScene(new Scene(new VBox(new Label("Main Window")), 600, 400));
stage.show();
Dialog<String> dialog = loader.load();
dialog.initOwner(stage);
dialog.showAndWait();
System.out.println(dialog.getResult());
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 4
Reputation: 3968
Have you already tried this: get-selected-radio-button-from-togglegroup
group.selectedToggleProperty().addListener(new ChangeListener<Toggle>(){
public void changed(ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) {
if (group.getSelectedToggle() != null) {
System.out.println(group.getSelectedToggle().getUserData().toString());
// Do something here with the userData of newly selected radioButton
}
}
});
Upvotes: 0