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 :

Utilisation de SwingUtilities.invokeLater


Sujet :

AWT/Swing Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 176
    Points : 124
    Points
    124
    Par défaut Utilisation de SwingUtilities.invokeLater
    Bonjour tout le monde,

    J'ouvre cette petite discussion car malgré mes recherches sur internet, je ne comprends pas toujours pas l'utilité et même l'obligation d'utiliser cette méthode pour mettre à jour mes interfaces graphiques.
    Je viens de corriger un bug en utilisant justement cette méthode.
    J'avais une interface graphique qui ne se mettait pas à jour quand je faisais les modifications dans le thread principal.
    J'ai mis toutes les modifications dans une méthode invoqué par le run de mon SwingUtilities.invokeLater.
    Et là magie tout marche correctement mais je ne comprends pas pourquoi.
    Est-ce que vous pourriez me l'expliquer?

    Merci.

    Bonne journée.

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Parce que pour la plupart (sauf indication de la doc), les composants Swing ne sont pas thread safe, c'est à dire pas manipulables par plusieurs threads simultanément.
    Le seul thread autorisé à les modifier est l'EDT, responsable également de la boucle des événements.
    Donc pour éviter les bugs étranges, en cas de tâche longue, un accès à une base de données, un appel de web service, tu es censé utiliser un autre thread, pour ne pas bloquer le fameux EDT, et quand tu veux afficher les données issues de ton traitement, tu dois utiliser
    la méthode invokeLater par exemple. Tu peux utiliser également la classe Swingworker qui encapsule tout ça plus proprement.

  3. #3
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Anubis Voir le message
    J'ouvre cette petite discussion car malgré mes recherches sur internet, je ne comprends pas toujours pas l'utilité et même l'obligation d'utiliser cette méthode pour mettre à jour mes interfaces graphiques.

    J'avais une interface graphique qui ne se mettait pas à jour quand je faisais les modifications dans le thread principal.
    Tu réponds toi même à la question: parce que en dehors de l'EDT, les modifications faites sur des composants graphiques, c'est la roulette russe.

    Il y a même carrément des skins swing qui détectent les modifications en dehors de l'EDT et t'envoient joyeusement chier avec une exception.

    Bref la raison est la suivante: parce que la doc de java te dit qu'il FAUT faire comme ça et parce que quand tu ne le fais pas comme ça, parfosi ça foire

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 176
    Points : 124
    Points
    124
    Par défaut
    Citation Envoyé par fr1man Voir le message
    Parce que pour la plupart (sauf indication de la doc), les composants Swing ne sont pas thread safe, c'est à dire pas manipulables par plusieurs threads simultanément.
    Le seul thread autorisé à les modifier est l'EDT, responsable également de la boucle des événements.
    Donc pour éviter les bugs étranges, en cas de tâche longue, un accès à une base de données, un appel de web service, tu es censé utiliser un autre thread, pour ne pas bloquer le fameux EDT, et quand tu veux afficher les données issues de ton traitement, tu dois utiliser
    la méthode invokeLater par exemple. Tu peux utiliser également la classe Swingworker qui encapsule tout ça plus proprement.
    Donc si je comprends bien ce que tu dis;
    Les plupart des composants Swing n'étant pas thread safe, alors il faut pour mettre à jour l'interface graphique ("mettre à jours les composants Swing") faire exécuter ces modifications par le biais de la méthode invokeLater de la classe SwingUtilities. En faisant ainsi, je protège mon application de tous problèmes de mise à jour de l'interface graphique.

    Cependant, puis-je créer mon propre thread qui fera la mise à jour des composants Swing à l'aide des méthodes par exemple "setText" et autre en fonction des différents composants où dois-je obligatoirement passer par la méthode "invokeLater"?
    Je n'ai aucunement l'intention de faire une telle chose, mais l'utilisation de cette méthode est encore un peu flou pour moi et j'essaie de bien comprendre son fonctionnement.

    Merci.

    Bonne journée.

  5. #5
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Anubis Voir le message
    Cependant, puis-je créer mon propre thread qui fera la mise à jour des composants Swing à l'aide des méthodes par exemple "setText" et autre en fonction des différents composants où dois-je obligatoirement passer par la méthode "invokeLater"?
    Non. Il y a des traitements déclenchés par SWING dans son propre thread, sur lesquels tu n'as pas de contrôle : les traitements que tu effectuerais dans ton thread entreraient en concurrence avec ces traitements. De toute manière, l'exécution des mises à jour des composants graphiques est imposé dans ce thread par les spécifications : donc le code des jvm s'appuie sur cette directive. Libre à toi de ne pas le faire, et d'en subir les conséquences. Par exemple, avec les jvm Apple, cela pouvait causer des crashs de la jvm (j'écris "pouvait", car Oracle a repris le développement des jvm macosx depuis Java 7). Beaucoup le font justement pour lancer l'application (la première JFrame), et ça ne pose pas trop de problèmes en général, parce qu'il y a peu d'interactions concurrentes entre ce qu'on fait dans la méthode main() et ce qu'il se passe dans la JFrame (Rigoureusement, pourtant, il faudrait le faire).

    Cependant, rien ne t'empêche de faire des threads qui font des traitements en vue de préparer des mises à jour de l'interface graphique, et de, finalement, appliquer ces mises à jour dans un invokeLater. La classe SwingWorker en est justement un exemple intégré pour simplifier la mise en œuvre de ce genre de choses.

    A noter qu'il existe l'équivalent en SWT : la méthode asyncExec() correspond à invokeLater() et syncExec() à invokeAndWait (Des noms peut-être qui ont plus de sens - exécution asynchrone, exécution synchrone). Dans SWT, l'implémentation vérifie que le thread est le thread graphique, et dans le cas contraire soulève une exception. On peut toutefois créer plusieurs threads graphiques et les exécuter en parallèle, pour des interfaces séparées (qui ne peuvent communiquer ensemble que par asyncExec() et syncExec()).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 176
    Points : 124
    Points
    124
    Par défaut
    Merci. Je comprends bien mieux comment invokeLater et la mise à jour des composants Swing fonctionne.

    Citation Envoyé par joel.drigo Voir le message
    Cependant, rien ne t'empêche de faire des threads qui font des traitements en vue de préparer des mises à jour de l'interface graphique, et de, finalement, appliquer ces mises à jour dans un invokeLater. La classe SwingWorker en est justement un exemple intégré pour simplifier la mise en œuvre de ce genre de choses..
    Quand tu parles de préparer les mises à jour dans un autre thread, tu veux dire qu'il est possible de faire des setText, setColor,... dans un thread autre que le EDT et ensuite tu fais un invokeLater avec par exemple un appel à validate sur le composant?

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    non, ca veux dire que, par exemple, si le texte dois venir d'un fichier à lire sur le disque ou d'un serveur web, tu peux aller chercher ce texte dans une autre thread et ne mettre dans le invokeLater / invokAndWait que la partie setText


    exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public void run(){
         try {
               StringWriter sw = new StringWriter();
               Reader r = new InputStreamReader(new URL("http://www.developpez.net").openStream());
               IOUtils.copy(r,sw);
               final String content = sw.toString();
               SwingUtilities.invokeLater( ()-> textPane.setText(content) ); // Une lambda juste pour écrire plus court :p
         } catch (Exception e){ // pour l'exemple, faut mieux gérer que ça en pratique :)
            e.printStackTrace();
         }
    }

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 176
    Points : 124
    Points
    124
    Par défaut
    OK. Merci.
    Tout ceci est plus clair maintenant.

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

Discussions similaires

  1. Ne break plus après SwingUtilities.invokeLater()
    Par Julien Bodin dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 07/08/2009, 13h10
  2. Retour valeur SwingUtilities.invokeLater
    Par SebastianPx dans le forum EDT/SwingWorker
    Réponses: 8
    Dernier message: 30/03/2009, 12h02
  3. SwingUtilities.invokeLater : à quoi ça sert ?
    Par ANOVA dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 16/12/2007, 19h10
  4. SwingUtilities.invokeLater casse mon redimensionnment
    Par Baptiste Wicht dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 01/06/2007, 10h42
  5. Réponses: 17
    Dernier message: 10/07/2006, 19h13

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