单击按钮时,我想清除textArea,做一些工作,然后以相同的方法同步地在textArea中打印结果。
public void resetClicked(MouseEvent mouseEvent) {
textArea.clear();
String result = someSynchronousWork();
textArea.setText(result);
}
发生的是,textArea已更新,但是清除操作不可见。这项工作需要几秒钟。如果我注释掉textArea.clear()
以外的所有内容,则可以正常工作。
答案 0 :(得分:2)
正如我在评论中提到的,JavaFX不会渲染下一帧,直到"pulse"出现为止。当您清除文本,运行长时间运行的任务然后以一种方法全部设置文本时,不会发生这种情况。脉冲在所有这些发生之后发生,这意味着渲染的是新文本。另外,在 JavaFX Application Thread 上运行几秒钟的任务也不是一个好主意。所有阻塞和/或长时间运行的任务都应在后台线程上完成-否则您的GUI会变得无响应(并且用户会变得不高兴/紧张)。
如果此任务太简单而不能使用Task
,那么您可以尝试使用CompletableFuture
,这可以使您更轻松地异步调用简单的事物。
public void resetClicked(MouseEvent event) {
event.consume();
textArea.clear();
CompletableFuture.supplyAsync(this::someSynchronousWork)
.whenCompleteAsync((result, error) -> {
if (error != null) {
// notify user
} else {
textArea.setText(result);
}
}, Platform::runLater);
}
根据您要如何处理错误,您可以执行不同的操作。例如:
// can't ever be an error
supplyAsync(this::someSynchronousWork)
.thenAcceptAsync(textArea::setText, Platform::runLater);
// just want to show "Error" in text area on error
supplyAsync(this::someSynchronousWork)
.exceptionally(error -> "ERROR")
.thenAcceptAsync(textArea::setText, Platform::runLater);
注意::这些示例将使用通用的someSynchronousWork()
执行ForkJoinPool
。您可以通过将Executor
传递到supplyAsync
来对此进行自定义。
注意:您可能希望在任务运行时禁用某些UI组件(例如按钮),以防止一次启动多个任务。任务完成后启用UI组件。
此外,您似乎正在使用onMouseClicked
的{{1}}属性来处理操作。考虑改为使用Button
属性;不仅会向onAction
处理程序发出通知,而不仅仅是单击鼠标(例如,当按钮具有焦点并按下 Space 或 Enter 时)。