Progressbar ne s'affiche pas malgré setVisible(true)

Résolu/Fermé
JamieMacUloth Messages postés 43 Date d'inscription jeudi 16 février 2017 Statut Membre Dernière intervention 6 juin 2022 - Modifié le 11 juin 2021 à 13:23
JamieMacUloth Messages postés 43 Date d'inscription jeudi 16 février 2017 Statut Membre Dernière intervention 6 juin 2022 - 13 juin 2021 à 09:10
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 :)
A voir également:

2 réponses

KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
12 juin 2021 à 09:09
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);
    }
}
1
JamieMacUloth Messages postés 43 Date d'inscription jeudi 16 février 2017 Statut Membre Dernière intervention 6 juin 2022
13 juin 2021 à 09:10
Génial, ça fait plus que le job :D
Merci beaucoup pour ton aide !!!!!!!
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
11 juin 2021 à 15:10
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
0
JamieMacUloth Messages postés 43 Date d'inscription jeudi 16 février 2017 Statut Membre Dernière intervention 6 juin 2022
11 juin 2021 à 15:26
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
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
Modifié le 11 juin 2021 à 15:54
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());
0
JamieMacUloth Messages postés 43 Date d'inscription jeudi 16 février 2017 Statut Membre Dernière intervention 6 juin 2022 > KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024
11 juin 2021 à 17:47
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...
0