在加载/显示FXML时避免动画短暂停顿

Alw*_*elp 11 java javafx javafx-8

当加载新的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();
    }
Run Code Online (Sandbox Code Playgroud)

虽然这确保了在加载时保持UI响应的工作,但是当中心舞台第一次显示时,存在明显的滞后.查看CPU配置文件:

在此输入图像描述

我不确定延迟是来自初始化函数运行还是加载元素.这是程序的GIF,你可以看到可见的延迟:

在此输入图像描述

通过在VLC中加载并逐帧进行,延迟在30 fps视频中看起来是5或6帧,这意味着大约200ms的延迟意味着动画冻结超过50ms左右的初始化方法.(也许整个加载方法会冻结动画?)

问题是,在这期间可以保持动画流畅吗?

//*********EDIT**********//

所以我经历了这个项目并尽可能多地删除了一些方法和类,将整个游戏减少到了6个最小的类.我仍然有按下字符按钮('你'按钮)的延迟.有了这样一个极小的例子,我迷失了可能是错的.我已将此上传到谷歌驱动器供任何人查看.

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

Oli*_*low 2

您的代码没有任何“错误”(至少就这个问题而言)。

您遇到的问题也与 FXML 的加载无关(加载速度非常慢,并且您已正确处理 FX-Thread)。

出现口吃的原因如下:

  • 相对较大的层次结构character.fxml
  • 很多CSS(删除main.css,你会注意到;口吃稍微不那么明显)
  • 动态更改场景图(在运行时添加/删除节点)

每次用某个大节点替换 时centermainView都会导致 JavaFx 运行时完全重新布局并重新设计(至少)该节点的样式。这种情况发生在 FX-Thread 上,因此您会注意到卡顿。

一种可能的缓解措施是经典的游戏开发技术:尽可能多地预分配。只需在启动期间加载所有必需的 FMXL 并将它们放入场景图中即可。然后,在单击处理程序中,更改要显示/隐藏的节点的可见性或 (Z-) 位置。StackPane例如,这是一个很好的用例。

我对您的代码进行了一些修改以演示我的意思: 原型

查看这些资源以了解更多信息: