JavaFX FXML Параметр, передаваемый из контроллера A в B и обратно

Я хочу создать основанный на контроллере JavaFX GUI, состоящий из нескольких контроллеров.

Задача, которую я не могу выполнить, - передать параметры из одной сцены в другую и обратно.

Или другими словами: MainController загружает fxml SubController, передает объект в SubController, переключает сцену. Там не должно быть двух открытых окон. После того, как работа завершена, SubController должен переключить сцену обратно на MainController и передать некоторый объект обратно. Это где я терплю неудачу.

Этот вопрос очень похож на этот, но остается без ответа. Передача параметров JavaFX FXML Также было упомянуто в комментариях:

"Это работает, когда вы передаете параметр от первого контроллера ко второму, но как передать параметр от второго к первому контроллеру, я имею в виду после загрузки first.fxml.

- Xlint Xms 18 сентября '17 в 23:15"

Я использовал первый подход в верхнем ответе этой темы.

Кто-нибудь знает, как этого добиться без внешних библиотек?

3 ответа

Есть множество способов сделать это.

Вот одно решение, которое передает Потребителя другому контроллеру. Другой контроллер может вызвать потребителя для принятия результата, как только он завершил свою работу. Пример основан на примере кода из ответа на вопрос, который вы связали.

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));
  }
}

Еще один способ сделать это - добавить свойство результата в контроллер диалогового окна, и заинтересованные лица могут прослушивать или получать свойство результата. Свойство результата - это то, как работают встроенные диалоги JavaFX, так что вы бы по сути подражали некоторым из этих функций.

Если у вас много чего происходит, то вам может помочь модель внедрения общих зависимостей, основанная на чем-то вроде Gluon Ignite.

Я использовал AfterBurner.fx для внедрения зависимостей, который очень приятный и мощный, если вы следуете соглашениям. Это не обязательно внешняя библиотека, если вы просто скопируете 3 класса в свою структуру. Хотя вам и нужна javax Inject jar, так что я думаю, что это вечная ссылка.

С другой стороны, если у вас есть центральный "экран", с которого разветвляется большая часть вашего приложения, вы можете использовать привязку свойств, вероятно, в рамках одноэлементного шаблона. Есть несколько хороших статей об использовании синглтона в JavaFX, как эта. Я сделал это для небольшого приложения, которое действительно отлично работает, но определение всех этих привязок может выйти из-под контроля, если свойств много.

Чтобы передать данные обратно, возможно, лучше всего запустить пользовательские события, на которые родительский контроллер подписывается с помощью Node::addEventHandler. Смотрите Как генерировать и обрабатывать пользовательские события? для контекста.

В сложных случаях, когда два контроллера не имеют ссылок друг на друга, шина событий, как упомянуто @jewelsea, является лучшим вариантом.

Для общей архитектуры этот комментарий Reddit предоставляет некоторые хорошие детали: https://www.reddit.com/r/java/comments/7c4vhv/are_there_any_canonical_javafx_design_patterns/dpnsedh/

Другие вопросы по тегам