【问题标题】:Updating your UI and forcibly waiting before continuing JavaFX在继续 JavaFX 之前更新您的 UI 并强制等待
【发布时间】:2016-05-24 00:22:02
【问题描述】:

我在这里展示我的欢迎场景的图像。

创建新项目按钮的当前行为如下所示:

Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
stage.hide();
Parent root = FXMLLoader.load(getClass().getResource("/view/scene/configure/NewProjectConfigureScene.fxml"));
Scene scene = new Scene(root);
stage.setTitle("Configure New Project Settings");
stage.setScene(scene);
stage.show();

用文字来解释:按钮被按下 -> 我得到舞台 -> 隐藏当前场景 -> 切换舞台以拥有新场景 -> 重新显示舞台。此行为有效。

我是 GUI 编程新手,所以请耐心等待我解释我需要什么。

我现在正在尝试添加一个小功能,当按下 Create New Project 按钮时,当前场景中会出现一条加载消息,我强制 GUI 等待几秒钟(所以用户有时间在继续下一个场景之前看到这个“加载”消息)。加载消息看起来像这样。

我真的很想实现这个功能,因为加载消息后等待可能更直观,从而改善我在使用程序时的用户体验。

我最初的尝试是做以下事情:

statusText.setText("Please wait..."); // statusText is the "loading message"
Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
try {
    Thread.sleep(2000);                
} catch(InterruptedException ex) {
    Thread.currentThread().interrupt();
}
stage.hide();

Parent root = FXMLLoader.load(getClass().getResource("/view/scene/configure/NewProjectConfigureScene.fxml"));
Scene scene = new Scene(root);
stage.setTitle("Configure New Project Settings");
stage.setScene(scene);
stage.show();

我刚刚读到here,你永远不能让 UI 线程休眠,因为它会冻结整个应用程序。所以我一直在尝试上面链接的第一个答案中提到的方法,它说使用javafx.concurrent.Task,但是我已经尝试了很长时间无济于事。

如何更新UI,强制等待几秒,然后显示新场景?

【问题讨论】:

    标签: java multithreading javafx


    【解决方案1】:

    不要让线程休眠,而是使用PauseTransition 并在暂停结束后加载新场景。

    createNewProject.setOnAction(event -> {
        statusText.setText("Please wait...");
        PauseTransition pause = new PauseTransition(
            Duration.seconds(1),
        );
        pause.setOnFinished(event -> {
            Parent root = FXMLLoader.load(
                getClass().getResource(
                    "/view/scene/configure/NewProjectConfigureScene.fxml"
                )
            );
            Scene scene = new Scene(root);
            stage.setTitle("Configure New Project Settings");
            stage.setScene(scene);
            stage.sizeToScene();    
        });
        pause.play();
    });
    

    以上代码假设您只有一个阶段,因此您调整“欢迎”阶段的大小以成为“配置新项目设置”阶段。

    【讨论】:

    • 非常感谢......我想这就是我想要的。 (现在尝试),只是我使用了场景生成器,我对 lambda 表达式语法并不熟悉 ->。我现在就去读一读。
    【解决方案2】:

    您应该尝试在 ControlsFX 中添加这将有所帮助。

    您可以执行以下操作:

       Service<T> service = new Service<T>(){
           @Override
           protected Task<T> createTask() {
           return new Task<T>() {
              @Override
              protected T call() throws Exception {
            //Do your processing here.                      }
              };
          }
        };
        service.setOnSucceeded(event -> {//do your processing});
        service.setOnFailed(event -> {//do your processing});              
        ProgressDialog pd = new ProgressDialog(service);
        pd.setContentText("Please wait while the window loads...");
        pd.initModality(Modality.WINDOW_MODAL);
        pd.initOwner(stage);
        service.start();
    

    这会将您的代码放在后台线程上。 ControlsFX 对话框随服务启动和停止。

    【讨论】:

    • 你能详细说明一下吗?我认为这不是我想要的..这是在显示加载消息后强制等待一段时间。
    • 这样做是在您当前阶段的顶部设置一个 MODAL 窗口,以便用户无法执行任何其他操作。您将在任务的 call() 方法中加载新的视图/阶段/进程。如果您想要完全模态而不只是阶段,请将 initModality 设置为 Modality.APPLICATION_MODAL。如果您在主 FX 线程上执行逻辑,则 UI 将阻塞。在 call() 方法中所做的任何事情都将在后台线程上发生,并且 UI 由于模态 ProgressDialog 而被阻塞。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多