I hope I'm not duplicating a question, but I couldn't find one specifically for my issue. I'm developing a small math flash card application, using JavaFX to create the GUI. The program should runs as follow:
The problems is SELECT A.COLUMNA, A.COLUMNB, A.COLUMNC, B.COLUMND
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.COLUMNA = B.COLUMNA AND A.COLUMNB = B.COLUMNB
from user textfield is processed as soon as start button is pressed, without giving the user a chance to enter an answer. How do I make the program wait for X amount of seconds or for the next button to be clicked before processing the user's answer? Here's my code:
getText()
Here is the problem code... at least how I see it.
//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();
});
I've tried using //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));
}
but that freezes the gui for however long I specify and then goes through the Thread.sleep(X)
method and the loop before going to the test screen. (I know because I had the program set up to print the questions and answer input to the console). It shows the last question and that's all.
I didn't include the next button code because I can't get the gui to go to the test page anyway.
Any help on any of the code is appreciated.
答案 0 :(得分:1)
这可以通过各种方法实现。
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);
}
}
答案 1 :(得分:0)
对于计时器,您应该(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
方法之间捕获输入中的文本。