Question

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?

Was it helpful?

Solution 2

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.

OTHER TIPS

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"));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top