How to use ControlsFX (dialogs) together with FXML files?

I have the following idea:

  • I want to use ControlsFX: nice UI, good support for dialogs.
  • I want to use FXML as source for the UI: Scene Builder works nicely, fast creation and change.

Now I face problems in using ControlsFX together with the UI created by an FXML file. Here is the source code:

public class ConfigUI {
private Dialog dlg;

@FXML
TextField urlRepository;

protected Action showConfigDialog() throws IOException {
    dlg = new Dialog(null, "Configuration Dialog for Check SVN");

    Node content = null;
    content = FXMLLoader.load(getClass().getResource("check-dialog.fxml"));

    dlg.setResizable(false);
    dlg.setIconifiable(false);
    dlg.setContent(content);
    dlg.getActions().addAll(Dialog.Actions.OK, Dialog.Actions.CANCEL);
    return dlg.show();
}

The corresponding FXML file check-dialog.fxml is the following:

<AnchorPane id="AnchorPane"  xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="ConfigUI">
  <children>
    <Label layoutX="29.0" layoutY="26.0" text="URL of Repository" />
    <Label layoutX="29.0" layoutY="76.0" text="Revision Interval" />
    <TextField fx:id="urlRepository" layoutY="23.0" prefWidth="200.0" AnchorPane.leftAnchor="170.0" AnchorPane.rightAnchor="10.0" />
    <Slider fx:id="revIntervalLow" layoutY="77.0" prefWidth="196.0" AnchorPane.leftAnchor="170.0" AnchorPane.rightAnchor="234.0" />
    ...
  </children>
</AnchorPane>

When I now start the dialog by the following code, the @FXML of TextField urlRepository does not work:

    public void configureActionTrigger(ActionEvent actionEvent) {
      ConfigUI ui = new ConfigUI();
      Action result = ui.showConfigDialog();
      ...
    }

In the debugger, I see that the attribute urlRepository is never bound. What do I am missing here? Is it necessary to have an application class and a controller class, and that the application class builds the UI, which then binds the controller?

Is there an example available on the internet that explains in a non-trivial example how ControlsFX and FXML files could be used together?

Answers


The line

content = FXMLLoader.load(getClass().getResource("check-dialog.fxml"));

will create new instance of ConfigUI class, so your current instance's urlRepository remains uninstantiated. Instead try as:

FXMLLoader loader = new FXMLLoader();
loader.setController(this);
content = (Parent) loader.load(getClass().getResourceAsStream("check-dialog.fxml"));

I found a working solution by the tip of Uluk Biy. Here is what has worked for me:

  1. Move the method showConfigDialog() to the caller.
  2. Get a reference to the dialog and the UI instance (to get values of the configuration from there later) and add that reference to the call.

Here are the changes to above:

Controller
  public void configureActionTrigger(ActionEvent actionEvent) {
    Dialog dlg = new Dialog(null, "Configuration Dialog for Check SVN");
    Action result = this.showConfigDialog(dlg);
    ...
  }

  protected Action showConfigDialog(Dialog dlg) throws IOException {
    Node content = content = FXMLLoader.load(getClass().getResource("check-dialog.fxml"));
    dlg.setResizable(false);
    dlg.setIconifiable(false);
    dlg.setContent(content);
    dlg.getActions().addAll(Dialog.Actions.OK, Dialog.Actions.CANCEL);

    return dlg.show();
}

ConfigUI
  @FXML
  TextField urlRepository;

No change was necessary to check-dialog.fxm.

Now the TextField is bound properly, and when I enter something in the text field, the value of that field changes as expected.

So the solution was to move the responsibility of building the UI for the configuration dialog to another class, and let the controller only handle the input.


Need Your Help

How do I extract child nodes from XML file using XPath when both child nodes must exist?

c# xpath xpathnavigator

I am trying to extract certain values from an xml document. In the example below, I want to store the values stored in the 'c' and 'd' nodes in a list, but only where the 'b' node contains both 'c'...

Is there a way to use function argument as a label in ggplot2?

r ggplot2

Quick question: if I want to run a function, such as plt.diff(dataset1), and in the output graph, I want the function to use the name "dataset1" as the y-axis label, how can this be done?