© Sofia ZAIDENBERG CNRS Mai 2007 1 Interface utilisateur graphique en Java Construire une interface graphique en Java (suite) adaptateurs d’événements.

Slides:



Advertisements
Présentations similaires
La programmation orientée objet avec Java L3-MIAGE Plan
Advertisements

Réaliser en Java un programme client d’une Base de Données
Evénements Java Beans Java RMI
Gestion des événements (suite)
La classe String Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s.
Page 1 Les applets Jacques Lonchamp. Page 2 Présentation Une applet est téléchargée à partir dune machine distante qui fournit le code. Ce chargement.
Approfondissement du langage
Introduction à Java - les paquetages -
F. Voisin : Introduction à Java 1 Introduction à Java - les interfaces - Frédéric VOISIN FIIFO - « Remise à Niveau »
Vos premiers pas en Swing
JAV - TD 6 Structures de données JAVA
TD 1 IJA Introduction Objet, méthode, attribut Classe, instance
Leçon 3 : Héritage IUP 2 Génie Informatique
Introduction à la POO: Les classes vs les objets
Programmation par Objets et Java
Pattern État PowerPoint 2003, télécharger la visionneuse PowerPoint Viewer dernière édition si vous ne lavez pas…télécharger la visionneuse PowerPoint.
Classes locales classes définies à l'intérieur d'un bloc de code,
Programmation orientée objet
JavaBeans Réalise par: EL KHADRAOUY TARIK AOUTIL SAFOWAN.
Les méthodes en java Une méthode est un regroupement d’instructions ayant pour but de faire un traitement bien précis. Une méthode pour être utilisée.
POO-L3 H. Fauconnier1 Chapitre IV 1. classe Object, clonage 2. interfaces 3. classes internes et imbriquées.
1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.
Écouteurs de click d'une fenêtre
Langage Oriente Objet Cours 4.
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
Les Classes les structures en C (struct) regroupent des variables : structuration de l'analyse mais problèmes de cohérence problèmes de sécurité d'accès.
77 Utilisation des classes (suite). 7-2 Objectifs A la fin de ce cours, vous serez capables de : Définir des méthodes surchargées dans une classe Fournir.
Classes abstraites et Interfaces
1 Objectifs de ce cours (I21) Cours JAVA (I21) -Licence 1 Semestre 2 / Y.Laborde Résumé du cours précédent.
Graphical User Interface (GUI)
Langage Oriente Objet Cours 2.
Master 1 SIGLIS Java Lecteur Stéphane Tallard Chapitre 5 – Héritage, Interfaces et Listes génériques.
Graphical User Interface
66 Utilisation des classes et des objets. 6-2 Objectifs A la fin de ce cours, vous serez capables de : Créer de nouvelles classes à laide de Eclipse Utiliser.
Introduction au paradigme orienté-objet (suite)
Présentation Structures de Données et TDA
1 IFT 6800 Atelier en Technologies dinformation Le langage de programmation Java chapitre 3 : Classes et Objects.
COURS DE PROGRAMMATION ORIENTEE OBJET :
COURS DE PROGRAMMATION ORIENTEE OBJET :
Leçon 1 : notion dobjet IUP Génie Informatique Besançon Méthode et Outils pour la Programmation Françoise Greffier Université de Franche-Comté.
Interfaces Graphiques
LIFI-Java 2004 Séance du Mercredi 22 sept. Cours 3.
La notion de type revisitée en POO
Evénements. Plan Evénements Principes Exemples Adapteur.
Cours 9 Exceptions (fin) Généricité. POO-L3 H. Fauconnier2 Chaînage d'exceptions  Une exception peut être causée par une autre.  il peut être utile.
11/04/ L'héritage Cours 7 Cours 7.
Variables et accès en Java. Déclaration des variables final transient static private Printer hp; transient => ne doivent pas être sérialisées volatile.
Cours 7 Classes locales Clonage Divers: tableaux.
Créer des packages.
Master 1 SIGLIS Java Lecteur Stéphane Tallard Les erreurs communes en Java.
Interfaces graphiques. Composants d'interface utilisateur graphique (GUI) 1 Bibliothèques Awt et Swing Procédures communes pour l'utilisation de ces clases.
14 La gestion d’événements
Tutorat en bio-informatique
5ième Classe (Mercredi, 19 octobre) Prog CSI2572.
Réaliser par: Sadok Amel Cheboui hassiba
Les classes présenté par: RAHMOUNE RIME / ZEKRI SELMA.
Les classes et les objets Les données finales class A { … private final int n = 20 ; // la valeur de n est définie dans sa déclaration … } class A { public.
Cours du 5 novembre.
Iterator Design Pattern Alessandro Soro Sylvain Giroux.
Cours 4 (14 octobre) Héritage. Chapitre III Héritage.
Construire une interface graphique en Java
Héritage Conception par Objet et programmation Java
Graphical User Interface
 1) Il faut connaître le modèle et son fonctionnement  2) Définir le contrôle que l’on veut faire ouvrir, fermer, afficher, etc.) sur le modèle  3)
Classes abstraites, interface Classe interne Classes enveloppes
Les interfaces de gestion d’événements (la suite).
Transcription de la présentation:

© Sofia ZAIDENBERG CNRS Mai Interface utilisateur graphique en Java Construire une interface graphique en Java (suite) adaptateurs d’événements et classes internes

© Sofia ZAIDENBERGCNRS Mai GUI Modèle événementiel du JDK 1.1 l Le modèle événementiel de JDK 1.1 se compose : l d'objets sources d'événements l d'objets événements l d'objets récepteurs d'événements l Ces objets interagissent de façon standard en invoquant des méthodes pour permettre le déclanchement et la gestion des événements Activer JButton MonBouton Source d’événements ActionEvent unEvnt 1 new ActionEvent( ) 3 getSource() unObjet 2 actionPerformed(unEvnt ) Récepteur d’événements

© Sofia ZAIDENBERGCNRS Mai GUI Sources et écouteurs d’événements l Événements générés par des sources d’événements (« event sources ») l Source d’événements, un objet capable de : l déterminer quand un événement « intéressant » s'est produit l d'avertir (« notify ») des objets récepteurs (« event listeners ») de l'occurrence de cet événement l Pour être averti des événements produits par une source, un récepteur doit se faire enregistrer auprès de la source Activer JButton MonBouton Source d’événements unObjet Récepteur d’événements addActionListener(unObjet) 1 removeActionListener(unObjet) 4 2 actionPerformed(unEvnt )... 3 actionPerformed(unEvnt ) Implémente l’interface d’écoute ActionListener

© Sofia ZAIDENBERGCNRS Mai GUI Rappel EditeurGraphique JFrameJPanel BarreOutils ZoneDessin BarreEtat Construction de l’interface graphique Gestion de l’interaction Déplacement de la souris sur la zone de dessin doit mettre à jour les coordonnées du curseur dans la barre d’état Type d’événement : MouseEvent ( MOUSE_MOVED, MOUSE_DRAGGED ) MouseEvent Source : la zone de dessin 3 3 Récepteur : la zone de dessin également

© Sofia ZAIDENBERGCNRS Mai GUI rappel l Code de la classe lançant l’application import javax.swing.*; public class EditeurGraphique extends JFrame { final static int HAUTEUR = 450; final static int LARGEUR = 750; public EditeurGraphique { BarreEtat barreEtat = new BarreEtat(); setTitle("Ma première Fenêtre"); setSize(LARGEUR,HAUTEUR); setJMenuBar(new MenuEditeur()); this.getContentPane().add(new BarreOutils(),"North"); this.getContentPane().add(new ZoneGraphique(barreEtat),"Center"); this.getContentPane().add(barreEtat,"South"); barreEtat.afficheInfo("coordonnées du cruseur"); setVisible(true); } public static void main(String[] args) { new EditeurGraphique(); } } // MyFrame L’objet zone graphique a connaissance de l’objet barre d’état pour pouvoir agir sur lui lors de la réception des MouseEvent

© Sofia ZAIDENBERGCNRS Mai GUI rappel l Code de la classe représentant la zone graphique import java.awt.*; import javax.swing.*; import java.awt.event.*; public class ZoneDessin extends JPanel implements MouseMotionListener { private BarreEtat be; public ZoneDessin(BarreEtat be) { setBackground(Color.white); setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); this.be = be; this.addMouseMotionListener(this); } public void mouseMoved(MouseEvent e) { be.afficheCoord(e.getX(),e.getY()); } public void mouseDragged(MouseEvent e) { be.afficheCoord(e.getX(),e.getY()); } } // ZoneGraphique L’objet zone dessin va être à l’écoute des événements MouseEvent de type MouseMotion 1 L’objet zone dessin utilise les informations contenues dans l’objet MouseEvent qui lui est transmis pour mettre à jour la barre d’état. 2 L’objet zone dessin s’enregistre lui- même comme récepteur des événements MouseEvent de type MouseMotion qu’il est susceptible de générer 3

© Sofia ZAIDENBERGCNRS Mai GUI import javax.swing.*; public class EditeurGraphique extends JFrame { final static int HAUTEUR = 450; final static int LARGEUR = 750; public EditeurGraphique { setTitle("Ma première Fenêtre"); setSize(LARGEUR,HAUTEUR); setJMenuBar(new MenuEditeur()); this.getContentPane().add(new BarreOutils(),"North");... setVisible(true); } Adaptateurs d’événements Fermeture de la fenêtre Clic doit provoquer arrêt de l’application EditeurGraphique JFrame this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); Pas utilisable si on veut un comportement plus spécifique, par exemple ne quitter l'application que si l'utilisateur le confirme.  Il faut alors définir explicitement le code de gestion des événements sur la fenêtre

© Sofia ZAIDENBERGCNRS Mai GUI Adaptateurs d’événements Fermeture de la fenêtre Clic doit provoquer arrêt de l’application Type d’événement : WindowEvent ( WINDOW-CLOSING ) WindowEvent 1 1 EditeurGraphique JFrame 2 2 Source : l’éditeur graphique (JFrame) 3 3 Récepteur : l’éditeur graphique

© Sofia ZAIDENBERGCNRS Mai GUI Adaptateurs d’événements Fermeture de la fenêtre l Code de l’Editeur Graphique import javax.swing.*; public class EditeurGraphique extends JFrame { final static int HAUTEUR = 450; final static int LARGEUR = 750; public EditeurGraphique { BarreEtat barreEtat = new BarreEtat(); setTitle("Ma première Fenêtre"); setSize(LARGEUR,HAUTEUR); setJMenuBar(new MenuEditeur()); this.getContentPane().add(new BarreOutils(),"North"); this.getContentPane().add(new ZoneGraphique(barreEtat),"Center"); this.getContentPane().add(barreEtat,"South"); barreEtat.afficheInfo("coordonnées du cruseur"); setVisible(true); } public static void main(String[] args) { new EditeurGraphique(); } } // MyFrame implements WindowListener { this.addWindowListener(this) L’objet éditeur graphique s’enregistre lui-même comme récepteur des WindowEvent qu’il est susceptible de générer 2 L’objet éditeur graphique va être à l’écoute des événements WindowEvent 1 Mais maintenant il faut aussi implémenter les méthodes de l’interface WindowListener import java.awt.event.*;

© Sofia ZAIDENBERGCNRS Mai GUI Adaptateurs d’événements Fermeture de la fenêtre WINDOW_ACTIVATED WINDOW_CLOSED WINDOW_CLOSING WINDOW_DEACTIVATED WINDOW_DEICONIFIED WINDOW_ICONIFIED WINDOW_OPENED WindowEvent définit plusieurs sous types d’événements windowActivated(WindowEvent) Invoked when a window is activated windowClosed(WindowEvent) Invoked when a window has been closed. windowClosing(WindowEvent) Invoked when a window is in the process of being closed. windowDeactivated(WindowEvent) Invoked when a window is de-activated. windowDeiconified(WindowEvent) Invoked when a window is de-iconified. windowIconified(WindowEvent) Invoked when a window is iconified. windowOpened(WindowEvent) Invoked when a window has been opened. WindowListener définit plusieurs méthodes, une pour chacun de ces types Dans le cas présent seuls les événements WINDOW_CLOSING nous intéressent. public class EditeurGraphique extends JFrame implements WindowListener { public EditeurGraphique() { … this.addWindowListener(this); this.setVisible(true); } } public void windowClosing(WindowEvent e){ if (JOptionPane.showConfirmDialog(this, "Voulez-vous vraimment quitter ?", null, JOptionPane.YES_NO_OPTION) == 0) System.exit(0); } Mais quand on implémente une interface il faut implémenter toutes les méthodes qu’elle définit public void windowActivated(WindowEvent e){;} public void windowOpened(WindowEvent e){}... corps vide setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE);

© Sofia ZAIDENBERGCNRS Mai GUI Adaptateurs d’événements Fermeture de la fenêtre Adaptateur d’événements WindowAdapter dans package java.awt.event public class EditeurGraphique extends JFrame { public EditeurGraphique() { … this.addWindowListener( ); this.setVisible(true); } public static void main(String[] args){ new EditeurGraphique(); } public class ClosingAdapter extends WindowAdapter { public void windowClosing(WindowEvent e){ if(JOptionPane.showConfirmDialog(this, "Voulez-vous vraiment quitter ?", null, JOptionPane.YES_NO_OPTION) == 0) System.exit(0); } new ClosingAdapter() Étendre la classe WindowAdapter et n’implémenter que la méthode qui nous concerne 1 2 Associer une instance de cette classe à la fenêtre

© Sofia ZAIDENBERGCNRS Mai GUI Adaptateurs d’événements Dessin des segments de droite l Gestion des événements souris Déplacement de la souris sur la zone de dessin met à jour les coordonnées du curseur dans la barre d’état MOUSE_MOVED, MOUSE_DRAGGED Appuyer sur un bouton de la souris ( MOUSE_PRESSED ) définit le début d’une droite Relâcher le bouton de la souris ( MOUSE_RELEASED ) définit la fin de la droite type d’événement : MouseEvent source : zone de dessin interface d’écoute : MouseListener récepteur : zone de dessin MouseListener void mouseClicked(MouseEvent) void mouseEntered(MouseEvent) void mouseExited(MouseEvent) void mousePressed(MouseEvent) void mouseReleased(MouseEvent) Comme pour la fermeture de la fenêtre, seules deux des méthodes de l’interface nous intéressent

© Sofia ZAIDENBERGCNRS Mai GUI Adaptateurs d’événements Dessin des segments de droite import java.awt.*; import javax.swing.*; import java.awt.event.*; public class ZoneDessin extends JPanel implements MouseMotionListener { private BarreEtat be; public ZoneDessin(BarreEtat be) { setBackground(Color.white); setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); this.be = be; addMouseMotionListener(this); } public void mouseMoved(MouseEvent e) { be.afficheCoord(e.getX(),e.getY()); } public void mouseDragged(MouseEvent e) { be.afficheCoord(e.getX(),e.getY()); } } // ZoneDessin addMouseListener(new GestionnaireClic(this)); public void initieDroite(int x, int y) { be.afficheMessage(« Relacher pour dessiner la droite »); // on complétera ensuite } public void termineDroite(int x, int y) { be.afficheMessage(« Cliquer pour initier une droite »); // on complétera ensuite } import java.awt.event.*; public class GestionnaireClic extends MouseAdapter { public void mousePressed(MouseEvent e) { zone.initieDroite(e.getX(),e.getY()); } public void mouseReleased(MouseEvent e) { zone.termineDroite(e.getX(),e.getY()); } Pour ne pas avoir à définir des méthodes inutiles, possibilité d’utiliser un adaptateur d’événements : MouseAdapter private ZoneDessin zone; public GestionnaireClic(ZoneDessin z) { zone = z; }

© Sofia ZAIDENBERGCNRS Mai GUI Des adaptateurs aux classes internes l Gestion des boutons de la barre d’outil type d’événement : ActionEvent source : les JButton interface d’écoute : ActionListener récepteur ? Annule le dernier tracé Efface toute la zone de dessin L’activation des boutons doit se traduire par un changement d’état de la zone de dessin. Il semble naturel que cela soit la zone dessin qui récupère les événements et réalise les traitement adéquats.

© Sofia ZAIDENBERGCNRS Mai GUI le code zone dessin dépend du code de la barre d’outils. Des adaptateurs aux classes internes import java.awt.*; import javax.swing.*; import java.awt.event.*; public class ZoneDessin extends JPanel implements MouseMotionListener { private BarreEtat be; public ZoneDessin(BarreEtat be) { …. } public void mouseMoved(MouseEvent e) {... } public void mouseDragged(MouseEvent e) {... } public void initieDroite(int x, int y) {... } public void termineDroite(int x, int y) {... } } // ZoneGraphique public void efface() {... } public void annule() {... } 1) C’est la zone dessin qui effectue les traitements déclenchés par les boutons efface et annule, ActionListener { 2) La zone dessin reçoit les événements issus des boutons public void actionPerformed(ActionEvent e) { selon l’origine de l’événement efface() ou annule() } Quid si on supprime la barre d’outils et que toutes les opérations s’effectuent via la barre de menus ? Lourdeur du code : si beaucoup de boutons à écouter si plusieurs moyens de déclencher ces actions (boutons, menus…)

© Sofia ZAIDENBERGCNRS Mai GUI Des adaptateurs aux classes internes l Le modèle événementiel de JAVA 1.1 peut rapidement devenir difficile à gérer l si un objet doit être à l’écoute d’un grand nombre d’objets sources, l il lui faut implémenter les interfaces appropriées à chacun de ces objets l si un objet est à l’écoute d’événements issus de deux objets (ou davantage) sources d'événements du même type l l’objet récepteur ne peut implémenter qu’une seule fois l’interface réceptrice d’événements, il lui faudra découvrir lui-même quel objet a émis l’événement  Cela peut conduire à du code difficile à lire et/ou difficile à écrire l Une solution : introduire un objet « médiateur » entre la source d’événements et le récepteur d’événements l son rôle : adapter la source aux besoins spécifiques d’où le nom d’adaptateur d’événements

© Sofia ZAIDENBERGCNRS Mai GUI Des adaptateurs aux classes internes import java.awt.event.*; import java.awt.*; public class AdaptateurEfface implements ActionListener { ZoneDessin zone; public adaptateurEfface(ZoneDessin z) { zone = z; } public void actionPerformed(ActionEvent e) { zone.efface(); } import java.awt.event.*; import java.awt.*; public class AdaptateurAnnule implements ActionListener { ZoneDessin zone; public AdaptateurEfface(ZoneDessin z) { zone = z; } public void actionPerformed(ActionEvent e) { zone.annule(); } Adaptateurs d’événements Simplification de ZoneDessin Meilleur découplage des différents éléments de l’interface utilisateur Mais multiplication du nombre de classes classes pas vraiment réutilisables Dans le code de BarreOutils... BarreOutils(ZoneDessin zd) {... JButton b; this.add(b= new JButton("Défaire")); b.addActionListener(new AdaptateurAnnule(zd)); this.add(b = new JButton("Tout effacer")); b.addActionListener(new AdaptateurEfface(zd));... }...

© Sofia ZAIDENBERGCNRS Mai GUI l Alors que faut-il faire ? l classes imbriquées (« nested classes ») et internes (« inner classes ») l possibilité de définir des classes à l’intérieur d’autres classes l l’une des évolutions majeures de Java 1.1 l si on élimine « les cas obscurs et pathologiques » (D. Flanagan in Java in a nutshell, 2nd Edition, O ’Reilly) c’est un ajout élégant et très utile l utilisation très fréquente en particulier avec le nouveau modèle d’événements introduit aussi dans Java 1.1 Des adaptateurs aux classes internes

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes l Trois types de classes internes : l Classe membre : définition de la classe à l’intérieur d’une classe, au même niveau que les attributs et méthodes class X { class Member extends Superclass {…} } class X { void work() { class Local extends Superclass {…} } l Classe locale : définition de la classe à l’intérieur d’une méthode l Classe anonyme : définition de la classe à l’intérieur d’une expression class X { void work() { obj = new Superclass() {…} } class Anonymous extends/implements Superclass

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes membres l Classes membres class X { class Member extends Superclass {…} } l Toute instance d’une classe membre est associée de manière interne à une instance de la classe englobante l accès implicite aux membres (attributs/méthodes) définis dans la(les) classe(s) englobante(s), (y compris les membres privés) l exemple : (d’après Java In a Nutshell, 2nd Edition, D. Flanagan, O ’Reilly) public interface Linkable { public Linkable getNext(); public void setNext(Linkable node); } public class LinkedList { private Linkable head;... public void insert(Linkable node) {... } public void remove(Linkable node) {... } public interface Iterator { public boolean hasNext(); public Object next(); } public Iterator iterator() {... } Implémentation d’une liste chaînée Ajouter à la liste chaînée la possibilité de parcourir les éléments à l’aide d’un Iterator

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes membres public class LinkedList { private Linkable head;... public void insert(Linkable node) {... } public void remove(Linkable node) {... } public Iterator iterator() {... } class LinkedListIterator implements Iterator { private Linkable current; public boolean hasNext() { return current != null; } public Object next() { if(current == null) throw NoSuchElementException("LinkedList"); Object value = current; current = current.getNext(); return value } Sans classe membre public class LinkedList { private Linkable head;... public void insert(Linkable node) {... } public void remove(Linkable node) {... } public Iterator iterator() {... } private class LinkedListIterator implements Iterator{ private Linkable current; public LinkedListIterator() { current = head; } public boolean hasNext() { return current != null; } public Object next() { if(current == null) throw NoSuchElementException(«LinkedList»); Object value = current; current = current.getNext(); return value } Avec une classe membre return new LinkedListIterator(); Plus besoin de passer l’objet LinkedList dans le constructeur head; Accès direct aux membres (même privés) de la classe englobante return new LinkedListIterator(this); public LinkedListIterator(LinkedList l) { } current = l.head; Nécessité de passer explicitement un objet LinkedList dans le constructeur et de rendre accessible l'attribut head

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes membres l Comment cela marche ? l Toute instance d’une classe membre est associée de manière interne à une instance de la classe englobante public class LinkedList { private Linkable head;... public void insert(Linkable node) {... } public void remove(Linkable node) {... } public Itrator iterator() { return new LinkedListIterator(); } private class LinkedListIterator implements Iterator{ private Linkable current; public LinkedListIterator() { current = head; } public boolean hasNext() { return current != null; } public Object next () { if(current == null) throw NoSuchElementException(«LinkedList»); Object value = current; current = current.getNext(); return value } le compilateur insère auto- matiquement un attribut privé pour contenir cette référence 1 le compilateur ajoute auto- matiquement un argument caché à tous les constructeurs de la classe membre 2 private LinkedList container; 1 (LinkedList l) { 2 (this); 3 3 et passe l’objet contenant en valeur de cet argument container = l;

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes membres l Accès implicite aux champs (attributs/méthodes) définis dans la(les) classe(s) englobante(s), (y compris les champs privés) private class LinkedListIterator implements Iterator { private Linkable current; public LinkedListIterator() { current = head; }... } public class LinkedList { private Linkable head;... } this.current = this.head; this.current = LinkedList.this.head; Syntaxe pour faire référence explicitement à l’instance contenante de l’instance courante de la classe membre Pas d’attribut head dans la classe membre

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes membres l Hiérarchie d’imbrication et hiérarchie d’héritage sont totalement distinctes l’une de l’autre l héritage : définit les champs (attributs, méthodes) dont hérite la classe membre l imbrication : définit les champs qui sont dans la portée (accessibles) de la classe membre. import java.util.*; public class C { Vector a;... } public class A { int a; } class B extends C { } l Restrictions sur les classes membres l ne peuvent avoir un nom identique à celui de l’une des classes englobantes ne peuvent contenir de membres (attributs, méthodes ou classe) static En cas de conflit, le compilateur le signale : Variable 'a' is inherited in inner class A.B, and hides a variable of the same name in class A. An explicit 'this' qualifier must be used to select the desired instance. this.a est un Vector A.this.a est un int a ??

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes membres l Compilation de classes membres l La machine virtuelle JAVA n’a pas été modifiée pour la prise en compte des classes internes l Le compilateur doit convertir les classes internes en classes standard (top-level classes) que l’interpréteur JAVA peut comprendre l C’est effectué à l’aide de transformations du code source (insertion ‘ $ ’ dans le nom des classes internes, insertion d’attributs et paramètres cachés...). public class LinkedList { } class LinkedListIterator { } LinkedList.java javac LinkedList.class LinkedList$LinkedListIterator.class

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes locales l Classes locales : définies à l’intérieur d’un bloc de code class X { void work() { class Local extends Superclass {…} } l Une classe locale est une classe interne, elle partage bien des caractéristiques des classes membres. l Une classe locale est aux classes membres ce qu’est une variable locale aux variables d’instance l uniquement visible et utilisable dans le bloc de code où elle est définie elle peut utiliser n’importe quelle variable locale (ou paramètre de méthode) visible à l’endroit où elle est définie à condition qu’elle (ou qu’il) soit déclaré final l exemple : (toujours d’après Java In a Nutshell, 2nd Edition, D. Flanagan, O ’Reilly)

© Sofia ZAIDENBERGCNRS Mai GUI public class LinkedList { private Linkable head;... public void insert(Linkable node) {... } public void remove(Linkable node) {... } public Iterator iterator() { } class LinkedListIerator implements Iterator { private Linkable current; public LinkedListIterator() { current = head; } public boolean hasMoreElements() { return current != null; } public Object nextElement() { if(current == null) throw NoSuchElementException(«LinkedList»); Object value = current; current = current.getNext(); return value } Classe locale Classes internes classes locales public class LinkedList { private Linkable head;... public void insert(Linkable node) {... } public void remove(Linkable node) {... } public Iterator iterator() { return new LinkedListIterator(); } La définition de la classe est encore rapprochée de l’endroit où elle est utilisée -> augmente la clarté du code (?) private class LinkedListIterator implements Iterator { private Linkable current; public LinkedListIterator () { current = head; } public boolean hasNext() { return current != null; } public Object next () { if(current == null) throw NoSuchElementException(«LinkedList»); Object value = current; current = current.getNext(); return value } Classe membre return new LinkedListIterator(); }

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes locales public class A { private int a;... public void methodeX(int param1, int param2){ int local1; double local2; local2 =... ;... new B()... } // fin methode x... } class B { private int b; public B() {... } public void methodY() { a =... ; }... } // fin classe B l Ce qui différencie une classe locale d’une classe membre est qu’elle a en plus accès aux variables locales (et paramètres) visibles dans son bloc de définition. if (param2 == 0 && local2 < 0.0) {... } A.java:13: local variable param2 is accessed from within inner class; needs to be declared final if (param2 == 0 && local2 < 0.0) { ^ A.java:13: local variable local2 is accessed from within inner class; needs to be declared final if (param2 == 0 && local2 < 0.0) { ^ 2 errors Compilation exited abnormally with code 1 at Mon Mar 18 07:22:02 Pourquoi ? javac ClasseA.java

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes locales l Ce qui différencie une classe locale d’une classe membre est qu’elle a en plus accès aux variables locales (et paramètres) visibles dans son bloc de définition. Mais à condition que ces variables et paramètres soient déclarés final l Comment et pourquoi ? public class A { private int a;... public void methodeX(int param1, int param2){ int local1; double local2; local2 =... ;... new B()... } // fin methode x... } class B { private int b; public B() {... }... } private int attributCaché1; private double attributCaché2; 1 Une classe locale peut accéder aux variables locales car le compilateur ajoute automatiquement : des attributs privés pour stocker une copie des variables locales 1 des paramètres cachés aux constructeurs de la classe membre pour initialiser ces attributs privés créés automatiquement. 2 (private int pCaché1,double pCaché2) { B(param2,local2) 2 Le seul moyen de maintenir ces copies en accord avec les variables locales est de définir ces dernières comme finales final

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes locales l Restrictions sur les classes locales comme les classes membres elles ne peuvent contenir de champs (attributs ou méthodes) static l comme les classes membres elles ne peuvent avoir le même nom que l’une des classes englobantes elles ne peuvent être déclarées public, protected, private ou static (de la même manière que ces modifieurs ne sont pas autorisés pour des variables locales)

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes locales l Une utilisation très courante des classes locales est pour la réalisation d’adaptateurs d’événements l Reprenons la gestion des boutons de la barre d’outils de l’éditeur graphique type d’événement : ActionEvent source : les JButton interface d’écoute : ActionListener Annule le dernier tracé Efface toute la zone de dessin Récepteur : utilisation d’une classe locale dans le constructeur de la barre d’outils

© Sofia ZAIDENBERGCNRS Mai GUI Des adaptateurs aux classes internes import java.awt.event.*; import java.awt.*; import java.swing.*; public class BarreOutils extends JPanel { public BarreOutils( ZoneDessin zd) {... JButton bDefaire = new JButton("Défaire"); this.add(bDefaire); JButton bEffacer = new JButton("Tout effacer"); this.add(bEffacer); } Dans le code de BarreOutils class BOActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource() == bDefaire) zd.defaire(); else if (e.getSource() == bEffacer) zd.efface(); } Classe interne adaptateur d’événements Variables déclarées finales pour les rendre accessibles dans le code de la classe interne final BOActionListener boAL = new BOActionListener(); bDefaire.addActionListener(boAL); bEffacer.addActionListener(boAL); Création d’une instance de la classe interne qui est à l’écoute des boutons

© Sofia ZAIDENBERGCNRS Mai GUI public class A { void methodA() { } void methodB() { } A.java Classes internes classes locales l Compilation de classes locales class B { } javac A.class class B extends C { } A$1$B.class A$2$B.class

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes anonymes l Classes locales : définies à l’intérieur d’un bloc de code l Une classe anonyme est une classe locale sans nom Permet de regrouper définition et instanciation d’une classe locale l Très couramment utilisées en tant qu’adaptateurs d’événements class X { void work() { obj = new Superclass() {…} } class Anonymous extends/implements Superclass

© Sofia ZAIDENBERGCNRS Mai GUI import java.awt.event.*; import java.awt.*; Import java.swing.*; public class BarreOutils extends JPanel { public BarreOutils(final ZoneDessin zd) {... JButton bDefaire = new JButton("Défaire"); this.add(bDefaire); JButton bEffacer = new JButton("Tout effacer"); this.add(bEffacer);... bDefaire.addActionListener( ); bEffacer.addActionListener( );... } Avec des classes anonymes Classes internes classes anonymes Import java.swing.*; import java.awt.event.*; import java.awt.*; public class BarreOutils extends JPanel { public BarreOutils(final ZoneDessin zd) {... final JButton bDefaire = new JButton("Défaire"); this.add(bDefaire); final JButton bEffacer = new JButton("Tout effacer"); this.add(bEffacer);... BOActionListener boAL = new BOActionListener(); bDefaire.addActionListener(boAL); bEffacer.addActionListener(boAL);... } class BOActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource() == bDefaire) zd.defaire(); else if (e.getSource() == bEffacer) zd.efface(); } new ActionListener() { public void actionPerformed(ActionEvent e) { zd.efface(); } Avec une classe locale Classe anonyme adaptateur d’événements pour le JButton new ActionListener() { public void actionPerformed(ActionEvent e) { zd.defaire(); }

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes anonymes new NomDeClasse() { corps de la classe } new NomDinterface() { corps de la classe } classe anonyme sous-classe de la classe NomDeClasse classe anonyme implémente l’interface NomDinterface dans ce cas la classe anonyme est sous- classe de Object Une classe anonyme n’ayant pas de nom il n’est pas possible de définir de constructeur dans son corps Les arguments éventuellement spécifiés après NomDeClasse sont implicitement passés en paramètre du constructeur de cette super- classe Jamais d’arguments après NomDinterface puisque le constructeur de la super-classe ( Object ) n’a pas d’arguments ( liste d’arguments ) {

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes anonymes public class EditeurGraphique extends JFrame implements WindowListener { public EditeurGraphique() {... this.addWindowListener(new ClosingAdapter()); this.setVisible(true); } public static void main(String[] args) { new EditeurGraphique(); } public class ClosingAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } public class EditeurGraphique extends JFrame { public EditeurGraphique() {... this.addWindowListener( ); this.setVisible(true); } public static void main(String[] args) { new EditeurGraphique(); } new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } sans classe interne avec classe interne anonyme

© Sofia ZAIDENBERGCNRS Mai GUI Classes internes classes anonymes l Comment choisir entre écrire une classe locale ou écrire une classe anonyme l choisir ce qui rend le code plus clair è Classe anonyme l la classe doit avoir un corps petit l une seule instance de la classe est nécessaire l la classe est utilisée juste après qu’elle soit définie l le nom éventuel de la classe ne rend pas le code plus facile à comprendre è Classe locale l la classe doit avoir plusieurs instances l la classe nécessite un constructeur

© Sofia ZAIDENBERGCNRS Mai GUI public class A { } A.java Classes internes classes anonymes l Compilation de classes anonymes new B() { } javac A.class new C() { } A$1.class A$2.class

© Sofia ZAIDENBERGCNRS Mai GUI Iihm.imag.fr/~calvary/IHMO1O02