JavaFX FXML Parameter passing from Controller A to

2019-05-19 13:43发布

I want to create a controller based JavaFX GUI consisting of multiple controllers.

The task I can't accomplish is to pass parameters from one Scene to another AND back.

Or in other words: The MainController loads SubController's fxml, passes an object to SubController, switches the scene. There shall not be two open windows. After it's work is done, the SubController shall then switch the scene back to the MainController and pass some object back. This is where I fail.

This question is very similar to this one but still unanswered. Passing Parameters JavaFX FXML It was also mentioned in the comments:

"This work when you pass parameter from first controller to second but how to pass parameter from second to first controller,i mean after first.fxml was loaded.

– Xlint Xms Sep 18 '17 at 23:15"

I used the first approach in the top answer of that thread.

Does anyone have a clue how to achieve this without external libs?

3条回答
Ridiculous、
2楼-- · 2019-05-19 14:10

I've used AfterBurner.fx for dependency injection, which is very slick and powerful as long as you follow the conventions. It's not necessarily an external lib if you just copy the 3 classes into your structure. Although you do need the javax Inject jar, so I guess it is an eternal reference.

Alternately, if you have a central "screen" from which most of your application branches out you could use property binding probably within a singleton pattern. There are some good articles on using singleton in JavaFX, like this one. I did that for a small application that works really great, but defining all of those bindings can get out of hand if there are a lot of properties.

查看更多
等我变得足够好
3楼-- · 2019-05-19 14:24

There are numerous ways to do this.

Here is one solution, which passes a Consumer to another controller. The other controller can invoke the consumer to accept the result once it has completed its work. The sample is based on the example code from an answer to the question that you linked.

public Stage showCustomerDialog(Customer customer) {
  FXMLLoader loader = new FXMLLoader(
    getClass().getResource(
      "customerDialog.fxml"
    )
  );

  Stage stage = new Stage(StageStyle.DECORATED);
  stage.setScene(
    new Scene(
      (Pane) loader.load()
    )
  );

  Consumer<CustomerInteractionResult> onComplete = result -> {
    // update main screen based upon result.
  };
  CustomerDialogController controller = 
    loader.<CustomerDialogController>getController();
  controller.initData(customer, onComplete);

  stage.show();

  return stage;
}

...

class CustomerDialogController() {
  @FXML private Label customerName;
  private Consumer<CustomerInteractionResult> onComplete
  void initialize() {}
  void initData(Customer customer, Consumer<CustomerInteractionResult> onComplete) {
    customerName.setText(customer.getName());
    this.onComplete = onComplete;
  }

  @FXML
  void onSomeInteractionLikeCloseDialog(ActionEvent event) {
    onComplete.accept(new CustomerInteractionResult(someDataGatheredByDialog));
  }
}

Another way to do this is to add a result property to the controller of the dialog screen and interested invokers could listen to or retrieve the result property. A result property is how the in-built JavaFX dialogs work, so you would be essentially imitating some of that functionality.

If you have a lot of this passing back and forth stuff going on, a shared dependency injection model based on something like Gluon Ignite, might assist you.

查看更多
聊天终结者
4楼-- · 2019-05-19 14:28

To pass data back, the best approach is probably to fire custom Events, which the parent controller subscribes to with Node::addEventHandler. See How to emit and handle custom events? for context.

In complex cases when the two controllers have no reference to each other, a Event Bus as @jewelsea mentioned is the superior option.

For overall architecture, this Reddit comment provides some good detail: https://www.reddit.com/r/java/comments/7c4vhv/are_there_any_canonical_javafx_design_patterns/dpnsedh/

查看更多
登录 后发表回答