繁体   English   中英

等待然后接收文本字段输入而不冻结GUI

[英]Wait for and then receive textfield input without freezing GUI

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

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

问题是来自用户文本字段的getText()在按下开始按钮时立即处理,而不给用户输入答案的机会。 在处理用户的答案之前,如何让程序等待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()方法和循环。 (我知道,因为我已经设置了程序来打印问题并回答控制台的输入)。 它显示了最后一个问题,就是这样。

我没有包含下一个按钮代码,因为无论如何我都无法让gui进入测试页面。

任何代码的任何帮助表示赞赏。

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

PauseTransition是目前众多的解决方案之一。 它等待X time interval ,然后执行Task 它可以随时startrestartstop at any moment

以下是如何使用它来实现类似结果的示例。

在此输入图像描述

完整代码

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);
    }
}

对于计时器,您应该(IMO)使用Timeline 这是一个例子:

public class MultiGame extends Application {
    ProgressBar progressBar;

    final int allowedTime = 5; //seconds
    final DoubleProperty percentOfTimeUsed = new SimpleDoubleProperty(0);
    final Timeline timer =
            new Timeline(
                new KeyFrame(
                        Duration.ZERO, new KeyValue(percentOfTimeUsed, 0)),
                new KeyFrame(
                        Duration.seconds(allowedTime), new KeyValue(percentOfTimeUsed, 1))
            );

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

    @Override
    public void start(Stage primaryStage) {
        BorderPane root = new BorderPane();

        progressBar = new ProgressBar();
        progressBar.progressProperty().bindBidirectional(percentOfTimeUsed);
        root.setTop(progressBar);

        Button answer = new Button("Answer");
        answer.setOnAction(ae -> restart());// the on answer handler

        Button skip = new Button("Skip");
        skip.setOnAction(ae -> restart());// the skip question handler

        HBox mainContent = new HBox(15,
                new Label("Your Question"), new TextField("The answer"),  answer, skip);
        root.setCenter(mainContent);

        timer.setOnFinished(ae -> restart());// the end of timer handler

        primaryStage.setScene(new Scene(root));
        primaryStage.show();

        restart();
    }

    void restart() { timer.stop(); timer.playFromStart(); }

    void pause() { timer.pause(); }

    void resume() { timer.play(); }
}

您只需要在时间轴的开始和restart方法之间捕获输入中的文本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM