Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Sujet : problème entre Swing et SwingWorker [ Multimédia / Java2D ] (theFrogkiller)

lundi 11 août 2008 à 13:25:44 | problème entre Swing et SwingWorker

theFrogkiller

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:
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:
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;
}


}
 
la classe pour dessiner dans le jpanel
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;
}


}
 
la classe de thread:
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;
}

}
 
la classe gérant les événements de boutons:
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);
}
 
}
 
}
 
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

mardi 12 août 2008 à 09:35:34 | Re : problème entre Swing et SwingWorker

uhrand

Réponse acceptée !
Tu as oublié de nous montrer les classes "CalculsProgressifsUtils", "Des" et "Stat".

mardi 12 août 2008 à 10:19:36 | Re : problème entre Swing et SwingWorker

theFrogkiller

Je les déposerais ce soir en rentrant.

Tueur de grenouille professionel en freelance

mardi 12 août 2008 à 19:17:24 | Re : problème entre Swing et SwingWorker

theFrogkiller

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

vendredi 15 août 2008 à 00:49:01 | Re : problème entre Swing et SwingWorker

uhrand

Réponse acceptée !
Je ne vois rien qui se bloque: TestThread.jar (code source dans le jar)

vendredi 15 août 2008 à 01:45:47 | Re : problème entre Swing et SwingWorker

theFrogkiller

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

vendredi 15 août 2008 à 12:43:57 | Re : problème entre Swing et SwingWorker

uhrand

Réponse acceptée !
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.

vendredi 15 août 2008 à 14:09:17 | Re : problème entre Swing et SwingWorker

theFrogkiller

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!!!!



Cette discussion est classé dans : appli, frame, import, stat, datastat


Répondre à ce message

Sujets en rapport avec ce message

Probleme lors d'une copie de fichier [ par asetti ] Slt, j'ai créer ce code juste pour essayer (avant de coder pour de bon) de copier un fichier "C:/a.txt" dans "C:/nn/a.txt".pour ça et comme je ne mait Bouton créant un bouton [ par kanagan ] Bonjour, Voilà, j'ai un petit problème, je veux créer un bouton qui, lorsque l'on clique dessus, crée un autre bouton. Cependant je n'arrive pas à af JTextArea [ par patRachel ] <img style="BORDER-LEFT-COLOR: black; BORDER-BOTTOM-COLOR: black; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black; border-siz [debutant] image dans un jar [ par jeremeclip ] bonjour voici mon probleme. Je viens de faire une petite application donc dans cette application je doit avoir une image de fond et par dessu j'ia des Gestion des frames en AWT [ par kalf2000 ] Salut! voila je voudrais savoir comment mis prendre pour gérer une appli avec plusieur frame. en faite l'idée serait d'avoir une succession de frame 3D [ par papse ] Bonjour à  tousje suis élève ingénieur et j'ai un mini projet qui consiste à développer une application faisant des Frame prioritaire? [ par yamxx ] Je voudrait pouvoir lancer une JFrame qui s'affiche toujours même si le CPU est à 100%.Parce qu'en fait j'ai une appli qui recherche des fichiers sur JEditorPane et Applets [ par louatiamin ] le code est mis en ba il permet de charger des pages html dans un panel JEditorPanebon le probleme est que lorsque la page a charger elle meme contien frame Jframe ??? [ par Ftiti ] bonjour a tousJe vient vous demande quel est la différence entre une frame et une Jframe Que peut ton faire de plus avec l'une ou l'autre Quelle est l Parser du XML avec JDOM en java [ par red210 ] Voila je pose une ptit questin concernant le XML... Je viens tout juste de lire un super tuto pour lire et générer du XML ca me pousse à m'y mettre ca


Nos sponsors

Sondage...

CalendriCode

Décembre 2008
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

Téléchargements



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,374 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.