据我了解,您需要更改call()
的{{1}}方法中的光标才能正确更改光标。但在我的应用程序中,我按下按钮并做了一些事情。在完成此操作之前,我不希望应用程序执行任何操作。我只想通过更改光标通知用户应用程序正在加载。
问题是如果我为任务启动一个单独的线程,程序的其余部分就不会等待该任务成功。如果我把它放在与应用程序相同的线程中(我想这就是我正在做的事情),通过执行Task
,光标不会改变。
按下按钮时调用的方法是void方法,因此可以防止我将return语句放在任务Platform.runLater(task)
方法中。
最佳方案是我能做到这一点:
setOnSucceeded()
或者只是创建一个任务并在当前线程中执行它,如下所示:
//app.getPrimaryStage() returns the application stage.
void method () throws InterruptedException {
app.getPrimaryStage().getScene().setCursor(Cursor.WAIT);
// Simulate execution of code that takes some time
Thread.sleep(3000);
app.getPrimaryStage().getScene().setCursor(Cursor.DEFAULT);
}
但这些方法都不起作用。我可以看到光标正在变化"在"下面通过执行此操作://app.getPrimaryStage() returns the application stage.
void method () throws InterruptedException {
Task<Void> task = new Task<Void>() {
protected Void call() {
app.getPrimaryStage().getScene().setCursor(Cursor.WAIT);
// Simulate execution of code that takes some time
Thread.sleep(3000);
app.getPrimaryStage().getScene().setCursor(Cursor.DEFAULT);
return null;
}
};
Platform.runLater(task);
}
但除非我在单独的线程中运行任务,否则更改不会显示。为什么是这样?什么是强制程序等待由单独线程运行的任务的最佳方法?
答案 0 :(得分:3)
您需要遵循两条关于JavaFX中多线程的规则:
通常,您应该使用Task
在后台线程上执行代码,即不在FX应用程序线程上执行代码。
您的代码块都违反了第二条规则:第一条规则是因为您直接在FX应用程序主题上调用了Thread.sleep(...)
。在第二个代码块中,您将该调用放在Task
中,然后使用Platform.runLater(...)
在FX应用程序线程上显式执行任务,这使得它(或多或少)等同于第一个块(即它使任务变得多余)。
你的基本前提是错误的:你不想&#34;阻止程序&#34;通过阻止FX应用程序线程的执行。这将使UI无响应并阻止任何UI更新(如更改光标)实际发生。你应该&#34;阻止程序&#34;通过禁用它(或它的一部分),并在任务完成时重新启用它。
所以你想要这样的东西:
void method() {
Scene scene = app.getPrimaryStage().getScene();
Task<Void> task = new Task<Void>() {
@Override
public void call() throws Exception {
// Simulate execution of code that takes some time
Thread.sleep(3000);
return null ;
}
};
task.setOnSucceeded(e -> {
scene.getRoot().setDisable(false);
scene.setCursor(Cursor.DEFAULT);
});
scene.getRoot().setDisable(true);
scene.setCursor(Cursor.WAIT);
Thread t = new Thread(task);
t.setDaemon(true);
t.start();
}