2015-05-12 12 views
5

Mam nadzieję, że nie powielam pytania, ale nie udało mi się znaleźć jednego konkretnego problemu. Pracuję nad małą kartą z matematyką, używając JavaFX do stworzenia GUI. Program powinien przebiega następująco:Poczekaj, a następnie otrzymasz tekstowe dane wejściowe bez zamrożenia GUI

  1. użytkownik dobiera ustawienia, a następnie naciska początek przycisk.
  2. gui wyświetla pytanie i pole tekstowe do wprowadzania danych przez użytkownika.
  3. wprowadzane przez użytkownika odpowiedzi w ciągu X sekund lub gui automatycznie przechodzą do następnego pytania - alternatywnie użytkownik może przejść do następnego pytania natychmiast, naciskając następny przycisk.
  4. GUI wyświetla wynik i średnią.

problemów jest getText() z tekstowym użytkownika jest przetwarzane tak szybko, jak początku przycisk jest wciśnięty, nie dając użytkownikowi możliwość wejścia odpowiedź. Jak sprawić, aby program czekał na X sekund lub przycisk Kliknij, aby kliknąć zanim rozpatrzy odpowiedź użytkownika? Oto mój kod:

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

Oto kod problemu ... przynajmniej jak go widzę.

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

Próbowałem za pomocą Thread.sleep(X) ale że zamarznie gui na długo jednak określić, a następnie przechodzi przez sposobu addAsk() i pętli przed udaniem się na ekranie testowym. (Wiem, ponieważ miałem ustawiony program, aby wydrukować pytania i odpowiedzieć na wejście do konsoli). Pokazuje ostatnie pytanie i to wszystko.

Nie dodałem kodu przycisku next, ponieważ nie mogę uzyskać gui, aby przejść do strony testowej.

Każda pomoc dotycząca dowolnego kodu jest doceniana.

Odpowiedz

0

Dla timera należy (IMO) użyć Timeline. Oto przykład:

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

Wystarczy przechwycić tekst z wejściem pomiędzy rozruchu linii czasu i sposobu restart.

+0

Masz kilka nieporozumień w swojej odpowiedzi. Prawdopodobnie chcesz ustawić dozwoloną czas na pięć sekund, a nie na 500 sekund. Właściwość ['progressProperty'] (https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/ProgressIndicator.html#progressProperty--) powinna być liczbą od zera do jedności, więc nie powinno dwukierunkowo wiązać go do wartości, która waha się od zera do stu. Preferowane jest jednokierunkowe wiązanie: 'progressBar.progressProperty(). Bind (percentOfTimeUsed.divide (100.0));' – jewelsea

+0

@jewelsea To wyjaśnia problem z dozwolonym czasem - dziękuję za wskazanie tego. Wzniesiony przykład. –

+0

Dokładnie tego, czego szukałem. Dziękuję Ci. – gabe2390

1

Można to osiągnąć różnymi metodami.

PauseTransition jest jednym z wielu dostępnych rozwiązań apt. Czeka na X time interval, a następnie wykonuje Task. Może start, restart, , .

Oto przykład, w jaki sposób można go wykorzystać do osiągnięcia podobnego rezultatu.

enter image description here

Pełny kod

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); 
    } 
} 
Powiązane problemy