Progressbar ne s'affiche pas malgré setVisible(true) [Résolu]

Signaler
Messages postés
39
Date d'inscription
jeudi 16 février 2017
Statut
Membre
Dernière intervention
13 juin 2021
-
Messages postés
39
Date d'inscription
jeudi 16 février 2017
Statut
Membre
Dernière intervention
13 juin 2021
-
Coucou,

Je souhaite afficher une Progressbar (JavaFX), sur un event click d'un bouton, et simuler une progression de quelques instants en utilisant une boucle while dans laquelle j'incrémente une variable de progression et je sors quand la progression atteint 1.
Donc 1) click bouton - 2) rendre visible ma progress bar - 3) Une boucle while où j'incrémente la progression - 4) Sortie du while et je rends invisible la progress bar.
Voici mon code :


pb.setVisible(true);
pb.setProgress(0.0);
double x = 0.0;
while(pb.getProgress()<1.0)
{
x = x + 0.00000001;
pb.setProgress(x);
}
pb.setVisible(false);


=> à noter que l'incrémentation est suffisamment petite pour que l'exécution du while dure bien quelques secondes
=> à noter que je n'ai pas de problème d'affichage car sans le while et le setVisible(false), la progress bar s'affiche bien.
Du coup je comprends pas pourquoi la progress bar ne s'affiche plus quand je mets ce while

Merci d'avance :)

2 réponses

Messages postés
16361
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
11 juin 2021
2 843
Bonjour,

Pour t'aider, voici un exemple complet d'une ProgressBar avec une Task.

import javafx.concurrent.Task;

public class ProgressTask extends Task<Void> {
    @Override
    protected Void call() throws Exception {
        int count = 100;
        for (int i = 0; i < count; i++) {
            update(i, count);
            task(i, count);
        }
        update(count, count);
        return null;
    }

    private void task(int i, int count) throws Exception {
        Thread.sleep(50);
    }

    private void update(int i, int count) {
        updateProgress(i, count);
        updateMessage("Item " + i + "/" + count);
    }
};

import javafx.application.Application;
import javafx.concurrent.WorkerStateEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.FlowPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class ProgressBarApplication extends Application {

    @Override
    public void start(Stage primaryStage) {
        final Button startButton = new Button("Start");

        final ProgressBar progressBar = new ProgressBar(0);
        progressBar.setMinWidth(250);

        final Label statusLabel = new Label("Non Démarré...");
        statusLabel.setMinWidth(50);

        startButton.setOnAction(actionEvent -> {
                    ProgressTask task = new ProgressTask();

                    startButton.setDisable(true);
                    progressBar.setProgress(0);
                    statusLabel.setText("Démarré !");
                    progressBar.progressProperty().bind(task.progressProperty());
                    statusLabel.textProperty().bind(task.messageProperty());

                    task.addEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED, workerStateEvent -> {
                        statusLabel.textProperty().unbind();
                        progressBar.progressProperty().unbind();
                        statusLabel.setText("Terminé !");
                        progressBar.setProgress(1);
                        startButton.setDisable(false);
                    });

                    new Thread(task).start();
                }
        );

        FlowPane root = new FlowPane();
        root.setPadding(new Insets(10));
        root.setHgap(10);
        root.getChildren().addAll(startButton, progressBar, statusLabel);

        Scene scene = new Scene(root, 450, 50, Color.WHITE);
        primaryStage.setTitle("ProgressBar");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}
Messages postés
39
Date d'inscription
jeudi 16 février 2017
Statut
Membre
Dernière intervention
13 juin 2021

Génial, ça fait plus que le job :D
Merci beaucoup pour ton aide !!!!!!!
Messages postés
16361
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
11 juin 2021
2 843
Bonjour,

Sans le code complet pour tester je ne peux que faire des suppositions, mais je dirais que lorsque tu cliques sur le bouton, quoi que tu fasses, l'interface graphique ne se mettra pas à jour tant que le clic du bouton n'est pas terminé.
Normalement il faudrait que le clic sur le bouton ajoute une tâche de fond à exécuter et rende la main tout de suite. Et c'est la tâche de fond qui va mettre à jour l'interface graphique, qui du coup ne sera plus bloquée puisque le clic sur le bouton est bien terminé.

Voir ce tutoriel et notamment l'exemple 1-3
https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/fx_concurrency.htm
Messages postés
39
Date d'inscription
jeudi 16 février 2017
Statut
Membre
Dernière intervention
13 juin 2021

Merci pour ta réponse KX. Cependant je pense que ça n'explique pas ma situation car si j'enlève la boucle while, la progress bar s'affiche bien alors que ça se passe bien en event su clic bouton. Pour plus de clarté, voici plus d'éléments de mon code...

Ici la méthode qui demande d'afficher la progressbar durant l'exécution du while puis de la rendre invisible ensuite

public void launchAnalysisConfirm(){

mainViewController.MV_progressbar.setVisible(true);
mainViewController.MV_progressbar.setProgress(0.0);
double x = 0.0;
while(mainViewController.MV_progressbar.getProgress()<1.0)
{
x = x + 0.00000001;
mainViewController.MV_progressbar.setProgress(x);
}
mainViewController.MV_progressbar.setVisible(false);

}


Ici une méthode qui génère l' event sur le click du bouton MV_LaunchAnalysisBtn

public void initManager(final MainViewManager mainViewManager) {

MV_LaunchAnalysisBtn.setOnAction(event -> {
mainViewManager.launchAnalysisConfirm();
});
}


et quelque part dans mon programme l'appel de la méthode initManager :

mainViewController.initManager(mainViewManager);


Cas 1 : sans le while suivi du setVisible(false) => progress bar s'affiche bien
Cas 2 : avec le while suivi du setVisible(false) => progress bar ne s'affiche pas

/!\ ce n'est pas un problème de while qui s'exécute trop vite pour la voir : le while dure bien quelques secondes
Messages postés
16361
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
11 juin 2021
2 843
Pour reprendre le contenu du lien que je t'ai envoyé, en l'adaptant à ton code, essaie quelque chose comme ceci :
Task task = new Task<Void>(){
    @Override
    public Void call(){
        mainViewManager.launchAnalysisConfirm();
        return null;
    }
};

MV_LaunchAnalysisBtn.setOnAction(event -> new Thread(task).start());
Messages postés
39
Date d'inscription
jeudi 16 février 2017
Statut
Membre
Dernière intervention
13 juin 2021
>
Messages postés
16361
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
11 juin 2021

Ok cool ça marche mieux mais....Bon du coup lorsque je clique une 1ère foir sur le bouton, la progressBar s'affiche, par contre, malgré que j'incrémente son setProgress, ça reste tout blanc à l'intérieur. Et si je réappuie sur le bouton, ça plante :
Exception in thread "Thread-3" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3

Donc peut-être qu'il faut faire un truc pour fermer le thread je sais pas trop...