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

EDT/SwingWorker Java Discussion :

[SwingWorker] tâche longue interruptible


Sujet :

EDT/SwingWorker Java

  1. #1
    Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 50
    Points : 40
    Points
    40
    Par défaut [SwingWorker] tâche longue interruptible
    Bonjour à tous,

    je viens de lire et comprendre le tuto sur SwingWorker (http://rom.developpez.com/java-swingworker/), mais je n'arrive pas à l'adapter à mon cas.

    Voici ce que je voudrais faire :

    J'ai une Frame avec un bouton "Start".
    Lorsque je clique sur ce bouton, j'ouvre une boite de Dialog du style "veuillez patienter" avec une barre de progression et un bouton "Cancel", et en parallèle j'exécute un traitement qui dure assez longtemps.

    Seulement voilà, avec le code que j'ai écrit, la boîte de Dialog s'ouvre mais est "freezée", et ce pendant toute la durée du traitement qui tourne en parallèle, puis le traitement se termine et elle se "dé-freeze".

    Ce qui n'est évidemment pas le but recherché.

    Je vais mettre mon code ci-dessous, si quelqu'un peut me dire où je fais fausse route, ça m'aiderait.

    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
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
     
     
    public class MainFrame extends JFrame
    {
        private SwingWorker testSW;
     
        private SettingsPanel settingsPanel;
        private WaitDialog    waitDialog;
     
        /** Creates a new instance of MainFrame */
        public MainFrame () 
        {
            initComponents();
        }
     
        private void initComponents()
        {
            super ("Test SwingWorker");
            this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
     
            settingsPanel = new SettingsPanel();
            settingsPanel.getStartButton    ().addActionListener (new ActionListener() { public void actionPerformed(ActionEvent e) { startClicked    (); } });
     
            // WaitDialog() extends JDialog        
            waitDialog = new WaitDialog(this, false);
            waitDialog.setResizable (false);
            waitDialog.setDefaultCloseOperation (DO_NOTHING_ON_CLOSE);
            waitDialog.addWindowListener (new WindowAdapter() { public void windowClosing(WindowEvent e) { cancelProcess (); } } );
            waitDialog.setSize (300, 150);
            waitDialog.setMinimumSize (waitDialog.getSize ());
     
            waitDialog.getMessage().setText ("Process running...");
            waitDialog.getProgressBar  ().setIndeterminate (true);
            waitDialog.getCancelButton ().addActionListener (new ActionListener() { public void actionPerformed(ActionEvent e) { cancelProcess (); } });
     
            showSettingsPanel (true);
        }
     
        public void showSettingsPanel(boolean b)
        {
            if (b)
            {
                this.add(settingsPanel);
     
                this.pack();
     
                Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
                this.setLocation((screenSize.width  - this.getWidth ()) / 2,
                                 (screenSize.height - this.getHeight()) / 2);
     
            }
            else
            {
                this.remove (settingsPanel);
                this.setMinimumSize (new Dimension());
                this.pack ();
            }
        }
     
        public void showWaitDialog(boolean b)
        {
            if (b)
            {
                Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
                waitDialog.setLocation((screenSize.width  - waitDialog.getWidth ()) / 2,
                                       (screenSize.height - waitDialog.getHeight()) / 2);
                waitDialog.setVisible(true);
            }
            else
            {
                waitDialog.setVisible(false);
            }
        }
     
        private void startClicked()
        {
            // Show wait Dialog
            showWaitDialog (true);
            testSW = new TestSwingWorker();
            testSW.execute ();
            try{ System.out.println((String)compareSW.get ()); }
            catch (InterruptedException e) {System.out.println("interrompu");}
            catch (Exception e) {System.out.println("erreur");}
        }
     
        private void cancelProcess ()
        {
            System.out.println("Process cancelled");
            showWaitDialog (false);
            testSW.cancel (true);
        }
     
        public static void start()
        {
            EventQueue.invokeLater (new Runnable() 
            {
                public void run ()
                {
                    new MainFrame().setVisible(true);
                }
            });
        }
     
        class TestSwingWorker extends SwingWorker <String, String>
        {
            public TestSwingWorker () { super(); }
     
            protected String doInBackground()
            {
                System.out.println("[DEB] doInBackgroung()");
                // juste un test
                for (int i = 0; i < 5; i++)
                    try { Thread.sleep (1000); } catch (InterruptedException e) {}
     
                return "[FIN] doInBackground()";
            }
     
            protected void done()
            {
                System.out.println("Terminated");
            }         
        }
    }

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Déjà il y a quelque chose de bizarre dans ton code, je ne comprend pas comment ceci peut compiler :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	private void initComponents()
    	{
    		super ("Test SwingWorker");
    En effet l'appel au constructeur parent ne peut avoir lieu que dans les constructeurs...



    Quand à ton problème, il ne vient pas du SwingWorker en lui-même, mais de la manière dont tu récupère le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	testSW = new TestSwingWorker();
    	testSW.execute ();
    	try{ System.out.println((String)compareSW.get ()); }
    	catch (InterruptedException e) {System.out.println("interrompu");}
    	catch (Exception e) {System.out.println("erreur");}
    En effet : tu lances bien le traitement dans un autre thread, mais tu bloques le thread de l'EDT jusqu'à ce que ton autre thread se termine, afin de récupérer le résultat du traitement...

    Bref l'EDT est bloqué et ne peut donc pas mettre à jour l'affichage...

    Les 3 dernières lignes devraient plutôt se trouver dans la méthode done() de ton SwingWorker...

    a++

  3. #3
    Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 50
    Points : 40
    Points
    40
    Par défaut
    Oups pour le super il se trouve bien sûr dans le constructeur et non dans le initComponents

    Par contre, confère le tuto, la méthode done n'est pas forcément appelée en fin d'exécution. C'est pourquoi je préfère mettre le code de récupération du résultat à un autre endroit.

    J'ai aussi essayé de virer ces 3 lignes, sans rien mettre à la place, et j'obtiens toujours le freeze.
    Je ne comprend pas ce qui bloque l'EDT dans mon script.

    [Edit] : au temps pour moi, j'avais appelé la méthode run() au lieu de execute()... avec execute(), ça fonctionne.

    Pourrais-tu me dire comment tu ferais toi, sachant qu'après ce traitement long il y aura sûrement une phase de présentation des résultats dans un panel séparé par exemple. Je suis plutôt nul en dev graphique, je sais jamais où mettre mon code pour que ce soit propre.

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Tino13
    Oups pour le super il se trouve bien sûr dans le constructeur et non dans le initComponents
    Ok ca me rassure

    Citation Envoyé par Tino13
    Par contre, confère le tuto, la méthode done n'est pas forcément appelée en fin d'exécution. C'est pourquoi je préfère mettre le code de récupération du résultat à un autre endroit.
    Je viens de voir cela dans le tuto, mais j'ignore dans quel cas elle n'est pas appelée.

    Citation Envoyé par Tino13
    Pourrais-tu me dire comment tu ferais toi, sachant qu'après ce traitement long il y aura sûrement une phase de présentation des résultats dans un panel séparé par exemple. Je suis plutôt nul en dev graphique, je sais jamais où mettre mon code pour que ce soit propre.
    Perso j'aurais mis ca dans done()... mais là j'attend d'avoir plus d'info sur les cas où elle n'est pas appelée avant de répondre


    a++

  5. #5
    Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 50
    Points : 40
    Points
    40
    Par défaut
    Encore une fois je crois que j'ai été un peu trop vite.
    Pour avoir lu la Javadoc de l'API, rien ne parle de ce que done() n'est pas toujours appelée en fin de traitement.

    En fait, pour avoir relu le tuto, la méthode done() n'est pas toujours appelée après un appel à la méthode process(). Ce qui n'est pas mon cas en l'occurence.

    En fait, il faudrait me le confirmer, mais je pense que lorsqu'on fait un publish(), la méthode process() est appelée et ce que le tuto veut dire, c'est que la méthode done() est appelée [parfois] ensuite. C'est pourquoi ils recommendent de remplir le textArea depuis process() et non pas depuis done().

    Je pense que c'est bon, il ne me manque plus qu'un petit cours d'archi des applications graphiques...

    Merci pour ta réactivité en tout cas adiGuba

  6. #6
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Salut,

    En fait, ce que j'ai voulu dire dans le tuto, c'est qu'il n'y a pas de garantie sur l'ordre d'exécution entre les process() et le done().
    Le done() n'est pas forcément APRES les process(), il peut etre AVANT, ou AU MILIEU DE.

    Mais il est toujours appelé.

    Par exemple pour 3 process, 4 possibilités d'entrelacement:
    done() process() process() process()
    process() done() process() process()
    process() process() done() process()
    process() process() process() done()

  7. #7
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ®om
    Salut,

    En fait, ce que j'ai voulu dire dans le tuto, c'est qu'il n'y a pas de garantie sur l'ordre d'exécution entre les process() et le done().
    Le done() n'est pas forcément APRES les process(), il peut etre AVANT, ou AU MILIEU DE.

    Mais il est toujours appelé.
    Ok cela me rassure

    Mais ce problème d'ordonnancement est quand même bizarre... il faudrait que j'y jettes un coup d'oeil quand j'ai le temps...

    a++

  8. #8
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par adiGuba
    Ok cela me rassure

    Mais ce problème d'ordonnancement est quand même bizarre... il faudrait que j'y jettes un coup d'oeil quand j'ai le temps...

    a++
    C'est simplement en faisant moi-meme un test que je m'en suis aperçu, je ne l'ai pas vu dans la doc

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 23
    Points : 34
    Points
    34
    Par défaut
    salut,
    adiGuba
    Mais ce problème d'ordonnancement est quand même bizarre... il faudrait que j'y jettes un coup d'oeil quand j'ai le temps...

    a++
    cela m'interesse parceque moi, par exemple, dans la méthode done() je dois activer ou désactiver le bouton ok . Donc j'ai besoin d'être sure que la méthode done() s'exécute après tous les process . n'y a t'il pas un moyen de faire ca ????

  10. #10
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Perso je n'ai jamais réussi à mettre ce problème en évidence...

    a++

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

Discussions similaires

  1. Executer 200 fois en parallèle une tâche longue
    Par Arnard dans le forum Framework .NET
    Réponses: 1
    Dernier message: 16/09/2014, 11h21
  2. Exécuter une tâche longue depuis un JPanel
    Par eat your potato dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 03/04/2013, 18h51
  3. Reprise du travail après longue interruption
    Par AnneFM dans le forum Emploi
    Réponses: 2
    Dernier message: 17/12/2007, 17h51
  4. Bloquer l'interface sur tâche longue
    Par danje dans le forum Interfaces Graphiques en Java
    Réponses: 3
    Dernier message: 05/12/2005, 00h32

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