同步 textArea.clear() 后跟 textArea.setText() 不清除文本
Synchronous textArea.clear() followed by textArea.setText() does not clear text
单击按钮时,我想清除 textArea,做一些工作,然后在 textArea 中以相同的方法同步打印结果。
public void resetClicked(MouseEvent mouseEvent) {
textArea.clear();
String result = someSynchronousWork();
textArea.setText(result);
}
发生的情况是,textArea 已更新,但清除操作不可见。这项工作需要几秒钟。如果我注释掉除 textArea.clear()
之外的所有内容,它会起作用。
正如我在评论中提到的那样,JavaFX 直到 "pulse" 出现后才会渲染下一帧。当您清除文本,运行 一个 long-running 任务,然后在一个方法中全部设置文本时,不会发生这种情况;脉冲发生在所有这些发生之后,这意味着呈现的是新文本。此外,运行在 JavaFX 应用程序线程 上执行 several-seconds-long 任务也不是一个好主意。所有阻塞 and/or long-running 任务都应该在后台线程上完成——否则你的 GUI 会变得无响应(并且你的用户会变成 unhappy/nervous)。
如果此任务太简单而无法使用 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);
注意:这些示例将使用通用的 ForkJoinPool
执行 someSynchronousWork()
。您可以通过将 Executor
传递给 supplyAsync
.
来自定义它
注意:您可能希望在任务 运行 期间禁用某些 UI 组件(例如按钮)防止同时启动多个任务。任务完成后启用 UI 组件。
此外,您似乎在使用 Button
的 onMouseClicked
属性 来处理操作。考虑改用 onAction
属性; onAction
处理程序不仅会收到鼠标单击通知(例如,当按钮具有焦点并且 Space 或 Enter被按下)。
单击按钮时,我想清除 textArea,做一些工作,然后在 textArea 中以相同的方法同步打印结果。
public void resetClicked(MouseEvent mouseEvent) {
textArea.clear();
String result = someSynchronousWork();
textArea.setText(result);
}
发生的情况是,textArea 已更新,但清除操作不可见。这项工作需要几秒钟。如果我注释掉除 textArea.clear()
之外的所有内容,它会起作用。
正如我在评论中提到的那样,JavaFX 直到 "pulse" 出现后才会渲染下一帧。当您清除文本,运行 一个 long-running 任务,然后在一个方法中全部设置文本时,不会发生这种情况;脉冲发生在所有这些发生之后,这意味着呈现的是新文本。此外,运行在 JavaFX 应用程序线程 上执行 several-seconds-long 任务也不是一个好主意。所有阻塞 and/or long-running 任务都应该在后台线程上完成——否则你的 GUI 会变得无响应(并且你的用户会变成 unhappy/nervous)。
如果此任务太简单而无法使用 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);
注意:这些示例将使用通用的 ForkJoinPool
执行 someSynchronousWork()
。您可以通过将 Executor
传递给 supplyAsync
.
注意:您可能希望在任务 运行 期间禁用某些 UI 组件(例如按钮)防止同时启动多个任务。任务完成后启用 UI 组件。
此外,您似乎在使用 Button
的 onMouseClicked
属性 来处理操作。考虑改用 onAction
属性; onAction
处理程序不仅会收到鼠标单击通知(例如,当按钮具有焦点并且 Space 或 Enter被按下)。