Избегание короткого заикания в анимации при загрузке/отображении 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();
}
И хотя это делает работу по поддержанию пользовательского интерфейса в режиме загрузки, когда центральная ступень отображается в первый раз, появляется заметное отставание. Глядя на профиль процессора:
Я не уверен, что задержка происходит от выполняемой функции инициализации или загрузки элементов. Здесь gif программы, вы можете видеть видимую задержку:
Загружая его в 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
Проверьте эти ресурсы, чтобы узнать больше: