Рекомендуемый подход
Этот ответ перечисляет различные механизмы для передачи параметров в контроллеры FXML.
Для небольших приложений я настоятельно рекомендую передавать параметры непосредственно от вызывающей стороны к контроллеру - это просто, просто и не требует дополнительных платформ.
Для более крупных и сложных приложений было бы целесообразно выяснить, хотите ли вы использовать в своем приложении механизмы Dependency Injection или Event Bus .
Передача параметров напрямую от вызывающего к контроллеру
Передайте пользовательские данные в контроллер FXML, извлекая контроллер из экземпляра загрузчика FXML и вызывая метод на контроллере, чтобы инициализировать его необходимыми значениями данных.
Что-то вроде следующего кода:
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()
)
);
CustomerDialogController controller =
loader.<CustomerDialogController>getController();
controller.initData(customer);
stage.show();
return stage;
}
...
class CustomerDialogController {
@FXML private Label customerName;
void initialize() {}
void initData(Customer customer) {
customerName.setText(customer.getName());
}
}
Новый FXMLLoader строится , как показано в примере кода , т.е. new FXMLLoader(location)
. Расположение является URL-адресом, и вы можете создать такой URL-адрес из ресурса FXML:
new FXMLLoader(getClass().getResource("sample.fxml"));
Будьте осторожны, НЕ используйте функцию статической загрузки на FXMLLoader, иначе вы не сможете получить свой контроллер от экземпляра загрузчика.
Сами экземпляры FXMLLoader никогда ничего не знают об объектах домена. Вы непосредственно не передаете специфичные для приложения доменные объекты в конструктор FXMLLoader, вместо этого вы:
- Создайте FXMLLoader на основе разметки fxml в указанном месте
- Получить контроллер из экземпляра FXMLLoader.
- Вызовите методы на полученном контроллере, чтобы предоставить контроллеру ссылки на объекты домена.
Этот блог (другой автор) предоставляет альтернативный, но похожий пример .
Настройка контроллера на FXMLLoader
CustomerDialogController dialogController =
new CustomerDialogController(param1, param2);
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
loader.setController(dialogController);
Pane mainPane = (Pane) loader.load();
Вы можете создать новый контроллер в коде, передавая любые параметры из вызывающей программы в конструктор контроллера. Создав контроллер, вы можете установить его на экземпляр FXMLLoader, прежде чем вызывать метод load()
экземпляра .
Чтобы установить контроллер на загрузчик (в JavaFX 2.x), вы НЕ МОЖЕТЕ также определить fx:controller
атрибут в вашем файле fxml.
В связи с ограничением fx:controller
определения в FXML, я лично предпочитаю получать контроллер из FXMLLoader, а не устанавливать контроллер в FXMLLoader.
Наличие контроллера, получающего параметры из внешнего статического метода
Этот метод иллюстрируется ответом Сергея на Javafx 2.0 How-to Application.getParameters () в файле Controller.java .
Использовать инъекцию зависимостей
FXMLLoader поддерживает системы внедрения зависимостей, такие как Guice, Spring или Java EE CDI, позволяя вам установить фабрику пользовательских контроллеров на FXMLLoader. Это обеспечивает обратный вызов, который можно использовать для создания экземпляра контроллера с зависимыми значениями, введенными соответствующей системой внедрения зависимостей.
Пример внедрения приложения и контроллера JavaFX с помощью Spring приведен в ответе на:
Действительно хороший, чистый подход к внедрению зависимостей иллюстрируется фреймворком afterburner.fx с примером приложения air-hacks, которое его использует. afterburner.fx использует Jav6 javax.inject для выполнения внедрения зависимостей.
Используйте шину событий
Грег Браун (Greg Brown), создатель и разработчик оригинальной спецификации FXML, часто предлагает рассмотреть возможность использования шины событий, такой как Guava EventBus , для связи между экземплярами контроллера FXML и другой логикой приложения.
EventBus - это простой, но мощный API публикации / подписки с аннотациями, который позволяет POJO взаимодействовать друг с другом в любом месте JVM без необходимости ссылаться друг на друга.
Последующие вопросы и ответы
на первом методе, почему вы возвращаете этап? Этот метод также может быть аннулирован, потому что вы уже дали команду show (); как раз перед возвращением стадии ;. Как вы планируете использование, возвращая этап
Это функциональное решение проблемы. Этап возвращается из showCustomerDialog
функции, так что ссылка на него может быть сохранена внешним классом, который может захотеть что-то сделать, например скрыть этап на основе нажатия кнопки в главном окне, в более позднее время. Альтернативное объектно-ориентированное решение может инкапсулировать функциональность и ссылку на стадию в объекте CustomerDialog или иметь расширенную стадию CustomerDialog. Полный пример объектно-ориентированного интерфейса с настраиваемым диалоговым окном, инкапсулирующим данные FXML, контроллера и модели, выходит за рамки этого ответа, но может стать достойной записью в блоге для любого, кто хочет его создать.
Дополнительная информация предоставлена пользователем StackOverflow с именем @dzim
Пример для инъекции зависимостей весенней загрузки
На вопрос, как это сделать «The Spring Boot Way», шла дискуссия о JavaFX 2, на которую я ответил в прикрепленной постоянной ссылке. Этот подход все еще действителен и протестирован в марте 2016 года на Spring Boot v1.3.3.RELEASE:
https://stackoverflow.com/a/36310391/1281217
Иногда вы можете захотеть передать результаты обратно вызывающей стороне, и в этом случае вы можете проверить ответ на соответствующий вопрос: