我有一个简单的JavaFX GUI,可在单击按钮时触发后台任务。此任务使用其最新的进度消息连续更新TextArea。我已经在下面演示了如何解决此问题。当任务出错时会出现问题,并且需要用户决定如何进行。我的目标是通过用户选择“是”或“否”的警报来做出此决定。不过,我一直无法实现此功能。到目前为止,这是我尝试过的事情:
谢谢您的帮助!
使用EventHandler创建按钮:
private Button createButton() { Button btn = new Button(); btn.setText("Run"); btn.setPrefWidth(100); EventHandler<ActionEvent> buildWindow = new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { TextArea output = buildCenterTextArea(); Task task = new Task<Void>() { @Override public Void call() { callScript(output); // Calls script return null; } }; new Thread(task).start(); } }; btn.setOnAction(buildWindow); return btn; } private void buildCenterTextArea() { // Builds a text area which the script updates with status TextArea output = new TextArea(); output.setEditable(false); this.borderpane.setCenter(output); return output }
在我的脚本中,通过执行以下操作更新文本:
output.setText(statusText+ "\n" + newStatus);
后台线程可以保持忙碌等待。这意味着您可以创建一个CompletableFuture,用于Platform.runLater创建警报并使用showAndWait将其显示,然后用结果填充未来。在后台线程上的此调用之后,使用来等待结果Future.get。
CompletableFuture
Platform.runLater
Future.get
以下示例生成0到9(含)之间的随机数,并在上打印0-8 TextArea。9是模拟错误,并且询问用户是否应该继续执行任务。
TextArea
9
@Override public void start(Stage stage) throws IOException { TextArea ta = new TextArea(); Thread thread = new Thread(() -> { Random rand = new Random(); while (true) { int i = rand.nextInt(10); if (i == 9) { CompletableFuture<ButtonType> future = new CompletableFuture<>(); // ask for user input Platform.runLater(() -> { Alert alert = new Alert(AlertType.CONFIRMATION); alert.setContentText("An error occured. Continue?"); future.complete(alert.showAndWait().orElse(ButtonType.CANCEL)); // publish result }); try { if (future.get() == ButtonType.CANCEL) { // wait for user input on background thread break; } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); break; } } else { Platform.runLater(() ->ta.appendText(Integer.toString(i) + "\n")); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); break; } } } }); thread.setDaemon(true); thread.start(); Scene scene = new Scene(new VBox(ta)); stage.setScene(scene); stage.show(); }