更新JavaFX界面并在继续之前强制等待的方法。

6

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

image

当前 创建新项目 按钮的行为如下所示:
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编程的新手,请耐心听我解释我的需求。

现在,我正在尝试添加一个小功能,即当按下“创建新项目”按钮时,在当前场景中会出现一个加载消息,我强制GUI等待几秒钟(以便用户有时间看到这个“加载”消息),然后继续进入下一个场景。加载消息可能会像这样。

image

我希望能够实现这个功能,因为在加载信息后加上等待提示会更加直观,从而提高用户使用程序的体验。我的初始尝试是做如下操作:
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();

我刚刚在这里读到,您永远不能让UI线程睡眠,因为它会冻结整个应用程序。因此,我一直在尝试上面链接中第一个答案提到的方法,即使用javafx.concurrent.Task,但是长时间尝试无果。

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

2个回答

11

不要让线程睡眠,使用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();
});

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


0

你应该尝试在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对话框随服务启动和停止。


你能为我详细解释一下吗?我认为这并不是我想要的,即在显示加载消息后强制等待一段时间。 - Hen
这个操作是在你当前的舞台上设置一个模态窗口,以便用户无法执行其他操作。在任务的call()方法中加载新视图/舞台/进程。如果您想要完全模态而不仅仅是舞台,请将initModality设置为Modality.APPLICATION_MODAL。如果您在主FX线程上执行逻辑,则UI将被阻塞。在call()方法中执行的任何操作都将在后台线程上发生,并且由于模态ProgressDialog而导致UI被阻塞。 - purring pigeon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接