La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

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

Présentations similaires


Présentation au sujet: "© Sofia ZAIDENBERG CNRS Mai 2007 1 Interface utilisateur graphique en Java Construire une interface graphique en Java (suite) adaptateurs d’événements."— Transcription de la présentation:

1

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

3 © Sofia ZAIDENBERGCNRS Mai 2007 2 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

4 © Sofia ZAIDENBERGCNRS Mai 2007 3 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

5 © Sofia ZAIDENBERGCNRS Mai 2007 4 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 1 1 2 2 Source : la zone de dessin 3 3 Récepteur : la zone de dessin également

6 © Sofia ZAIDENBERGCNRS Mai 2007 5 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

7 © Sofia ZAIDENBERGCNRS Mai 2007 6 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

8 © Sofia ZAIDENBERGCNRS Mai 2007 7 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

9 © Sofia ZAIDENBERGCNRS Mai 2007 8 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

10 © Sofia ZAIDENBERGCNRS Mai 2007 9 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.*;

11 © Sofia ZAIDENBERGCNRS Mai 2007 10 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);

12 © Sofia ZAIDENBERGCNRS Mai 2007 11 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

13 © Sofia ZAIDENBERGCNRS Mai 2007 12 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

14 © Sofia ZAIDENBERGCNRS Mai 2007 13 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; }

15 © Sofia ZAIDENBERGCNRS Mai 2007 14 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.

16 © Sofia ZAIDENBERGCNRS Mai 2007 15 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…)

17 © Sofia ZAIDENBERGCNRS Mai 2007 16 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

18 © Sofia ZAIDENBERGCNRS Mai 2007 17 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));... }...

19 © Sofia ZAIDENBERGCNRS Mai 2007 18 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

20 © Sofia ZAIDENBERGCNRS Mai 2007 19 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

21 © Sofia ZAIDENBERGCNRS Mai 2007 20 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

22 © Sofia ZAIDENBERGCNRS Mai 2007 21 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

23 © Sofia ZAIDENBERGCNRS Mai 2007 22 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;

24 © Sofia ZAIDENBERGCNRS Mai 2007 23 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

25 © Sofia ZAIDENBERGCNRS Mai 2007 24 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 ??

26 © Sofia ZAIDENBERGCNRS Mai 2007 25 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

27 © Sofia ZAIDENBERGCNRS Mai 2007 26 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)

28 © Sofia ZAIDENBERGCNRS Mai 2007 27 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(); }

29 © Sofia ZAIDENBERGCNRS Mai 2007 28 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

30 © Sofia ZAIDENBERGCNRS Mai 2007 29 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

31 © Sofia ZAIDENBERGCNRS Mai 2007 30 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)

32 © Sofia ZAIDENBERGCNRS Mai 2007 31 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

33 © Sofia ZAIDENBERGCNRS Mai 2007 32 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

34 © Sofia ZAIDENBERGCNRS Mai 2007 33 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

35 © Sofia ZAIDENBERGCNRS Mai 2007 34 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

36 © Sofia ZAIDENBERGCNRS Mai 2007 35 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(); }

37 © Sofia ZAIDENBERGCNRS Mai 2007 36 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 ) {

38 © Sofia ZAIDENBERGCNRS Mai 2007 37 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

39 © Sofia ZAIDENBERGCNRS Mai 2007 38 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

40 © Sofia ZAIDENBERGCNRS Mai 2007 39 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

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


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

Présentations similaires


Annonces Google