API调用似乎阻止了JavaFX代码

时间:2015-12-14 09:41:43

标签: java events javafx

当我从JavaFX视图提交时,我遇到了问题。提交时我想实现以下链:

  1. 将光标更改为等待符号
  2. 设置标签文字'loading ...'
  3. 进行API调用
  4. 将标签文字设置为“已完成,请点击刷新”
  5. 将光标设置回默认值
  6. 我想这样做,因为API调用会锁定(web-)视图的其余部分,我不希望用户点击并导致程序崩溃。我编写了这段代码来实现我上面描述的事件链

    Button submit = new Button();
    submit.setPadding(new Insets(5));
    submit.setText("Submit");
    submit.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            try {
                scene.setCursor(Cursor.WAIT);
                label.setText("loading...");
                System.out.println("loading");
                model.newRootNode(searchIndividual.getText(), Integer.valueOf(numberField.getText()));
                // This makes the API call
                System.out.println("finished");
                label.setText("Done! Please hit \'Refresh\'");
                scene.setCursor(Cursor.DEFAULT);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    vbox.getChildren().add(submit);
    

    使用eclipse调试器我无法使标签文本更改可见,但光标似乎有效。此外,我使用sysouts()来检查API调用之前和之后的代码是否获得执行,并且它确实打印了loadingfinished。标签设置为Done! Please hit 'Refresh',如果我以后不再覆盖它,它会将光标设置为cursor.WAIT
    为什么API调用之前的代码似乎没有执行?或者让我们说给出视觉反馈?

1 个答案:

答案 0 :(得分:2)

从ui线程调用事件处理程序,在更改ui内容后,该线程无法自由刷新场景。在不同的线程上执行长时间运行的操作,并让ui线程继续完成它的工作来解决这个问题。您可以简单地使用Platform.runLater从您开始使用的非ui线程中更改ui,或使用Task来完成这样的工作:

Task<Void> task = new Task<Void>() {
    @Override
    protected Void call() throws Exception {
        // makes the long-running API call
        return null;
    }
};
task.setOnRunning((WorkerStateEvent event) -> {
    // disable ui
});

task.setOnCancelled((WorkerStateEvent event) -> {
    // reenable ui
    // handle cancel
});
task.setOnSucceeded((WorkerStateEvent event) -> {
    // reenable ui
    // handle succeed
});

task.setOnFailed((WorkerStateEvent event) -> {
    // reenable ui
    // handle failed task e.g.:
    System.err.println("Oops, Error:");
    task.getException().printStackTrace(System.err);
});

Thread t = new Thread(task);
// thread shouldn't prevent program shutdown
t.setDaemon(true);
t.start();

另请注意,处理异常的方式如果抛出异常,ui将不会再次解锁,因为代码的那部分位于发生异常的块内。