Problème entre Swing et SwingWorker

Résolu
theFrogkiller Messages postés 5 Date d'inscription lundi 11 août 2008 Statut Membre Dernière intervention 15 août 2008 - 11 août 2008 à 13:25
theFrogkiller Messages postés 5 Date d'inscription lundi 11 août 2008 Statut Membre Dernière intervention 15 août 2008 - 15 août 2008 à 14:09
bonjour,

voilà je développe une application autour de lancements de dés. une
partie consiste en l'affichage progressif du résultat de lancement de
dés. pour éviter de bloquer l'application à cause de l'EDT lors des
affichages successifs j'utilise la classe SwingWorker.

Et là c'est le drame !

mon appli a un comportement assez étrange. quand le nombres de dés est
grand tout ce déroule comme prévu. mais dès que le nombre de dés est
faible l'affichage se bloque et le nombres de cycles d'affichages est
aléatoire (de 10 à une centaine).


Si quelqu'un à une idée je suis preneur.


voici mes classes:

la classe Stat contient entre autre un tableau stockant les données du graphique.

le main:
<!-- BEGIN TEMPLATE: bbcode_code -->
Code :

publicclass TestThread {
 
/**
* @param args
*/
publicstaticvoid main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
publicvoid run(){
/** Démarrage de l'interface graphique et du SwingWorker. **/
FrameTest frame = new FrameTest();
}
});
 
}
}

la classe pour la frame:
<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
package des.jet.appli.main.test;
 
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
 
import des.jet.appli.ihm.sortie.onglet1.Dessin;
import des.jet.appli.utils.business.Des;
import des.jet.appli.utils.business.Stat;
import des.jet.appli.utils.constantes.SortieOnglet1;
 
@SuppressWarnings("serial")
publicclass FrameTest extends JFrame implements SortieOnglet1{
private Dessin jDessin;
private JButton start;
private JButton exit;
private JButton stop;

private Collection<Des>cDes;
private ThreadSwingWorker swingWorker;

public FrameTest(){
init();
ajoutButton();
}
 
privatevoid ajoutButton(){
JPanel jPanelButtons = new JPanel();
this.getContentPane().add(jPanelButtons, "South");

start = new JButton("Start");
start.addActionListener(new GestionActionButton(this, 1));
jPanelButtons.add(start);

stop = new JButton("Stop");
stop.addActionListener(new GestionActionButton(this, 2));
jPanelButtons.add(stop);

exit = new JButton("Exit");
exit.addActionListener(new GestionActionButton(this, 3));
jPanelButtons.add(exit);
}
 
privatevoid init(){
/* Construction de l'interface graphique. */
this.setTitle("test Thread");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setBounds(400, 100, FRAME_RESULT_ONGLET1_WIDTH, FRAME_RESULT_ONGLET1_HEIGHT);

jDessin = new Dessin(new Stat(), Color.RED);
this.getContentPane().add(jDessin, "Center");
this.setVisible(true);

// ajout des dés pour les tests
cDes = new ArrayList<Des>();
cDes.add(new Des(9,5));
// cDes.add(new Des(5,6));
// cDes.add(new Des(15,10));

swingWorker = new ThreadSwingWorker(this);
}
 
public Dessin getJDessin(){
return jDessin;
}
 
publicvoid setJDessin(Dessin dessin){
jDessin = dessin;
}
 
public Collection<Des> getCDes(){
return cDes;
}
 
publicvoid setCDes(Collection<Des> des){
cDes = des;
}
 
public ThreadSwingWorker getSwingWorker(){
return swingWorker;
}
 
publicvoid setSwingWorker(ThreadSwingWorker swingWorker){
this.swingWorker = swingWorker;
}

}
 

<!-- END TEMPLATE: bbcode_code -->la classe pour dessiner dans le jpanel
<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
package des.jet.appli.ihm.sortie.onglet1;
 
import java.awt.Color;
import java.awt.Graphics;
 
import javax.swing.JPanel;
 
import des.jet.appli.utils.business.Stat;
import des.jet.appli.utils.constantes.SortieOnglet1;
 
@SuppressWarnings("serial")
publicclass Dessin extends JPanel implements SortieOnglet1{
private Stat dataStat;
private Color couleur;

public Dessin(Stat dataStat, Color couleur){
this.dataStat = dataStat;
this.couleur = couleur;
this.setBounds(10, 10, 200, 100);
 
}

@Override
publicvoid paintComponent(Graphics g){
super.paintComponent(g);
Rectangle R = new Rectangle(10, 10, FRAME_RESULT_ONGLET1_GRAPH_WIDTH + 10,
FRAME_RESULT_ONGLET1_GRAPH_HEIGHT + 10, Color.blue,g);

if(dataStat != null && dataStat.getLoiProba() != null && dataStat.getLoiProba().length != 0){
dessiner(g);
}
}
 
publicvoid dessiner(Graphics g){
int l, y, a;
double h = FRAME_RESULT_ONGLET1_GRAPH_HEIGHT / dataStat.getValMax();

if(dataStat.getLoiProba().length < FRAME_RESULT_ONGLET1_GRAPH_WIDTH){
l = FRAME_RESULT_ONGLET1_GRAPH_WIDTH / dataStat.getLoiProba().length;
a = 1;
}
else{
l = 1;
a = dataStat.getLoiProba().length / FRAME_RESULT_ONGLET1_GRAPH_WIDTH;
}

for(int x = 0; a * x < dataStat.getLoiProba().length; x++){
y = FRAME_RESULT_ONGLET1_GRAPH_HEIGHT - (int)(dataStat.getLoiProba()[a * x] * h);
new Rectangle(x * l + 15, y + 15, l, (int)(dataStat.getLoiProba()[a * x] * h), couleur, g);
}
}
 
publicvoid redessiner(Stat dataStat, Color couleur){
this.dataStat = dataStat;
this.couleur = couleur;
Graphics g = getGraphics();

g.clearRect(10, 10, FRAME_RESULT_ONGLET1_GRAPH_WIDTH + 10,
FRAME_RESULT_ONGLET1_GRAPH_HEIGHT + 10);

dessiner(g);
}
 
 
public Stat getDataStat(){
return dataStat;
}
 
 
 
publicvoid setDataStat(Stat dataStat){
this.dataStat = dataStat;
}

}
 

<!-- END TEMPLATE: bbcode_code -->la classe de thread:
<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
 
package des.jet.appli.main.test;
 
import java.awt.Color;
import java.util.List;
 
import javax.swing.SwingWorker;
 
import des.jet.appli.utils.business.Stat;
import des.jet.appli.utils.calculs.CalculsProgressifsUtils;
import des.jet.appli.utils.constantes.SortieOnglet1;
 
class ThreadSwingWorker extends SwingWorker<Stat, Stat> implements SortieOnglet1{
private FrameTest frame;
privateint boucle = 1;
privateint processe = 1;
privateboolean bFinish = true;

public ThreadSwingWorker(FrameTest frame){
this.frame = frame;
}
 
@Override
public Stat doInBackground(){
Stat stat = new Stat();

try{
while(bFinish){
Thread.sleep(DEFAULT_LOOP_WAIT);
stat = CalculsProgressifsUtils.getCalculsProgressifsUtils().boucleTirageAleatoire(stat, frame.getCDes(), 100);
publish(stat);
System.out.println("boucle n° : " + boucle);
boucle++;
 if(boucle DEFAULT_LOOP_NUMBER)bFinish false;
}
}
catch(InterruptedException e){
e.printStackTrace();
}

return stat;
}
 
@Override
protectedvoid process(List<Stat> stats){
/** Mise à jour du JPanel de dessin **/
System.out.println("processe n° : " + processe + " nb param dans process : " + stats.size());
Stat stat = stats.get(0);
stat.calculValMax();
frame.getJDessin().redessiner(stats.get(0), Color.RED);
processe++;
}
 
@Override
protectedvoid done(){
frame.setSwingWorker(new ThreadSwingWorker(frame));
}
 
publicboolean isBFinish(){
return bFinish;
}
 
publicvoid setBFinish(boolean finish){
bFinish = finish;
}

}
 

<!-- END TEMPLATE: bbcode_code -->la classe gérant les événements de boutons:
<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
package des.jet.appli.main.test;
 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.SwingWorker;
 
publicclass GestionActionButton implements ActionListener {
private FrameTest frameTest;
privateint choix;

public GestionActionButton(FrameTest frameTest, int choix){
this.frameTest = frameTest;
this.choix = choix;
}
 
@Override
publicvoid actionPerformed(ActionEvent arg0){
if(choix == 1){
if(frameTest.getSwingWorker().getState() != SwingWorker.StateValue.STARTED){
frameTest.getSwingWorker().execute();
}
}
elseif(choix == 2){
frameTest.getSwingWorker().setBFinish(false);
System.out.println("Stop");
}
elseif(choix == 3){
System.exit(0);
}
 
}
 
}
 

<!-- END TEMPLATE: bbcode_code -->toutes vos remarques sont les bienvenues car là je sèche, l'appli réagissant à l'opposé de ce que l'on pourrait croire.
Tueur de grenouille professionel en freelance

7 réponses

uhrand Messages postés 491 Date d'inscription samedi 20 mai 2006 Statut Membre Dernière intervention 15 juillet 2012 9
12 août 2008 à 09:35
Tu as oublié de nous montrer les classes "CalculsProgressifsUtils", "Des" et "Stat".
3
uhrand Messages postés 491 Date d'inscription samedi 20 mai 2006 Statut Membre Dernière intervention 15 juillet 2012 9
15 août 2008 à 00:49
Je ne vois rien qui se bloque: TestThread.jar (code source dans le jar)
3
uhrand Messages postés 491 Date d'inscription samedi 20 mai 2006 Statut Membre Dernière intervention 15 juillet 2012 9
15 août 2008 à 12:43
Parfois il ne se passe rien du tout, ça doit être ai niveau de ton algorithme. Je ne vois toujours rien qui se bloque au niveau de Swing.
3
theFrogkiller Messages postés 5 Date d'inscription lundi 11 août 2008 Statut Membre Dernière intervention 15 août 2008
12 août 2008 à 10:19
Je les déposerais ce soir en rentrant.

Tueur de grenouille professionel en freelance
0

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

Posez votre question
theFrogkiller Messages postés 5 Date d'inscription lundi 11 août 2008 Statut Membre Dernière intervention 15 août 2008
12 août 2008 à 19:17
Comme demandé voici les classes manquantes

la classe CalculsProgressifsUtils :
public class CalculsProgressifsUtils {
    private static CalculsProgressifsUtils calculsProgressifsUtils = new CalculsProgressifsUtils();
   
    public static CalculsProgressifsUtils getCalculsProgressifsUtils(){
        return calculsProgressifsUtils;
        }
   
    public Stat tirageAleatoire(Stat stat, Collection<Des>cDes){
        int result = 0;
        int sizeTab = 0;
        Iterator<Des> iDes = cDes.iterator();
       
        while(iDes.hasNext()){
            Des de = iDes.next();
            sizeTab += de.getNbDes() * de.getNbFaces();
           
            for(int i = 0; i < de.getNbDes(); i++){
                result += (int)(de.getNbFaces() * Math.random()) + 1;
                }
            }
       
            if(stat.getLoiProba() == null){
                stat.setLoiProba(new double[sizeTab]);
                }
            stat.getLoiProba()[result] = stat.getLoiProba()[result] + 1;
            return stat;
        }
   
    public Stat boucleTirageAleatoire(Stat stat, Collection<Des>cDes, int nbBoucles){
        for(int i = 0; i < nbBoucles; i++)
            stat = tirageAleatoire(stat, cDes);
       
        return stat;
        }
    }

la classe Des :
public class Des implements Comparable<Des>{
    private int nbFaces;
    private int nbDes;
   
    /** constructeurs **/
    public Des(int nbDes, int nbFaces) {
        this.nbDes = nbDes;
        this.nbFaces = nbFaces;
        }
   
    public Des(){}

    /** getters et setters **/
    public int getNbFaces() {
        return nbFaces;
        }
   
    public void setNbFaces(int nbFaces) {
        this.nbFaces = nbFaces;
        }
   
    public int getNbDes() {
        return nbDes;
        }
   
    public void setNbDes(int nbDes) {
        this.nbDes = nbDes;
        }
   
    @Override
    public String toString() {
        String s = nbDes + " dé";
        if(nbDes > 1){
            s += "s";
            }
        s += nbFaces;
        return s;
        }

    public void addDes(int nbDes) {
        this.nbDes += nbDes;
       
    }

    public void removeDes(int nbDes) {
        if(this.nbDes < nbDes){
            this.nbDes = 0;
        }
        else {
            this.nbDes -= nbDes;
            }
        }

    public String getNbFacesString() {
        if(nbFaces != 0){
            return String.valueOf(nbFaces);
            }
        return "";
        }

    public String getNbDesString() {
        if(nbDes != 0){
            return String.valueOf(nbDes);
            }
        return "";
        }

    @Override
    public int compareTo(Des o) {
        if(this.nbFaces > o.getNbFaces()){
            return 1;
            }
        else if(this.nbFaces < o.getNbFaces()){
            return -1;
            }
        return 0;
        }

la classe Stat :
public class Stat {
    private int nbDifferent;
    private double nbCas;
    private double moyenne;
    private double sigmaCarre;
    private double valMax;
    private double[] loiProba;
   
    public double getNbCas() {
        return nbCas;
    }
    public void setNbCas(double nbCas) {
        this.nbCas = nbCas;
    }
    public int getNbDifferent() {
        return nbDifferent;
    }
    public void setNbDifferent(int nbDifferent) {
        this.nbDifferent = nbDifferent;
    }
    public double getMoyenne() {
        return moyenne;
    }
    public void setMoyenne(double moyenne) {
        this.moyenne = moyenne;
    }
    public double getSigmaCarre() {
        return sigmaCarre;
    }
    public void setSigmaCarre(double sigma) {
        this.sigmaCarre = sigma;
    }
    public double getValMax() {
        return valMax;
    }
    public void setValMax(double valMax) {
        this.valMax = valMax;
    }
    public double[] getLoiProba() {
        return loiProba;
    }
    public void setLoiProba(double[] loiProba) {
        this.loiProba = loiProba;
    }
   
    public Stat clone(){
        Stat stat = new Stat();
       
        stat.setLoiProba(loiProba);
        stat.setMoyenne(moyenne);
        stat.setNbCas(nbCas);
        stat.setNbDifferent(nbDifferent);
        stat.setSigmaCarre(sigmaCarre);
        stat.setValMax(valMax);
       
        return stat;
        }
   
    public void calculParam(Des de) {
        moyenne = (double)((de.getNbFaces() + 1) *  de.getNbDes()) / 2;
        sigmaCarre = (double)((de.getNbFaces() - 1) * de.getNbFaces() * de.getNbDes()) / 12;
        nbCas = Math.pow(de.getNbFaces(), de.getNbDes());
        nbDifferent = 1;
        }
   
    public void calculValMax(){
        if(loiProba != null){
            for(int i = 0; i < loiProba.length; i++){
                if(loiProba[i] > valMax)valMax = loiProba[i];
                }
            }
        }
   
    public double getSigma(){
        return Math.pow(sigmaCarre, 0.5);
        }
       
    public void viewStat(){
        if(loiProba != null && loiProba.length != 0){
            for(int i = 0; i < loiProba.length; i++){
                String s = String.valueOf(i);
                while(s.length() < 15){
                    s += " ";
                    }
                System.out.println(s + loiProba[i]);
                }
            }
        }

Tueur de grenouille professionel en freelance
0
theFrogkiller Messages postés 5 Date d'inscription lundi 11 août 2008 Statut Membre Dernière intervention 15 août 2008
15 août 2008 à 01:45
effectivement c'est le fonctionnement attendu là ça bloque pour les paramètres suivants:
1- paramètres de bouclages et de sleep du thread dans l'interface:
    public static int DEFAULT_LOOP_WAIT = 50;
    public static int DEFAULT_LOOP_NUMBER = 1000;
2- valeur du dé dans la frame de test:
   cDes.add(new Des(3, 6));

il faut moins de 6 dés à 6 faces pour que les cycles se bloquent.

Tueur de grenouille professionnel en freelance
0
theFrogkiller Messages postés 5 Date d'inscription lundi 11 août 2008 Statut Membre Dernière intervention 15 août 2008
15 août 2008 à 14:09
effectivement j'ai pus mettre la main sur le problème qui proviens bien de l'algorithme.
cela viens d'une bette erreur d'indexoutbound de la méthode tirageAleatoire. lors d'un tirage aléatoire j'incrémente le tableau contenant les valeurs de la loi de probabilité.
je faisais :  stat.getLoiProba()[result] = stat.getLoiProba()[result] + 1t] au lieux de loiProga[resultat]
au lieu de : stat.getLoiProba()[result - 1] = stat.getLoiProba()[result - 1] + 1

dans un seul cas cela entraine une erreur. c'est lorsque l'on obtien la valeur maximale. evidement c'est l'évènement, avec le tirage de la plus petite valeur possible, qui a la plus faible probabilité expliquant ainsi pourquoi plus j'augmente le nombre de dés moins la boucle de raffraichissement se bloque. rien qu'avec 6 dés on a une probabilité qui tombe à 1/7776

enfin la raison principale pour ne pas avoir vus cela c'est que la méthode de tirage aléatoire est appellée dans la méthode ThreadSwingWorker.doInBackground() hors il fallait catché le Thread.sleep(500) par une InterruptedException du coup je n'ai pas vu l'IndexOutBoundException

pour avoir pris le temps de chercher mon erreur je me devais de fournir l'explication. Encore merci

Conclusion: il faut toujours tester unitairement ses méthodes!!!!
0
Rejoignez-nous