java - 加载/显示 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();
}
虽然这可以在加载时保持 UI 响应,但当中心舞台第一次显示时,会有明显的延迟。查看 CPU 配置文件:
我不确定延迟是来自初始化函数的运行还是元素的加载。这是程序的 gif,您可以看到可见的延迟:
通过在 VLC 中加载并逐帧进行,延迟看起来是 30 fps 视频中的 5 或 6 帧,这意味着大约 200 毫秒的延迟,这意味着动画冻结超过 50 毫秒左右的初始化方法。(也许整个加载方法会冻结动画?)
问题是,在此期间是否可以保持动画流畅?
//********* 编辑 **********//
所以我通过这个项目,尽可能多地删减方法和类,将整个游戏减少到 6 个最小类。我仍然有按下字符按钮(“你”按钮)的延迟。有了这样一个最小的例子,我迷失了可能出错的地方。我已将其上传到谷歌驱动器供任何人查看。
https://drive.google.com/open?id=17A-PB2517bPJc8Dek-yp2wGXsjTyTj1d
解决方案
您的代码没有任何“错误”(至少在这个问题上)。
您遇到的问题也与 FXML 的加载无关(这很慢,您已经正确处理了 FX-Thread)。
出现口吃的原因如下:
- 相对较大的层次结构
character.fxml
- 大量的 CSS(删除
main.css
你会注意到;口吃稍微不那么突出) - 动态改变场景图(在运行时添加/删除节点)
每次用一些大节点替换 的center
时mainView
,都会导致 JavaFx 运行时完全重新布局和重新设置(至少)该节点的样式。这发生在 FX 线程上,因此您会注意到口吃。
一种可能的缓解措施是一种经典的游戏开发技术:尽可能多地预先分配。只需在启动期间加载所有必要的 FMXL 并将它们放入场景图中。然后在您的点击处理程序中,更改要显示/隐藏的节点的可见性或(Z-)位置。例如,这是一个很好的用StackPane
例。
我稍微修改了您的代码以说明我的意思: 原型
查看这些资源以了解更多信息:
推荐阅读
- ios - 无法以编程方式实例化初始视图控制器
- php - PHP 在 Docker 中找不到 MySQL 服务器
- mongodb - 将 mongodb 模型连接到 apollo-server 2.0
- parsing - antlr4 匹配选择表达式
- python - timedelta - 从字符串传递 'days=-5' 的最优雅方式
- google-sheets - 在查询 Importrange 函数中使用 OR 语句?
- reactjs - 反应路由器重定向到根空白页面
- sitemap - robots.txt 文件中的动态站点地图网址
- mysql - Varchar 上的 MySQL MAX 和 MIN
- javascript - 在javascript中创建一个以相反顺序返回数组和元素的函数