Избегание короткого заикания в анимации при загрузке/отображении FXML

При загрузке в новый FXML и установке центра BorderPane существует кратковременное "замораживание" приложения, где существующая анимация, будь то на временной шкале или из gif в представлении изображения, остановится. Я использую этот код для изменения centerView:

 @FXML
    public void handleChangeView(ActionEvent event) {
        Task<Parent> loadTask = new Task<>() {
            @Override
            public Parent call() throws IOException {

                String changeButtonID = ((ToggleButton) event.getSource()).getId();
                Parent newOne = getFxmls().get(changeButtonID);

                if (newOne == null) {
                    FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/" + changeButtonID + ".fxml"));
                    newOne = loader.load();
                    getFxmls().put(changeButtonID, newOne);
                }
                return newOne ;
            }
        };

        loadTask.setOnSucceeded(e -> {
                    getMainUI().setCenter(loadTask.getValue());
        });

        loadTask.setOnFailed(e -> loadTask.getException().printStackTrace());

        Thread thread = new Thread(loadTask);
        thread.start();
    }

И хотя это делает работу по поддержанию пользовательского интерфейса в режиме загрузки, когда центральная ступень отображается в первый раз, появляется заметное отставание. Глядя на профиль процессора:

enter image description here

Я не уверен, что задержка происходит от выполняемой функции инициализации или загрузки элементов. Здесь gif программы, вы можете видеть видимую задержку:

enter image description here

Загружая его в VLC и перепрограммируя кадр за кадром, задержка выглядит как 5 или 6 кадров в формате 30 кадров в секунду, что означает около 200 мс задержки, что предполагает, что анимация замерзает более чем на 50 мс или около того. (Может быть, весь метод загрузки замораживает анимацию?)

Вопрос в том, можно ли сохранить анимацию гладкой во время этого?

//********* РЕДАКТИРОВАТЬ **********//

Поэтому я прошел проект и вырезал как можно больше методов и классов, сократив всю игру до 6 минимальных классов. У меня STILL есть задержка при нажатии кнопки символа (кнопка "вы"). С таким минимальным примером я проиграл тому, что может быть неправильно. Я загрузил это на Google Drive, чтобы кто-нибудь мог взглянуть.

https://drive.google.com/open?id=17A-PB2517bPJc8Dek-yp2wGXsjTyTj1d

Ответ 1

Нет ничего "неправильного" с вашим кодом (по крайней мере, в отношении этой проблемы).

Проблема, с которой вы столкнулись, также не связана с загрузкой FXML (что очень медленно, и вы правильно обработали FX-Thread).

Заикание происходит по следующим причинам:

  • относительная большая иерархия в character.fxml
  • много CSS (удалите main.css и вы заметите, заикание немного менее заметно)
  • динамическое изменение графика сцены (добавление/удаление узлов во время выполнения)

Каждый раз, когда вы заменяете center mainView на некоторый большой узел, это приводит к тому, что среда выполнения JavaFx полностью переформатируется и перестраивает (по крайней мере) этот узел. Это происходит на FX-Thread, поэтому вы заметили заикание.

Одним из возможных смягчений является классическая техника игрового дебюта: предварительное распределение в максимально возможной степени. Просто загрузите все необходимые FMXL один раз во время запуска и поместите их в график сцены. Затем в обработчиках кликов измените видимость или (Z-) позиции узлов, которые вы хотите отобразить/скрыть. Например, это хороший пример использования StackPane.

Я немного адаптировал ваш код, чтобы продемонстрировать, что я имею в виду: Prototype

Проверьте эти ресурсы, чтобы узнать больше: