java - 等待然后接收文本字段输入而不卡住 GUI

标签 java multithreading user-interface javafx freeze

我希望我没有重复问题,但我找不到专门针对我的问题的问题。 我正在开发一个小型数学闪存卡应用程序,使用 JavaFX 创建 GUI。该程序应按如下方式运行:

  1. 用户选择设置,然后按下开始按钮。
  2. gui 显示用户输入的问题和文本字段。
  3. 用户在 X 秒内输入答案或 gui 自动转到下一个问题 - 或者,用户可以通过按 next 按钮立即转到下一个问题。
  4. GUI 显示分数和平均分。

问题是 getText() 在按下 start 按钮后立即处理用户文本字段,而不给用户输入答案的机会。如何让程序等待 X 秒或等待 下一步 按钮被点击,然后再处理用户的回答?这是我的代码:

//start button changes view and then runs startTest()
start.setOnAction(e -> {

        setLeft(null);
        setRight(null);

        setCenter(test_container);
        running_program_title.setText(getDifficulty().name() + " Test");
        buttons_container.getChildren().clear();
        buttons_container.getChildren().addAll(next, quit, submit);

        startTest();
    });

这是问题代码……至少我是这样看的。

//startTest method calls askAdd() to ask an addition question
void startTest() {

    int asked = 0;
    int correct = 0;

    while (asked < numberOfQuestions) {
        if(askAdd()){
        correct++;
        asked++;
    }
}

boolean askAdd() {

    int a = (int) (Math.random() * getMultiplier());
    int b = (int) (Math.random() * getMultiplier());

     //ask question
     question.setText("What is " + a + " + " + b + "?");

     //code needed to pause method and wait for user input for X seconds

     //retrieve user answer and return if its correct
     return answer.getText().equalsIgnoreCase(String.valueOf(a+b));
}

我试过使用 Thread.sleep(X) 但是无论我指定多长时间都会卡住 gui,然后通过 addAsk() 方法和循环在进入测试屏幕之前。 (我知道是因为我设置了程序来打印问题并将答案输入到控制台)。它显示了最后一个问题,仅此而已。

我没有包含 next 按钮代码,因为无论如何我都无法让 gui 转到测试页面。

感谢对任何代码的任何帮助。

最佳答案

这可以通过多种方法实现。

PauseTransition是目前众多的 apt 解决方案之一。它等待 X 时间间隔,然后执行 Task。它可以启动重新启动随时停止

这是一个示例,说明如何使用它来实现类似的结果。

enter image description here

完整代码

import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.util.stream.IntStream;

public class Main extends Application {

    int questionIndex = 0;
    int noOfQuestions = 10;

    @Override
    public void start(Stage stage) {

        VBox box = new VBox(10);
        box.setPadding(new Insets(10));
        Scene scene = new Scene(new ScrollPane(box), 500, 200);
        ObservableList<String> questions =
                FXCollections.observableArrayList("1) Whats your (full) name?",
                                                  "2) How old are you?",
                                                  "3) Whats your Birthday?",
                                                  "4) What starsign does that make it?",
                                                  "5) Whats your favourite colour?",
                                                  "6) Whats your lucky number?",
                                                  "7) Do you have any pets?",
                                                  "8) Where are you from?",
                                                  "9) How tall are you?",
                                                  "10) What shoe size are you?");

        ObservableList<String> answers = FXCollections.observableArrayList();

        final PauseTransition pt = new PauseTransition(Duration.millis(5000));

        Label questionLabel = new Label(questions.get(questionIndex));
        Label timerLabel = new Label("Time Remaining : ");
        Label time = new Label();
        time.setStyle("-fx-text-fill: RED");
        TextField answerField = new TextField();

        Button nextQuestion = new Button("Next");

        pt.currentTimeProperty().addListener(new ChangeListener<Duration>() {
            @Override
            public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
                time.setText(String.valueOf(5 - (int)newValue.toSeconds()));
            }
        });

        box.getChildren().addAll(questionLabel, answerField, new HBox(timerLabel, time), nextQuestion);

        nextQuestion.setOnAction( (ActionEvent event) -> {
            answers.add(questionIndex, answerField.getText());

            //Check if it is the last question
            if(questionIndex == noOfQuestions-1) {
                pt.stop();
                box.getChildren().clear();
                IntStream.range(0, noOfQuestions).forEach(i -> {
                    Label question = new Label("Question : " + questions.get(i));
                    question.setStyle("-fx-text-fill: RED");
                    Label answer = new Label("Answer : " + answers.get(i));
                    answer.setStyle("-fx-text-fill: GREEN");
                    box.getChildren().addAll(question, answer);
                });
            }
            // All other time
            else {
                //Set new question
                questionLabel.setText(questions.get(++questionIndex));
                answerField.clear();
                pt.playFromStart();
            }
        });

        pt.setOnFinished( ( ActionEvent event ) -> {
            nextQuestion.fire();
        });
        pt.play();

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

    public static void main(String[] args) {
        launch(args);
    }
}

关于java - 等待然后接收文本字段输入而不卡住 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30202582/

相关文章:

c++ - 寻找提供类似于 Google Go channel 功能的 C 或 C++ 库

java - 为什么我的 JAVA GUI 打开多个窗口?

java - JDBC Oracle 结果集空指针异常

java - 将字符串添加到 ArrayList 中

java - Mockito 测试 java 8 lambda Consumer API

Java:在排序列表中查找元素的最佳方法是什么?

java - 无法在未调用 Looper.prepare() : java. lang.RuntimeException 的线程内创建处理程序

java - Java 的轻量级长时间运行方法取消模式

java - 黑莓应用程序中的菜单项

c++ - Qt Creator - Gui 应用程序 - 构建错误 - 找不到 -IGL