yoliska
yoliska

Reputation: 1

JavaFX: ProgressBar with timeline; reset both if completed

I am building an application which is an exam. All the questions are shown on different screens, all with a progressbar showing how much time the user has left. When the progressbar is full, the screen with another question is shown and the progressbar and timeline should be resetted.

When the time is up, the next screen is shown and the timeline resets, but the progressbar (shown in code as 'PRGB') remains full and it will not reset to an empty progressbar. This is my code:

public void timeBar() throws Exception{
    Timeline timeline = new Timeline(
            new KeyFrame(Duration.ONE, new KeyValue(PRGB.progressProperty(), 0)),
            new KeyFrame(Duration.seconds(Main.time), e-> {
            }, new KeyValue(PRGB.progressProperty(), 1))
    );
    timeline.setCycleCount(1);
    timeline.play();
    timeline.setOnFinished(event -> {
        Main.setPane(questionNumber);
        questionNumber++;
        timeline.play();
        //in here the progressbar has to be resetted
    });
}

Update: I have deleted my ProgressBar from SceneBuilder, and made a new one on which I then run the code below (with a few alterations taking by your suggestions). But now the progressbar does reset it self, but it does not show the progress: it stays empty.

public void timeBar() throws Exception{
    Timeline timeline = new Timeline(
            //I only use two keyframes instead of three
            new KeyFrame(Duration.seconds(Main.time), e-> {
            }, new KeyValue(PRGB.progressProperty(), 1))
    );
    timeline.setCycleCount(1);
    timeline.play();
    timeline.setOnFinished(event -> {
        Main.setPane(questionNumber);
        questionNumber++;
        //The setProgress is added
        PRGB.setProgress(0.0F);
        timeline.play();
    });
}

Upvotes: 0

Views: 1509

Answers (2)

SedJ601
SedJ601

Reputation: 13858

This can probably be done better. In this example, 3 seconds is given for each question with 1 second at the end of each question to load the next question. Code from here.

import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.PauseTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application
{

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

    @Override
    public void start(Stage stage)
    {
        Label lblCurrentQuestion = new Label();
        ProgressBar prgb = new ProgressBar(0);

        int numberOfQuestions = 5;//Number of questions
        int timeForEachQuestion = 3;//3 second to do each questions
        AtomicInteger currentProgressCounter = new AtomicInteger(0);
        AtomicInteger currentQuestionCounter = new AtomicInteger(1);

        Timeline fiveSecondsWonder = new Timeline(new KeyFrame(Duration.seconds(1), (event) -> {
            if (currentProgressCounter.get() == timeForEachQuestion + 1) {
                //Go to next question!
                prgb.setProgress(0);
                currentProgressCounter.set(0);
                currentQuestionCounter.incrementAndGet();
            }
            lblCurrentQuestion.setText("Question " + currentQuestionCounter.get());
            prgb.setProgress(currentProgressCounter.getAndIncrement() / (double) timeForEachQuestion);
        }));

        fiveSecondsWonder.setCycleCount(numberOfQuestions * (timeForEachQuestion + 1));
        fiveSecondsWonder.play();
        fiveSecondsWonder.setOnFinished(event -> {
            PauseTransition wait = new PauseTransition(Duration.seconds(1));
            wait.setOnFinished((e) -> {
                /*YOUR METHOD*/
                lblCurrentQuestion.setText("Quiz done!");
                prgb.setProgress(0);
                wait.playFromStart();
            });
            wait.play();
        });

        Scene scene = new Scene(new StackPane(new VBox(lblCurrentQuestion, prgb)), 500, 500);

        stage.setScene(scene);
        stage.show();
    }
}

Upvotes: 1

Blake Ordway
Blake Ordway

Reputation: 308

You have a call to timeline.play() in your setOnFinished() call. Remove that call so that the progress bar doesn't get reset to full.

Also, you should reset your progress bar by doing progressBar.setProgress(0.0F); in the setOnFinished()

Upvotes: 0

Related Questions