我有一个耗时的方法,必须在按钮的操作上运行,并且当我运行该方法时,我希望UI仍然是活动的(即用户仍然可以与它交互)。我尝试了几种解决方案。一个是运行方法:
Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> label.setText(runConputation())); // takes a long time
但是这会在UI运行时锁定它。
另一种解决方案是使用单独的线程:
Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
label.setText(runConputation()); // takes a long time
}
});
thread.start();
});
但这会抛出一个IllegalStateException: not in javafx thread
或类似的东西。
我尝试添加Platform.runLater()
,因为我读到这将解决异常:
Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Platform.runLater(new Runnable() {
@Override
public void run() {
label.setText(runConputation()); // takes a long time
}
});
}
});
thread.start();
});
...但它会锁定UI。它看起来也很难看。
我也尝试使用Task
:
Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> {
Thread thread = new Thread(new Task<Void>() {
@Override
public Void call() throws Exception {
Platform.runLater(new Runnable() {
@Override
public void run() {
label.setText(runConputation()); // takes a long time
}
});
return null;
}
});
thread.start();
});
有类似的结果。
我想做类似的事情:
Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> {
Task<String> task = new Task<String>() {
@Override
public String call() throws Exception {
return runConputation();
}
};
Thread thread = new Thread(task);
thread.start();
// wait until thread is done
label.setText(task.getValue());
});
有办法做到这一点吗?