Progress bar qui ne s'affiche qu'a la fin de traitement

Résolu
jimdano Messages postés 16 Date d'inscription mercredi 7 avril 2010 Statut Membre Dernière intervention 20 mars 2013 - 16 avril 2012 à 23:38
cormandyr Messages postés 600 Date d'inscription samedi 20 mai 2006 Statut Membre Dernière intervention 8 juillet 2016 - 18 avril 2012 à 08:15
Bonjour, je suis confronté à un problème qui je suis sur est très simple à gérer, mais je regarde des forums et autres sans trouver de réponses à mon problème...

Lorsque je veux afficher ma progressbar, le SwingWorker fait ce qu'il a à faire et incrémente la progression de ma barre de chargement mais rien ne s'affiche jusqu'à la fin de mon autre tâche qui gère des actions avec une base de données...

pourriez vous m'aider à comprendre pourquoi le thread se lance mais ne fait pas son boulot entièrement (il calcul une nouvel valeur de progression mais ne l'affiche pas...)?

Merci d'avance, voici mon code...

public class MyProgressMonitor extends JFrame implements PropertyChangeListener{

private static final long serialVersionUID = 1L;
private JProgressBar current;
private Dimension screenSize;
private int windowX;
private Dimension windowSize;
private int windowY;
private static JButton but;
private JPanel pane;
private Task task;
    
class Task extends SwingWorker<Void, Void> {
        /*
         * Main task. Executed in background thread.
         */
        @Override
        public Void doInBackground() {
            Random random = new Random();
            int progress = 0;
            //Initialize progress property.
            setProgress(0);
            while (progress < 100) {
                //Sleep for up to one second.
                try {
                    Thread.sleep(random.nextInt(2000));
                } catch (InterruptedException ignore) {}
                //Make random progress.
                progress += random.nextInt(10);
                setProgress(Math.min(progress, 100));
            }
            return null;
        }
        
        public void done() {
            Toolkit.getDefaultToolkit().beep();
            setCursor(null); //turn off the wait cursor
        }        
}
        
public MyProgressMonitor(JButton button, boolean b) {
        super("Progression");
        setBackground(Color.white);
        setLocationRelativeTo(null); 
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
windowSize = getSize();
windowX = Math.max(0, (screenSize.width - windowSize.width) / 3);
windowY = Math.max(0, (screenSize.height - windowSize.height) / 2);

if(button != null){
        but = button;
        but.setEnabled(b);
}
        pane = new JPanel();
        pane.setLayout(new FlowLayout());
        
        current = new JProgressBar(0, 99);
        current.setValue(0);
        current.setString ("Progession: " + (int)(current.getPercentComplete()*100) + "%");
        current.setStringPainted(true);
        
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        task = new Task();
        task.addPropertyChangeListener(this);
        task.execute();
        
        pane.add(current);

        setVisible(true);
        setSize(new Dimension(250,75));
setResizable(false);
setLocation(windowX, windowY);
        setContentPane(pane);
    }

public void remove(JButton butt) {
// TODO Auto-generated method stub
setVisible(false);
current = null;
pane = null;
butt.setEnabled(true);
}

@Override
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub
if ("progress" == arg0.getPropertyName()) {
            int progress = (Integer) arg0.getNewValue();
            if(current != null){
            current.setValue(progress);
current.setString ("Progession: " + (int)(current.getPercentComplete()*100) + "%");
            }
        }
}
}


et je le crée dans une autre classe, pendant un traitement assez long :

MyProgressMonitor prog = new MyProgressMonitor(button,false);


Merci encore ;)
A voir également:

9 réponses

cormandyr Messages postés 600 Date d'inscription samedi 20 mai 2006 Statut Membre Dernière intervention 8 juillet 2016 11
17 avril 2012 à 11:56
quand tu appelles la méthode de traitement (celle qui calcule quoi ^^) fais ceci:

code actuel:
public void calcul(){
    /* tout plein de code ^^ */
}


nouveau code :
public void calcul() {
    new Thread(new Runnable() {
        public void run(){
            /* tout plein de code ^^ */
        }
    }).start();
}
3
cs_GodConan Messages postés 2113 Date d'inscription samedi 8 novembre 2003 Statut Contributeur Dernière intervention 6 octobre 2012 12
17 avril 2012 à 06:52
salut,

SwingWorker : je ne connais pas cette class (pas le temps de regarder ce matin sorry) .... Ceci dit si elle n instancie pas effectivement un thread, c est normale ...

Essai de tracer ca construction... sinon fait ta propre class et remplace la pour tester ;o) ...

GL

GodConan ;o)
0
cormandyr Messages postés 600 Date d'inscription samedi 20 mai 2006 Statut Membre Dernière intervention 8 juillet 2016 11
17 avril 2012 à 08:36
Salut, oui en effet, le fait que la progress bar ne s'affiche qu'à la fin du traitement laisse à penser qu'il s'agit d'un problème de thread... Autrement dit, le traitement et l'affichage sont fait dans la même Thread et ton GUI n'est rafraichi qu'à la fin du traitement...
0
jimdano Messages postés 16 Date d'inscription mercredi 7 avril 2010 Statut Membre Dernière intervention 20 mars 2013
17 avril 2012 à 11:38
oui je penses bien que c'est un problème de thread mais il me semblait que le fait d'utiliser swingWorker résolvait ce genre de problèmes avec les thread.

Il le gère en quelque sorte car il effectue ce qui lui est demandé mais je ne comprends pas pourquoi il ne l'affiche pas, je ne vois pas comment résoudre ce problème...

J'ai essayé d'effectuer des Thread.yield(); dans le programme appelant afin de voir si cela ne laisserait pas le temps d'afficher correctement la progressbar mais cela ne change rien à mon problème...

A vrai dire, je ne sais pas quoi essayer, j'ai également refait une classe sans le swingWorker mais c'est pire, rien ne s'effectue en tâche de fond...

Merci encore si quelqu'un à déja eu ce genre de problème et sait comment ou le régler, ou si quelqu'un connait juste la réponse à mon problème^^
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
17 avril 2012 à 21:36
Salut,

Je ne sais pas quoi dire ... J'ai ouvert eclipse (+ création d'un projet bidon + une classe MyProgressMonitor) ensuite j'ai fait un petit copier/coller de ton code vers eclipse, j'ai également ajouté le bloc suivant (simple main):
public class MyProgressMonitor // ...
  // ...
  public static void main(String[] args) {
    new MyProgressMonitor(null,false);
  }
// ...
}

et à l'exécution .... j'ai bien une fenêtre qui s'ouvre et anime la progressbar de façon régulière...
Donc visiblement rien à signaler de ce coté... tu nous as également parlé d'une interaction avec une base de données ?

Sinon elle te sert à quoi cette très mais vraiment très vilaine copie dans le constructeur du bouton vers une variable static ?


-----

"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
0
jimdano Messages postés 16 Date d'inscription mercredi 7 avril 2010 Statut Membre Dernière intervention 20 mars 2013
18 avril 2012 à 00:37
En fait, la copie dans le constructeur du bouton me sert à empêcher l'utilisateur d'appuyer sur le bouton pendant l'interaction avec la base de données et pendant l’exécution de mes méthodes^^

Je ne redonne le droit d'action au bouton qu'à la fin du chargement^^

Sans l'interaction avec ma base de données, la progress bar marche parfaitement, en effet.

En fait la progress bar s'anime, mais que à la fin du traitement avec la base de donnée, je ne peux pas te donner le code, il y a 6000 lignes pour mon projet, mais en gros, pendant l'interaction avec la base de données, je dis à l'utilisateur de patienter jusqu'à la fin de la progress bar (qui sera à optimiser quand elle marchera), le traitement se fait bien en parallèle, mais pas l'affichage de la progress bar, c'est ça que je ne comprends pas... :/

Merci cormandyr, ca marche maintenant =) =)
0
jimdano Messages postés 16 Date d'inscription mercredi 7 avril 2010 Statut Membre Dernière intervention 20 mars 2013
18 avril 2012 à 00:38
Et merci à tout ceux qui se sont attardé sur mon cas =)
0
jimdano Messages postés 16 Date d'inscription mercredi 7 avril 2010 Statut Membre Dernière intervention 20 mars 2013
18 avril 2012 à 01:24
public class MyProgressMonitor extends JFrame implements ChangeListener{

private static final long serialVersionUID = 1L;
private JProgressBar current;
private Dimension screenSize;
private int windowX;
private Dimension windowSize;
private int windowY;
private static JButton but;
private JPanel pane;
        
public MyProgressMonitor(JButton button, boolean b) {
        super("Progression");
        setBackground(Color.white);
        setLocationRelativeTo(null); 
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
windowSize = getSize();
windowX = Math.max(0, (screenSize.width - windowSize.width) / 3);
windowY = Math.max(0, (screenSize.height - windowSize.height) / 2);

if(button != null){
        but = button;
        but.setEnabled(b);
}
        pane = new JPanel();
        pane.setLayout(new FlowLayout());
        
        current = new JProgressBar(0, 99);
        current.setValue(0);
        current.setString ("Progession: " + (int)(current.getPercentComplete()*100) + "%");
        current.setStringPainted(true);
        current.addChangeListener(this);
        
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        
        pane.add(current);

        setVisible(true);
        setSize(new Dimension(250,75));
setResizable(false);
setLocation(windowX, windowY);
        setContentPane(pane);
    }

public void remove(JButton butt) {
setVisible(false);
current = null;
pane = null;
butt.setEnabled(true);
}

public void setProgress(int num){
current.setValue(num);
current.setString ("Progession: " + (int)(current.getPercentComplete()*100) + "%");
}

@Override
public void stateChanged(ChangeEvent arg0) {
current.setString ("Progession: " + (int)(current.getPercentComplete()*100) + "%");
}
}


et dans le programme appelant :

final MyProgressMonitor prog = new MyProgressMonitor(button,false);
new Thread(new Runnable() {
        public void run(){
            /* tout plein de code :) (interaction avec bdd...) */
        }
    }).start();


pour ceux qui voudraient s'en inspirer...
0
cormandyr Messages postés 600 Date d'inscription samedi 20 mai 2006 Statut Membre Dernière intervention 8 juillet 2016 11
18 avril 2012 à 08:15
au lieu de faire une copie de la référence de ton button, pourquoi ne pas directement travailler avec? Je veux dire, tu sais quand tu cliques sur le boutton (paf setEnabled(false)) et tu sais quand ton traitement est terminé (repaf setEnabled(true)) non?
0
Rejoignez-nous