[英]Wait for and then receive textfield input without freezing GUI
我希望我不會重復一個問題,但我找不到專門針對我的問題。 我正在開發一個小型數學閃存卡應用程序,使用JavaFX創建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
。 它可以隨時start
, restart
, stop 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.