java - 等待任务完成而不阻塞 javafx 中的 UI

标签 java multithreading asynchronous javafx ui-thread

我正在尝试使用 JavaFX 创建一个测验应用程序,因为我正在使用调用问题

Q1.invoke();
Q2.invoke();

这些问题将显示在 UI 线程上

public void display(McqQuestion mcqQuestion) {
        resourceAsStream  = getClass().getResourceAsStream("/mcqview.fxml");
        fxmlLoader = new FXMLLoader();
        if (executorService==null) executorService =Executors.newSingleThreadExecutor();
        Parent root = null;
        try {
            root = fxmlLoader.load(resourceAsStream);
            Mcqview controller = fxmlLoader.getController();
            controller.setAnswer1(mcqQuestion.getAnswers().get(0));
            //controller class has setters to accept question properties.
            controller.multipleChoiceQuestionType = this;
            this.view.getBorderPane().setCenter(root);
}

一旦显示问题,我需要等待直到得到答案,如果没有得到答案,则应该调用下一个问题。所以我在显示方法中引入了一个线程来等待超时

submit = executorService.submit(() -> {
             try {
                    TimeUnit.SECONDS.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
             });

            try {
                submit.get(20,TimeUnit.SECONDS);
                System.out.println("waiting finished");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

由于 future.get(); 是一个阻塞调用,它也会阻塞 UI 线程,因此如何在不阻塞 UI 线程的情况下实现此目的。

最佳答案

不要为此目的使用单独的线程。这只会让事情变得更加困难。 JavaFX 提供了等待方式,不需要您担心并发问题。

在这种情况下,可以通过 PauseTransitiononFinished 处理程序来完成等待。处理来自用户输入的事件处理程序的答案。

private static class Question {

    private final String questionText;
    private final String answers[];
    private final int correctAnswerIndex;

    public Question(String questionText, String[] answers, int correctAnswerIndex) {
        if (answers.length != 3) {
            // for simplicity's sake allow only exactly 3 answers
            throw new IllegalArgumentException();
        }
        this.questionText = questionText;
        this.answers = answers;
        this.correctAnswerIndex = correctAnswerIndex;
    }

}

private VBox questionPane;
private Label questionText;
private Button[] answerButtons;
private PauseTransition pauseTransition;
private Question currentQuestion;

private void answer(int index) {
    pauseTransition.stop(); // no longer wait for timeout
    Alert alert = new Alert(Alert.AlertType.INFORMATION);
    alert.setContentText((index == currentQuestion.correctAnswerIndex)
            ? "correct answer"
            : "incorrect answer");

    // show result and exit
    alert.showAndWait();
    Platform.exit();
}

private void ask(Question question) {
    questionText.setText(question.questionText);
    for (int i = 0; i < 3; i++) {
        answerButtons[i].setText(question.answers[i]);
    }
    currentQuestion = question;
    pauseTransition.playFromStart(); // start timeout timer
}

private void timeout() {
    pauseTransition.stop();
    Alert alert = new Alert(Alert.AlertType.INFORMATION);
    alert.setContentText("your time ran out");

    // cannot use showAndWait form animation directly
    Platform.runLater(() -> {
        // show result and exit
        alert.showAndWait();
        Platform.exit();
    });
}

@Override
public void start(Stage stage) {
    pauseTransition = new PauseTransition(Duration.seconds(10));
    pauseTransition.setOnFinished(evt -> timeout());

    questionText = new Label();
    questionText.setWrapText(true);

    questionPane = new VBox(questionText);
    questionPane.setPrefSize(400, 400);
    answerButtons = new Button[3];

    for (int i = 0; i < 3; i++) {
        final int answerIndex = i;
        Button button = new Button();
        button.setOnAction(evt -> answer(answerIndex));
        answerButtons[i] = button;
        questionPane.getChildren().add(button);
    }

    Scene scene = new Scene(questionPane);

    stage.setScene(scene);
    stage.show();

    Question question = new Question(
            "What is the answer to the ultimate question of life, the universe, and everything?",
            new String[]{"Mew", "42", "Peanut butter"},
            1
    );
    ask(question);
}

您可以轻松实现超时或以不同方式回答问题的结果,例如通过询问下一个问题或在完成最后一个问题后显示结果。

关于java - 等待任务完成而不阻塞 javafx 中的 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52984671/

相关文章:

java - 标记二维 java 数组

java - 如何在 Java Servlet Filter 中管理数据库连接?

c++ - 在单独的线程中启动带参数的成员函数

Android:如何获取指向服务的指针?

c# - 在 ASP.NET 中异步填充数据集或数据表的最佳做法是什么?

node.js - 同步多个请求和多个数据库调用

java - 在java中如何使用类的字符串属性来引用该类?

Java套接字文件发送

java - 共享一些公共(public)处理链的不同处理方法的设计模式

python - 非 Web、非文件应用程序中的异步性能