0

I have a gui built with javafx the controllers are loaded from fxml and created as Beans with spring so I can access my model. But that is predefined in fxml and loaded at start. Now I would like to load components, defined in fxml at runtime, but I could not yet find a working example, and no matter how I try it doesn't work.

So my question:

  • How can I create a custom Dialog (or any custom component) in runtime , that is loaded from .fxml and is aware of (Spring application) context?

Edit

So it loads but some fields are not initialized. This is my custom DialogPane,

@Controller
@Scope("prototype")
public class NewProgramDialogPane extends DialogPane implements Initializable {
public static final ButtonType buttonTypeOk = new ButtonType("Create", ButtonBar.ButtonData.OK_DONE);
public static final ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);

public TextField nameField;
public TextField data1Field;
public TextField data2Field;
public RegexValidator requiredField1;
public RequiredField requiredField2;
public RequiredField requiredField3;
public ErrorLabel duplicateProjectErrorLabel;

private SimpleBooleanProperty match = new SimpleBooleanProperty(false);

@Autowired
MainService mainService;

public NewProgramDialogPane() {
    URL url = getClass().getClassLoader().getResource("com/akos/fxml/NewProgramDialog.fxml");
    FXMLLoader loader = new FXMLLoader();
    loader.setLocation(url);
    loader.setRoot(this);
    try {
        loader.load();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void initialize(URL location, ResourceBundle resources) {
    this.lookupButton(buttonTypeOk).addEventHandler(ActionEvent.ACTION, event -> {
        if (!validate()) {
            event.consume();
        }
    });
    duplicateProjectErrorLabel.visibleProperty().bind(match);
}

public boolean validate() {
    requiredField1.eval();
    requiredField2.eval();
    requiredField3.eval();

    match.set(mainService.getPrograms().stream().anyMatch(
            program -> program != null && program.getName().equals(nameField.getText())));

    return !match.get() &&
            !requiredField1.getHasErrors() &&
            !requiredField2.getHasErrors() &&
            !requiredField3.getHasErrors();
}
}

And when I try to read the nameField, it is null.

public class NewProgramDialog extends Dialog<Program> {

public NewProgramDialog() {
    this.setDialogPane(new NewProgramDialogPane());
    this.setTitle("New program");
    this.initModality(Modality.APPLICATION_MODAL);
    this.initStyle(StageStyle.DECORATED);

    this.setResultConverter(param -> {
        if (param == NewProgramDialogPane.buttonTypeOk) {
            int x = 0;
            return new Program(((NewProgramDialogPane) getDialogPane()).nameField.getText());
        }
        return null;
    });
}
}
4
  • You omitted loader.setController(this); Commented Apr 1, 2016 at 23:51
  • Yeah. I have missed that. Thank you for spotting it. Commented Apr 2, 2016 at 2:13
  • After fixing that, and the switching the button action to addEventFIlter, in the validation, the mainService is still null. Commented Apr 2, 2016 at 2:21
  • You are creating the NewProgramDialogPane explicitly, instead of letting Spring instantiate it for you. Make the NewProgramDialogPane a spring-managed bean, and inject it into the NewProgramDialog. Combining two different frameworks like this is tricky; you may want to just spend some time understanding Spring on its own first. Commented Apr 2, 2016 at 2:57

1 Answer 1

1

Define your custom dialog using the custom component FXML pattern; then just expose the custom component as a (prototype-scoped) spring bean.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.