代码之家  ›  专栏  ›  技术社区  ›  AlwaysNeedingHelp

加载/显示fxml时避免动画中出现短暂的停顿

  •  11
  • AlwaysNeedingHelp  · 技术社区  · 7 年前

    当加载到新的fxml中并设置边框窗格的中心时,应用程序会有一个简短的“冻结”,即现有动画(无论是来自时间线还是来自图像视图中的GIF)都将停止。我正在使用此代码更改CenterView:。

    fxml前的代码 public void handleChangeView(actionEvent事件){ 任务<父级>加载任务=新任务<>()。{ @覆盖 public parent call()引发IOException{ 字符串changeButtonID=(toggleButton)event.getSource().getID(); 父级newone=getfxmls().get(changeButtonID); 如果(newone==null){ fxml loader loader=new fxmlloader(getclass().getresource(“/view/”+changebuttonid+“.fxml”)); newone=loader.load(); getfxmls().put(changeButtonID,newOne); } 返回newone; } }(二) 加载任务.setOnSucceed(e->){ getMainUI().setCenter(loadtask.getValue()); })(二) loadtask.setonfailed(e->loadtask.getException().printstacktrace()); 线程线程=新线程(loadtask); thread.start(); }

    虽然这可以在加载时保持UI的响应,但是当中心阶段第一次显示时,会有一个明显的延迟。查看CPU配置文件:

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

    通过将其加载到VLC中并逐帧编程,延迟看起来是30 fps视频中的5或6帧,这意味着大约有200毫秒的延迟,这意味着动画冻结超过50毫秒左右的初始化方法。(也许整个加载方法会冻结动画?)

    问题是,在此期间是否可以保持动画平滑?

    //*********编辑**********//

    所以我完成了这个项目,尽可能地减少方法和类的数量,将整个游戏减少到6个最小类。我仍然有延迟按下字符按钮(“你”按钮)。有了这样一个小小的例子,我就迷路了。我已经把这个上传到谷歌驱动器上让任何人看一下。

    https://drive.google.com/open?id=17a-pb2517bpjc8dek-yp2wgxsjtytj1d

     @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配置文件:

    enter image description here

    我不确定延迟是来自正在运行的初始化函数,还是来自元素的加载。下面是程序的GIF,您可以看到可见延迟:

    enter image description here

    通过将其加载到VLC中并逐帧编程,延迟看起来是30 fps视频中的5或6帧,这意味着大约有200毫秒的延迟,这意味着动画冻结超过50毫秒左右的初始化方法。(也许整个加载方法会冻结动画?)

    问题是,在此期间是否可以保持动画平滑?

    //*********编辑**********//

    所以我完成了这个项目,尽可能地减少方法和类的数量,将整个游戏减少到6个最小类。我仍然有延迟按下字符按钮(“你”按钮)。有了这样一个小小的例子,我就迷路了。我已经把这个上传到谷歌驱动器上让任何人看一下。

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

    1 回复  |  直到 7 年前
        1
  •  2
  •   Oliver Jan Krylow    7 年前

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

    您遇到的问题也与加载fxml无关(fxml 非常慢 并且您已经正确地处理了fx线程)。

    结巴的原因如下:

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

    每次更换 center mainView 对于一些大型节点,它会导致JavaFX运行时完全重新布局并重新设计(至少)该节点的样式。这发生在fx线程上,因此您会注意到结巴。

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

    我稍微修改了您的代码,以演示我的意思: Prototype

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