Я разрабатываю приложение GUI с использованием Java8 и JavaFX. В главном окне есть кнопка, которая должна открыть новое окно (с собственным fxml). До сих пор я загружал fxml каждый раз, когда была нажата кнопка, но поскольку новое окно имеет множество элементов управления, это (удивительно) занимает некоторое время (aprox 0.5-1s), чтобы открыть всплывающее окно, и, таким образом, я изменил код так что главный контроллер загружает popup fxml в его метод инициализации, и всякий раз, когда нажимается кнопка, отображается только предварительно загруженное окно. Все работает хорошо, но теперь я не могу установить initOwner (...) в новом окне, так как у меня нет доступа к объекту window в методе initilize. Я знаю, что мне не нужно устанавливать initOwner, но тогда у меня есть два окна приложений в меню «Пуск» (чего я хочу избежать). Есть идеи, как обойти эту проблему? Также, как стандартный способ отображения новых окон/диалогов в JavaFX, должен ли я загружать fxml каждый раз, когда происходит событие, или просто показывать/скрывать предварительно загруженный?Как инициализировать диалоговое окно во вложенном контроллере
ответ
Вы можете загрузить FXML один раз в методе initialize()
, затем лениво инициализировать диалоговое окно, когда оно вам понадобится. То есть
public class Controller {
private Parent dialogPane ;
private Stage dialog ;
@FXML
private Button button ;
public void initialize() throws IOException {
dialogPane = FXMLLoader.load(getClass().getResource("dialog.fxml"));
}
@FXML
private void handleButtonPress() {
getDialog().show();
}
private Stage getDialog() {
if (dialog == null) {
Scene scene = new Scene(dialogPane);
dialog = new Stage();
dialog.setScene(scene);
dialog.initOwner(button.getScene().getWindow());
}
return dialog ;
}
}
Вы можете лениво загрузить файл fxml. А именно не тогда, когда приложение запускается или не на каждое нажатие кнопки, но при запросе:
private Parent popupPane;
private PopupPaneController popupPaneController;
private void openPopup(ActionEvent event) {
if (popupPane == null) {
popupPane = FXMLLoader.load(...);
popupPaneController = // get it from FXMLLoader. Search this site for how
}
popupPaneController.updatePopupContent(newVals);
Stage popup = new Stage();
popup.initOwner(primaryStage);
stage.setScene(new ScrollPane(popupPane));
stage.show();
}
Обратите внимание, что если вы кэшировать содержимое всплывающего окна, вы можете установить initOwner()
позже. Также проверьте класс Alert в качестве альтернативы всплывающему окну. См. examples of it.
Показывая предварительно загруженную сцену/окно, вам может потребоваться обновить данные, отображаемые во всплывающем окне. для этого выполните метод updatePopupContent(newVals)
в классе контроллера всплывающего окна и вызовите его при каждом нажатии кнопки, как в приведенном выше коде.
Я думаю, что это хороший подход, но является ли это правильным? Я имею в виду, что лучше всего загружать FXML один раз, а не каждый раз, когда нажимается кнопка, верно? – Stugal