azerphoenix
@azerphoenix
Java Software Engineer

Как устранить проблему в Spring Boot + JavaFX?

Доброго времени суток!
Постараюсь максимально кратко описать проблему.
Использую связку Spring Boot + JavaFX для создания небольшого десктопного приложения.
Пример интеграции JavaFX + Spring + Spring Security взял отсюда -
https://github.com/emorgado/javafx-springboot-spri...

Итак, собственно сама проблема:
1) По клику на пункте меню открывается новое окно.
@FXML
public void addNewPatientMenu(ActionEvent event) {

        try {

            Stage newPatientStage = new Stage();
            newPatientStage.setTitle("Добавить нового пациента");
            PatientController patientController = applicationContext.getBean(PatientController.class);
            Scene newPatientScene = new Scene(patientController.getView());
            newPatientStage.setScene(newPatientScene);
            newPatientStage.setMaximized(true);
            newPatientStage.showAndWait();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

Если нажать на кнопку "Отмена", то срабатывает следующий код и окно закрывается.
@FXML
    public void cancelPatientButtonAction(ActionEvent event) {
        Stage stage = (Stage) cancelPatientButton.getScene().getWindow();
        stage.close();
    }


При попытке повторного открытия - Исключение:
IllegalArgumentException: AnchorPane is already set as root of another scene

И соответственно, указанное выше окно при повторном обращении не открывается. Прогуглил и глянул на stackoverflow, там есть решение проблемы, но почему-то вместе с Spring Security не удается все это дело "подружить".

Как устранить данную проблему? При надобности могу предоставить доступ к самому проекту на GitHub (а лучше на BitBucket).

Заранее благодарен!

P.S. Тут какой нюанс...
Сама ошибка возникает по следующей причине:
The exception is pretty self-explanatory: the anchor pane cannot be the root of two different scenes. Instead of creating a new scene every time, just replace the root of the existing scene:

https://stackoverflow.com/questions/46328192/javaf...

Но в данном случае Parent root он получает из следующего контроллера, как и указано в проекте на github (по ссылке выше)

public class FXMLController {

    Logger log = LoggerFactory.getLogger(FXMLController.class);

    private static String prefix = "Controller";

    private Parent root;

    public Parent load() throws IOException {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource(getFxmlName()));
        loader.setControllerFactory(clz -> this);
        return loader.load();
    }

    private String getFxmlName(){
        String name = this.getClass().getSimpleName();
        name = name.replaceAll("\\.", "/");
        if(name.endsWith(prefix)){
            name = name.substring(0, name.lastIndexOf(prefix));
        }
        return String.format("/fxml/%s.fxml", name).toLowerCase();
    }

    public Parent getView() throws IOException{
        if(root == null){
            root = load();
        }
        return root;
    }
}
  • Вопрос задан
  • 104 просмотра
Решения вопроса 1
@Cheypnow
При первом вызове
Scene newPatientScene = new Scene(patientController.getView());
создается root, который при следующем вызове будет использован повторно.
Поэтому и ошибка
AnchorPane is already set as root of another scene
- один и тот же root используется для двух сцен.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы