簡體   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