同步textArea.clear()后跟textArea.setText()不会清除文本

时间:2019-06-21 17:20:42

标签: java textarea java-11 javafx-11

单击按钮时,我想清除textArea,做一些工作,然后以相同的方法同步地在textArea中打印结果。

public void resetClicked(MouseEvent mouseEvent) {
    textArea.clear();
    String result = someSynchronousWork();
    textArea.setText(result);
}

发生的是,textArea已更新,但是清除操作不可见。这项工作需要几秒钟。如果我注释掉textArea.clear()以外的所有内容,则可以正常工作。

1 个答案:

答案 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 时)。