IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

[Stratégie] faire une JProgressBar ou un ProgressMonitor


Sujet :

AWT/Swing Java

  1. #1
    Membre habitué
    Inscrit en
    Avril 2007
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 10
    Par défaut [Stratégie] faire une JProgressBar ou un ProgressMonitor
    Bonjour,

    Je participe à la réalisation d'un assez gros logiciel, et j'ai réalisé un module permettant d'importer des données à partir de fichiers excel. Seulement la fonction principale de ce module, qui lit le fichier excel et sauve les données dans un format propre au logiciel, peut prendre beaucoup de temps.

    On m'a donc demandé de faire une progressBar pour montrer l'avancement de cette tâche mais je ne sais pas du tout comment m'y prendre. J'ai déjà regardé quelques exemples sur le site de Sun mais leurs exemples sont simplistes, avec juste une boucle qui augmente la valeur de la progressBar.Je ne vois pas comment réutiliser ces exemples pour ce que je veux faire...

    J'ai aussi remarqué qu'il y'avait des jProgressBar et jProgressMonitor. Quelle est la différence entre ces deux composants?

    J'ai aussi besoin que ce que je fais soit compatible avec java 1.5
    Merci pour toute réponse qui pourrait m'aider à avancer...

  2. #2
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    La JProgressBar est un composant affichant une jauge sous forme d'une barre horizontale qui se remplit quand on fait varier sa valeur sur un intervalle [min-max]. Generalement l'intervalle est connu a l'avance, mais il est toutefois possible de mettre la barre dans un etat indetermine ce qui fera juste une animation infinie et non pas une progression vers le max. Ce composant est donc a integrer dans un JPanel, une barre d'etat ou dans une boite de dialogue.

    Le ProgressMonitor (pas de J) est une boite de dialogue d'attente prete a l'emploi qui apparait au bout d'un certain temps a l'ecran (temps configurable), dispose d'une JProgressBar (voir paragraphe precedent), d'un bouton Annuler et peut afficher des messages recuts du processus qu'il observe.

    En utilisant le pattern observer/observateur, il est possible d'utiliser l'un l'autre de maniere interchangeable. C'est donc a toi de voir lequel tu preferres utiliser.

    Concernant ta tache elle-meme, tu effectues des operations I/O (conversion) qui prennent beaucoup de temps, il te faut donc effectuer ce traitement en fond dans une Thread specifique pour ne pas bloquer l'affichage de l'application qui elle utilise la Thread de Swing (EDT) car cela aurait pour effet de bloquer/geler l'affichage. Depuis la Thread de ton traitement, il te faut alors revenir de temps a autre dans l'EDT pour mettre a jour ta barre de progression ou ton moniteur grace a SwingUtilities.invokeLater() ou SwingUtilities.invokeAndWait().

    Dans tous les cas, il va donc te falloir estimer le temps que prend ta tache, ce ne sera pas forcement en seconde mais peut-etre plutot un nombre d'etapes critiques (conversion fichier 1, conversion fichier 2, etc...) au bout desquelles tu souhaites mettre a jour la GUI. Tu initialises la barre ou le moniteur avec le nombre d'etapes approprie et entre chaque etape tu met a jour le composant charge de presenter l'info a l'utilisateur.

    Si au contraire tu preferes donner une indication en secondes/minutes, soit il te faudra faire des estimations en fonction de tes propres tests soit ton programme devra etre capable de s'auto-evaluer lui-meme en fonction, par exemple, de la taille du fichier actuel a traiter et du temps mis par la precedente conversion (lors d'une conversion par lot).

    Enfin si jamais tu preferes rester dans une presentation non-determinee (on ne sait pas trop combien d'etapes on va faire ou combien de temps ca prendra), tu peux tout simplement utiliser un Timer qui modifiera a intervalles de temps regulier la valeur de la barre ou du moniteur pour avoir uniquement une animation ou des labels qui changent et ce de maniere a simuler une progression a l'utilisateur (comme ca il ne viendra pas a s'imaginer que ton programme ne fait rien ou est plante).

    A chaque fois que tu envoies l'information de maj de la progression, tu peux egalement verifier que le traitement n'a pas ete annule (par exemple en appuyant sur le bouton Annuler du ProgressMonitor) et interrompre ton traitement si necessaire.

    Un petit squelette tape a la va-vite:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    public interface TaskObserver {
      public void setMax(int max);
      public int setValue(int value);
      public void setValue();
      public boolean isCanceled();
    }
     
    public class ProgressBarTaskObserver extends JProgressBar implements TaskObserver {
     [...]
     
      public void setValue(final int value) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            setValue(value);
          }
        });
      }
     
      public boolean isCanceled() {
        return false;
      }
    }
     
    public class ProgressMonitorTaskObserver extends ProgressMonitor implements TaskObserver {
     [...]
     
      public void setValue(final int value) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            setProgress(value);
          }
        });
      }
     
      public boolean isCanceled() {
        return super.isCanceled();
      }
    }
     
     
    public class Task implements Runnable {
      private TaskObserver obs;
      privaate File[] files
     
      /**
      * @param obs A <code>TaskObserver</code>, may be <code>null</code>.
      * @param files List of files.
      */
      public Task(TaskObserver obs, File... files) {
         this.files = files;
         this.obs = obs;
         if (obs != null) {
           obs.setMax(getStepCount());
         }
      }
     
      public int getStepCount() {
        return files.length;
      }
     
      private boolean isCanceled() {
        return ((obs != null) && (obs.isCanceled());
      }
     
      private void incrementObs() {
        if (obs != null) {
          obs.setValue(obs.getValue() + 1);
        }
      }
     
      public void run() {
         for (File file : Files) {
           [...]
           if (isCanceled()) {
             return;
           }
           incrementObs();
        }
      }
    }
     
    public void actionPerformed(ActionEvent event) {
      try {
        File[] files = ...
        TaksObserver progressBar = new ProgressBarTaskObserver();
        Task task = new Task(progressBar, files);
        Thread thread = new ThreadTask()
        thread.setPriority(Thread.MIN_PRIORITY);
        thread.start();
      }
      catch (Throwable t) {
       [...]
      }
    }
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  3. #3
    Membre habitué
    Inscrit en
    Avril 2007
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 10
    Par défaut
    Bonsoir,

    Merci beaucoup pour cet eclaircissement. A vrai dire, je n'ai pas vraiment attendu que quelqu'un poste une réponse et j'ai réussi à faire une progress bar qui fonctionne. J'aimerais savoir si la façon dont je procède est assez "propre" ou si je devrais reprendre mon code..

    Voici comment je procède:

    j'ai 4 classes importantes liées à ce problème de progress bar.

    • ExcelConverter , qui permet de realiser le traitement sur le fichier
    • Bar, qui permet de créer la progressBar
    • UpdateBarThread, qui étend la classe Thread et permet de faire "avancer" la barre
    • SaveThread, qui permet de lancer mon traitement dans un thread séparé


    dans ma classe principale, je crée un nouveau SaveThread qui me permet de lancer le traitement. (je récupère la variable qui m'interesse a la fin de ce thread grace à un accesseur).

    je crée ensuite la Bar et son thread pour la faire avancer, et je la fais progresser grace a des methodes statiques de la classe ExcelConverter, qui me donnent la progression.

    J'ai l'impression que ce que j'ai fait est vraiment du bidouillage... . Dois-je reprendre mon code ou est ce que cela est correct? Ca marche plutot bien mais je me posais la question...

  4. #4
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    Non, cela semble etre effectivement une bonne idee puisque dans ce cas l'API permet effectivement de connaitre l'avancement (un luxe que toutes n'offrent pas) et ce dans une autre Thread que le traitement lui-meme.

    Par contre, IL FAUT que les appels qui mettent a jour ou manipulent la barre se fassent dans l'EDT (donc SwingUtilities.invokeLater() ou SwingUtilities.invokeAndWait()). Dans le cas d'une JProgressBar il est possible qu'un appel direct a setValue() depuis l'UpdateBarThread ne pose pas de probleme mais c'est la methode normale a utiliser et ca peut prevenir des problemes ulterieurs sur des composants plus complexes.

    Alternativement tu peux essayer de remplacer UpdateBarThread par un Timer Swing et la la manipulation directe est possible (a verifier cependant que ca ne cause pas de probleme dans Swing ou l'API de conversion).
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XSLT] Faire une boucle sur une variable [i]
    Par PoT_de_NuTeLLa dans le forum XSL/XSLT/XPATH
    Réponses: 8
    Dernier message: 07/06/2010, 12h45
  2. Réponses: 14
    Dernier message: 26/05/2009, 14h28
  3. Faire défiler une JProgressBar plusieurs fois
    Par Hohenheim dans le forum Composants
    Réponses: 8
    Dernier message: 03/05/2009, 21h29
  4. Réponses: 3
    Dernier message: 13/05/2006, 11h06
  5. Faire une liste de device??
    Par jackjack dans le forum DirectX
    Réponses: 1
    Dernier message: 23/05/2003, 14h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo