当我从JavaFX视图提交时,我遇到了问题。提交时我想实现以下链:
我想这样做,因为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调用之前和之后的代码是否获得执行,并且它确实打印了loading
和finished
。标签设置为Done! Please hit 'Refresh'
,如果我以后不再覆盖它,它会将光标设置为cursor.WAIT
。
为什么API调用之前的代码似乎没有执行?或者让我们说给出视觉反馈?
答案 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将不会再次解锁,因为代码的那部分位于发生异常的块内。