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 :

Demande d'explication sur un MouseListener [Débutant(e)]


Sujet :

AWT/Swing Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Debutant Java
    Inscrit en
    Avril 2015
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Debutant Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2015
    Messages : 11
    Par défaut Demande d'explication sur un MouseListener
    Bonjour à tous,

    Ci-dessous ce trouve un petit code qui affiche un JFrame qui contient un JPanel de couleur rouge. Lorsque nous cliquons dessus, l'arrière-plan devait passer du bleu, au jaune après une légère temporisation. Mais en fait, pas du tout...
    Es ce que vous pouvez m'expliquer pourquoi la commande "pan.setBackground(Color.BLUE);" est complètement ignoré ?




    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
    package test;
    import java.awt.Color;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
    public class Fenetre extends JFrame{
     
    public Fenetre() {   
    	this.setSize( 200 , 200 );
    	this.setLocationRelativeTo(null);
    	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    	JPanel pan = new JPanel();
    	pan.setBackground(Color.RED);
    	pan.addMouseListener(new java.awt.event.MouseAdapter() {
    		public void mouseClicked(java.awt.event.MouseEvent me) {
    			pan.setBackground(Color.BLUE);
    			tempo(5);
    	    	        pan.setBackground(Color.YELLOW);
    			}});
     
    	this.setContentPane(pan);
    	this.setVisible(true);
    }
    	private void tempo(int t) {
    		for(int i = 1; i <= t; i++)
    		{ try{ Thread.sleep(t*100); }
    		catch (InterruptedException e){e.printStackTrace(); } }
    	}
    }

  2. #2
    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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Salut,

    Swing (comme d'autres type d'environnement graphique), utilise une thread unique, appelé Event Dispatch Thread (EDT), pour gérer l'affichage (le dessin en particulier), et la réaction aux évènements (interaction).

    Un thread ne peux exécuter qu'une seule chose à la fois. Donc lorsque que tu cliques et que ça génère un MouseEvent, le code correspondant s'exécute dans l'EDT, et tout ce que tu y fais bloque l'affichage pendant ce temps, jusqu'à ce que ton code soit fini, ce qui donne l'occasion à Swing de lancer d'autres méthodes qui vont s'exécuter également dans l'EDT pour mettre à jour l'affichage. Donc tu ne peux pas voir de progression de l'affichage quand le code est dans l'EDT : on ne voit que le résultat final, quand la méthode est terminée (donc tu vois ton composant tout jaune, sans passer par le bleu). C'est vrai en particulier dans les boucles d'attente (les sleep()) : si tu fais un sleep() de 30 secondes dans l'EDT : tout l'affichage est figé pendant 30 secondes et l'application ne peut plus recevoir d'évènements souris ou clavier.

    Pour pouvoir faire ça, il faut justement exécuter le code dans un autre thread : pendant qu'il s'exécute, Swing peut continuer à faire ce qu'il a faire, et entre autre mettre à jour l'affichage. Pour faire ce que tu veux faire il y a un moyen simple : javax.swing.Timer. Il a le double avantage d'exécuter des boucles d'attente dans son propre thread, mais d'exécuter le code utile dans le thread swing, par l'intermédiaire d'un évènement (ActionEvent).

    Exemple :

    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
    public class Fenetre extends JFrame {
     
    	public Fenetre() {
    		this.setSize(200, 200);
    		this.setLocationRelativeTo(null);
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		JPanel pan = new JPanel();
    		pan.setBackground(Color.RED);
    		pan.addMouseListener(new java.awt.event.MouseAdapter() {
    			public void mouseClicked(java.awt.event.MouseEvent me) {
     
    				pan.setBackground(Color.BLUE);
     
    				new ExecuteAfter(500, e -> pan.setBackground(Color.YELLOW));
     
    			}
    		});
     
    		this.setContentPane(pan);
    		this.setVisible(true);
    	}
     
    	public static class ExecuteAfter {
     
    		public ExecuteAfter(int time, ActionListener listener) {
    			Timer timer = new Timer(time, e -> execute(e, listener));
    			timer.start();
    		}
     
    		private void execute(ActionEvent event, ActionListener listener) {
    			((Timer) event.getSource()).stop();
    			listener.actionPerformed(event);
    		}
     
    	}
     
    	public static void main(String[] args) {
    		new Fenetre();
    	}
     
    }
    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.

  3. #3
    Membre averti
    Homme Profil pro
    Debutant Java
    Inscrit en
    Avril 2015
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Debutant Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2015
    Messages : 11
    Par défaut
    Bonjour,

    Merci beaucoup pour cette réponse très claire et explicative. C'est exactement ce que je recherchais.
    Grace à toi, j'ai pu faire des recherches complémentaires sur les 3 threads qui sont lancé d'office avec java.
    Du coup, afin de mieux comprendre, j'ai essayé de coder différentes solutions.
    Par exemple :

    J’ai créé un nouveau thread du genre Thread t = new Thread.... et dans le run mettre la tempo. Mais j'ai très vite abandonné l'idée car c'était vraiment stupide...

    Ensuite je suis tombé sur les commandes, invokelater et invokandwait. Je m'y suis plus attardé car ces deux solutions fonctionnent. Voici le code de mon mouselistener

    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
    new Thread(new Runnable(){
    public void run(){
    	for(int i = 0; i <= 5; i++){
    		try { Thread.sleep(300); } 
    		catch (InterruptedException e){e.printStackTrace(); }}
    	Thread t = new Thread(new Runnable(){
    	public void run(){
    		pan.setBackground(Color.BLUE); }});
    		if(SwingUtilities.isEventDispatchThread()) {
    			t.start(); }
    		else{
    			SwingUtilities.invokeLater(t); }
    //		try { SwingUtilities.invokeAndWait(t); }
    //		catch (InvocationTargetException | InterruptedException e) { e.printStackTrace(); }}
     
    }}).start(); 
    pan.setBackground(Color.YELLOW);
    Ces deux méthodes marche très bien, et si j'ai tout compris, à la première ligne je crée un nouveau thread sur lequel je peux lancer des tempo sans problème, ensuite avec le if je vérifie que le thread EDT soit libre avant pouvoir exécuter le run qui contient la commande du changement de couleur.

    J'ai aussi lu que dans certain cas il faut mieux utiliser la class swingworker, mais l'utilisation et la syntaxe ont l'air vraiment plus compliqués.

    Pour en revenir au swing.Timer. Bien que la solution de Joël fonctionne à la perfection, je me demandais si nous pouvions simplifier le code de cette manière.

    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
    package test;
     
    import java.awt.Color;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.lang.reflect.InvocationTargetException;
     
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
     
    public class Test extends JFrame {
    private Timer timer;
    	public Test() {
    		this.setSize(200, 200);
    		this.setLocationRelativeTo(null);
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		JPanel pan = new JPanel();
    		pan.setBackground(Color.RED);
    		pan.addMouseListener(new java.awt.event.MouseAdapter() {
    		public void mouseClicked(java.awt.event.MouseEvent me) {
     
    	pan.setBackground(Color.BLUE);
     
    	ActionListener action = new ActionListener() {
     
    		public void actionPerformed(ActionEvent event) {
    			timer.stop();
    			pan.setBackground(Color.YELLOW);
    		}
    	};
     
    	timer = new Timer (600, action);
    	timer.start();
    	}});
     
    	this.setContentPane(pan);
    	this.setVisible(true);
    }
     
    public static void main(String[] args) {
    		new Test();
    }
    }
    Bien que ce code "raccourcie" marche bien, je me doute bien que Joël ne s’est pas ennuyé à taper des lignes de commande sans raison. Quelle en sont alors les différences majeur?

    Dans le but de l'apprentissage je me pose la question suivante, dans quel cas on doit utiliser l'une ou l'autre des méthodes.
    J'imagine que dans le cadre d’une petite tempo on utilise un timer, et que les autres sont réservé à des traitements plus long (exemple calcule de PI a 1000 décimal) non?

  4. #4
    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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par ludovic01 Voir le message
    Ces deux méthodes marche très bien, et si j'ai tout compris, à la première ligne je crée un nouveau thread sur lequel je peux lancer des tempo sans problème, ensuite avec le if je vérifie que le thread EDT soit libre avant pouvoir exécuter le run qui contient la commande du changement de couleur.
    Ouille ! Ouille ! Ouille !

    Ce code est bien compliqué, superfétatoire, et démontre de confusions.

    Tout d'abord,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for (int i = 0; i <= 5; i++) {
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    Autant écrire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        try {
            Thread.sleep(6*300);
        } catch (InterruptedException e) {
             // ici - voir explication
        }
    }
    Pourquoi faire une boucle, alourdissant le code, et parfaitement inutile, à moins qu'on veuille vraiment avoir un fonctionnement où l'interruption couperait l'attente de 300ms en cours (ce qui fonctionnellement n'est pas impossible, certes, mais dans quel contexte serait-ce nécessaire. De plus, le <=5 est trompeur, car on fait 6 itérations : toujours préférer des bornes explicites afin qu'une lecture rapide du code ne trompe pas sur ce qu'il fait. En plus, le 6*300 étant évalué à la compilation, on ne perd pas de temps inutile en calculs inutiles.
    Ensuite, pour l'interruption : en théorie, s'il y a un interruption, on devrait arrêter immédiatement le thread. Il y aura interruption par exemple si on fait CTRL-C sur l'application : on veut que l'application s'arrête de suite, pas que l'attente reprenne et que le panneau change de couleur. Surtout que comme l'application s'arrête, il n'est pas impossible que les éléments qu'on veuille manipuler soient passer dans un état qui ne permet plus de manipulation et on obtiens une erreur. On pourrait dire que ce n'est pas important parce que le programme s'arrête, mais en dehors du fait que ce n'est jamais très propre un programme qui fait des erreurs, on peut avoir le risque que le programme ne s'arrête pas comme voulu (ce qui peut avoir d'autres conséquences : des ressources systèmes pas libérées, comme des ports réseaux par exemple.

    Ensuite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (SwingUtilities.isEventDispatchThread()) {
    					t.start();
    				} else {
    					SwingUtilities.invokeLater(t);
    				}
    Ceci est parfaitement inutile.
    Si on est dans thread construit par new Thread(), alors on n'est forcément en dehors de l'Event Dispatch Thread. Inutile de le tester. On peut avoir ce genre de construction lorsqu'on fait une classe d'exécution susceptible de s'exécuter dans différents contextes, et qu'on veut que la méthode appelée réagisse correctement au thread courant.
    En plus, le thread t exécutes un code manifestement SWING : le fait de faire t.start() exécutera ce code de toute manière dans un thread à part.

    En gros tu as écrit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    si le thread est l'EDT
        exécuter mon code dans un thread à part
    sinon
        exécuter mon code dans l'EDT
    Pas très logique.

    La construction prend son sens plutôt avec un Runnable :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Runnable moncode = ()-> pan.setBackground(Color.Blue);
    if (SwingUtilities.isEventDispatchThread()) [
       moncode.run();
    } else {
       SwingUtilities.invokeLater(moncode);
    }
    Qui veut dire : mon code est toujours exécuté dans l'EDT, quelque soit le thread qui l'invoque


    Citation Envoyé par ludovic01 Voir le message
    J'ai aussi lu que dans certain cas il faut mieux utiliser la class swingworker, mais l'utilisation et la syntaxe ont l'air vraiment plus compliqués.
    C'est le cas lorsqu'on fait des tâches longues, qui pourraient donc bloquer l'EDT longtemps (donc bloquer l'affichage et l'interaction). Au contraire, pour un code équivalent en termes fonctionnelles, le SwingWorker est bien plus simple parce que moins verbeux. Son principe est simple, à base de en gros trois méthodes, à implémenter :

    • doInbackground() : on y met le code qu'on veut exécuter hors de l'EDT (tout ce qui s'y trouve s'exécute dans un thread à part), et on appelle publish() pour publier ce qui doit servir aux mises à jour de l'affichage
    • process() : on y met le code qui met à jour l'affichage en fonction de ce qui est publié par publish() dans la méthode doInBackground. Le code de cette méthode s'exécute sur l'EDT
    • done() : on y produit le résultat final du traitement



    Citation Envoyé par ludovic01 Voir le message
    Pour en revenir au swing.Timer. Bien que la solution de Joël fonctionne à la perfection, je me demandais si nous pouvions simplifier le code de cette manière.
    Oui on peut.
    Citation Envoyé par ludovic01 Voir le message
    Bien que ce code "raccourcie" marche bien, je me doute bien que Joël ne s’est pas ennuyé à taper des lignes de commande sans raison. Quelle en sont alors les différences majeur?
    Alors :
    1. On n'est plus en 1970 où l'octet de mémoire coûte cher et où on cherche à économiser du code. Un code n'est pas seulement fait pour s'exécuter : il est impératif de pouvoir le maintenir, et donc qu'il soit lisible (et qu'il est un sens fonctionnel quand on le lit. On privilégie donc la lisibilité à l'économie de code. Et la lisibilité passe plus par la sémantique que par la technique (et des classes anonymes et des variables d'état non sémantique).
    2. Par contre, on ne cherche pas à taper du code juste pour se faire plaisir : on cherche à faire du code réutilisable. On le tape une fois : et ensuite on l'utilise/le réutilise. Ceci à plusieurs avantages :
      • On le met au point une seule fois : ensuite on peut lui faire confiance quand on utilise. Surtout quand c'est quelqu'un d'autre qui l'a fait. la plupart de l'écriture d'une programme en Java, c'est utiliser des classes faites par d'autres. Pourquoi ne pas inclure des classes écrites par soit (dans d'autres programmes éventuellement).
      • Le fait d'isoler une fonction permet de l'utiliser partout, sans avoir à la réécrire à chaque fois, sans qu'il n'y ait d'interaction ou d'adaptation particulière. Toi ce que tu vois c'est que dans ton petit exercice, tu le tapes qu'une fois, et effectivement ça fait un peu moins de code. Moi, ce que je vois, c'est que j'ai fait une classe qui permet d'exécuter une tâche Swing avec un délai, qui peut être réutilisée par n'importe qui, n'importe quand ce besoin est nécessaire. C'est comme pour la classe javax.swing.Timer : on peut écrire aussi un thread, avec un sleep, puis qui fait un invokeLater, et on a pas de besoin d'action, ou d'arrêter le thread explicitement. Mais si tu regardes le code de la classe Timer, il y a bien plus de code que ça. Parce qu'elle fait de nombreuses choses, mais aussi parce qu'elle les fait de manière plus générale, et plus clean. Elle est utilisable dans différents contextes, en gérant au mieux les conflits et différentes subtilités (auxquelles tout le monde ne pense pas forcément).
      • En Java, il n'est pas interdit de faire des classes. Au contraire. Cette façon de programmer en foutant des classes anonymes et des variables à état en plein milieu d'une classe où elles n'ont rien à faire convient à peine à de petits POC, exercices ou TP. Dans une application de production, on a besoin d'une meilleure organisation, d'une meilleure répartition, d'isolation du code, de modularité, etc... En outre, le fait de ne pas avoir d'état du tout limite les risques (et c'est d'ailleurs dans cette optique que j'ai préféré ne pas mettre un code comme celui que tu as écrit). J'aurais pu aussi utiliser la méthode setRepeats(false), mais je préférais arrêter le timer explicitement plutôt que de le laisser s'exécuter qu'une seule fois de manière moins ostensible, pour l'exemple.

      bien sûr, il ne s'agit pas de taper du code inutile comme dans ton implémentation au début de ton message.



    Pour le choix entre Timer, SwingWorker, ExecutorService(tu n'en a pas parlé de ça) et Thread, je dirais que ça dépend un peu du contexte. Le Thread c'est quand on a besoin et qu'on a pas déjà une implémentation qui fait la même chose (il faut maîtriser plus pour l'utiliser : ce n'est pas parce qu'on écrit moins de code, qu'il ne faudrait pas en écrire en réalité plus). Le SwingWorker n'est pas seulement nécessaire quand on fait des calculs qui durent des heures : bloquer l'UI pendant 500 ms peut-être irritant, surtout si c'est toutes les secondes ! Le Timer permet d'éviter d'avoir à jongler entre EDT et autre thread.
    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.

  5. #5
    Membre averti
    Homme Profil pro
    Debutant Java
    Inscrit en
    Avril 2015
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Debutant Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2015
    Messages : 11
    Par défaut
    Bonsoir,

    En premier, je voulais remercier Joël d'avoir une telle patience pour avoir le courage de répondre aux questions de débutant tel que moi....


    Ensuite, pour les try catch :
    Si j’ai bien compris, et si je veux coder proprement, je dois gérer mes exceptions en manuel avec un code du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    try{
    ...
    }catch (GestionExceptuionX e ) { }
     
    public gestionExeception extends Exception {
         public GestionExecptionX(){
              ...
         }
    }

    Pour la solution du invokeLateret invokeAndWait, il me semblait bien avoir créé mes thread avec l'option runnable (bien que je ne saisisse pas encore bien la différence (mais cela fera peux être, voir surement l'objet d'un nouveau topic, que dis-je, d'un nouveau thread, lol)) avec la commande :
    Thread t = new Thread(new Runnable(){

    Aussi, si par exemple en plus de faire passer mon JPanel en jaune, je souhaite lui ajouter une image via ImageIcone, puis lui ajouter, je ne sais pas, un JtextField aussi. Dans ce cas-là, ne suis-je pas obligé de créer un objet via "ActionListener action = new ActionListener() {...}"en plein milieu de mon code pour le faire? Un peu comme dans mon exemple.


    Enfin, une dernière question qui prouve mon "absolu debutance" (je sais cela n'existe pas dans le dico) Que signifie le "e" et plus précisément le "e ->"

  6. #6
    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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par ludovic01 Voir le message
    Si j’ai bien compris, et si je veux coder proprement, je dois gérer mes exceptions en manuel avec un code du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    try{
    ...
    }catch (GestionExceptuionX e ) { }
     
    public gestionExeception extends Exception {
         public GestionExecptionX(){
              ...
         }
    }
    Oui, c'est bien mieux de gérer ses propres exceptions avec des classes qui étendent Exception ou RuntimeException que de faire un throw new Exception. Cela permet d'avoir des catch dédiés et de traiter chaque cas d'exception. Attention toutefois à ne pas créer des exceptions qui existent déjà en standard : c'est bien mieux d'utiliser une exception standard en général, car elle aura du sens pour n'importe quel développeur. En particulier lorsqu'on fait des API. Par exemple IllegalArgumentException lorsqu'un argument intraitable est passé à une méthode, ou une ArtichmeticException lorsqu'il s'agit d'un calcul artihmetique infaisable, ou encore une NullPointerException pour un argument null, un IllegalStateException pour une appel de méthode qui ne peut être fait pour un état donné, UnsupportedOperationException pour une méthode non encore implémentée, IndexOutOFBoundException pour un dépassement d'index, NoSuchElementException lors qu'on ne peut produire d'élément (par exemple pour un pool qui atteint un max) etc.

    Citation Envoyé par ludovic01 Voir le message
    exxxxxx
    Pour la solution du invokeLateret invokeAndWait, il me semblait bien avoir créé mes thread avec l'option runnable (bien que je ne saisisse pas encore bien la différence (mais cela fera peux être, voir surement l'objet d'un nouveau topic, que dis-je, d'un nouveau thread, lol)) avec la commande :
    Thread t = new Thread(new Runnable(){
    Le problème n'était pas dans la création même des threads, même dans leur usage dans ces circonstances là. Créer un thread avec un Runnable qui teste si on est dans l'EDT n'a pas de sens, non pas dans la façon de créer le thread, mais parce que le thread qu'on créé ne peut pas être l'EDT, donc inutile de tester s'il est. D'autre par, exécuter dans l'EDT un code qui doit être exécuté dans l'EDT lorsqu'on n'est pas dans l'EDT est bien ce qu'il faut faire, mais forcer son exécution dans un thread quelconque (donc pas l'EDT) lorsqu'on est justement dans l'EDT est un contresens.

    Citation Envoyé par ludovic01 Voir le message
    Aussi, si par exemple en plus de faire passer mon JPanel en jaune, je souhaite lui ajouter une image via ImageIcone, puis lui ajouter, je ne sais pas, un JtextField aussi. Dans ce cas-là, ne suis-je pas obligé de créer un objet via "ActionListener action = new ActionListener() {...}"en plein milieu de mon code pour le faire? Un peu comme dans mon exemple.
    Pour ajouter des composants, on les ajoute c'est tout. Pas besoin en effet d'ActionListener. Dans le contexte, l'ActionListener est juste nécessaire à cause de l'usage du Timer. On utilisera aussi un ActionListener par exemple pour l'action sur un bouton, ou la validation de saisie dans un JTextField. Dans un process normal, par exemple, de création de JFrame, on a pas besoin d'ActionListener : on exécute une séquence d'instruction dans l'EDT et c'est tout. Si on doit déclencher quelque chose sur un évenement, on utilisera un ActionListener ou un autre type d'écouteur d''évenement selon les cas.
    Citation Envoyé par ludovic01 Voir le message
    exxxxxx
    Enfin, une dernière question qui prouve mon "absolu debutance" (je sais cela n'existe pas dans le dico) Que signifie le "e" et plus précisément le "e ->"
    Il s'agit d'une notation propre aux expressions lambda. Cela représente un paramètre.

    Par exemple,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ActionListener actionListener = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                 System.out.println("coucou);
            }
    };
    Ceci est l'affectation d'une variable (actionListener) par une instance de classe anonyme implémentant l'interface ActionListener. Le e ici est un argument de la méthode actionPerformed, de type ActionEvent.

    L'équivalent en expression lambda explicite de ce code est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ActionListener actionListener = (ActionEvent e)-> System.out.println("coucou);
    Comme il n'y a pas ambiguïté sur l'argument (le compilateur voit que la classe attendue doit implémenter ActionListener, donc une méthode actionPerformed() qui a un argument, de type ActionEvent, on peut simplifier cette écriture par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ActionListener actionListener = e-> System.out.println("coucou);
    Le e est toujours là pour indiquer qu'il y a bien un argument, et au besoin, si on veut l'utiliser dans le code de l'expression lambda il s'appelle e.

    Cela devient plus clair si on a une interface fonctionnelle à 2 arguments. Par exemple java.util.Comparator. Mettons qu'on ait un tableau d'instance d'une classe Personne, qui a une méthode getNom() pour avoir le nom de la personne. On veut trier ce tableau de personne par ordre naturel (alphabétique) des noms de personne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Arrays.sort(tableauDePersonnes, (p1,p2)-> p1.getNom().compareTo(p2.getNom()));
    On a pas besoin de mettre le type de p1 et p2 (le compilateur "voit" qu'il s'agit d'un Comparator, et que le tableau étant un tableau de Personne, alors c'est que forcément le Comparator doit comparer des instances de Personne.
    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.

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

Discussions similaires

  1. Demande d explication sur protocole FTP
    Par Mr_Chut dans le forum Réseau
    Réponses: 1
    Dernier message: 04/05/2007, 18h47
  2. Réponses: 4
    Dernier message: 09/10/2006, 22h12
  3. Réponses: 3
    Dernier message: 27/09/2006, 13h11
  4. [C#] demande d'explication sur un sample msdn
    Par legillou dans le forum Windows Forms
    Réponses: 2
    Dernier message: 27/06/2006, 17h01
  5. [final]demande d'explication sur ce mot-clé
    Par Invité dans le forum Langage
    Réponses: 10
    Dernier message: 18/04/2006, 11h32

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