Cours LOO2 Partie 4 Applets Java
Transcription
Cours LOO2 Partie 4 Applets Java
Language Java Cours LOO2 Partie 4 Applets Java Stéphane GALLAND UTSEUS 2008 1 Plan du cours Language Java ● Introduction ● Créer une applet Java ● Dessiner dans une applet Java ● Gérer les événements ● Limites des applets ● Bibliothèque de programmation des applets ● Référence ● Exercices Stéphane GALLAND UTSEUS 2008 2 Language Java ● Introduction – Applet vs. Application Différences avec une application classique : – elles sont lancées grâce à un navigateur (netscape, HotJava...), – elles sont chargées à travers le réseau par l’intermédiaire de pages HTML, – leur cycle de vie est différent (initialisée et démarrée au chargement de la page HTML...) – par sécurité elles ont des droits limités sur le poste qui les exécute (pas d’écriture de fichier, pas de chargement de DLL...) Stéphane GALLAND UTSEUS 2008 3 Language Java ● ● Introduction – Quand écrire une applet ? Aux commencement de Java, l'un des avantages critiques des applets par rapport aux applications Java classiques est qu'elles pouvaient être facilement déployées par Internet alors que les applications classiques nécessitent plus de programmation. De plus, les applets étant téléchargées par Internet, elles s'exécutent dans un environnement restreint par des règles de sécurité draconienne (environnement "sandbox") afin de limiter les accès aux ressources locales (système de fichiers, ...) Stéphane GALLAND UTSEUS 2008 4 Language Java ● ● ● Introduction – Quand écrire une applet ? Depuis l'introduction de Java Web Start, il est possible de déployer plus facilement une application classique sur le réseau Internet. Ceci implique que l'avantage majeur restant aux applets est qu'elles peuvent s'exécuter dans un navigateur Internet, alors qu'une application classique s'exécute en dehors d'un navigateur. Ainsi les applets peuvent fournir des services complets qui ne sont pas habituellement réalisables avec HTML ou Javacript : jeux graphiques, édition complexe, interactions Stéphane GALLAND UTSEUS 2008 5 Language Java ● Introduction – Charger une applet Pour charger une applet dans une page Internet, il est nécessaire de spécifier une balise HTML particulière dans le fichier HTML : <applet code=AppletWorld.class width="200" height="200"> </applet> Stéphane GALLAND UTSEUS 2008 6 Language Java ● Introduction – Charger une applet Pour charger une applet dans une page Internet, il est nécessaire de spécifier une balise HTML particulière dans le fichier HTML : Nom de la balise HTML permettant de charger une applet <applet code=AppletWorld.class width="200" height="200"> </applet> Stéphane GALLAND Nom de la classe Java de l'applet UTSEUS 2008 7 Language Java ● Introduction – Charger une applet Pour charger une applet dans une page Internet, il est nécessaire de spécifier une balise HTML particulière dans le fichier HTML : Hauteur en pixels de l'applet dans la page Internet <applet code=AppletWorld.class width="200" height="200"> </applet> Stéphane GALLAND Largeur en pixels de l'applet dans la page Internet UTSEUS 2008 8 Language Java ● ● Introduction – Charger une applet Pour développer ou tester une applet, l'utilisation d'un navigateur est une pratique trop contraignante. Il est possible d'utiliser une application de visualisation et d'exécution d'applets plus légère que les navigateurs classiques. appletviewer AppletWorld.html ● L'application appletviewer est distribuée dans tous les JDK Java. Stéphane GALLAND UTSEUS 2008 9 Language Java ● Introduction – Charger une applet Pour développer ou tester une applet, l'utilisation d'un navigateur est une pratique trop contraignante. Il est possible d'utiliser une application de visualisation et d'exécution d'applets plus Nom de la page Internet contenant la légère que les navigateurs classiques. balise HTML chargeant ● l'applet Java appletviewer AppletWorld.html ● L'application appletviewer est distribuée dans tous les JDK Java. Stéphane GALLAND UTSEUS 2008 10 Language Java ● ● Introduction – Charger une applet Une fois l'applet développée et tester avec appletviewer, il est recommandé de tester l'applet avec de véritables navigateurs Internet. Ceci permet de vérifier que le navigateur retrouve l'ensemble des classes Java nécessaires à l'exécution de l'applet Stéphane GALLAND UTSEUS 2008 11 Language Java ● Créer une applet Java - Exemple : Hello World! L'exemple suivant permet d'afficher un message « Hello World » : import javax.swing.JApplet; import java.awt.Graphics; public class HelloWorld extends JApplet { public void paint(Graphics g) { g.drawRect(0, 0, getSize().width - 1, getSize().height - 1); g.drawString("Hello world!", 5, 15); } } Stéphane GALLAND UTSEUS 2008 12 Language Java ● ● ● ● Créer une applet Java – Convertir une application en une applet Une application Java classique contient au moins une classe avec une fonction main(). Les applets ne possèdent pas de fonction main() A la place de cette fonction, un certain nombre d'autres de fonctions sont utilisées pour exécuter les applets. La différence entre une application et une applet est la méthode avec laquelle est sont exécutées. Stéphane GALLAND UTSEUS 2008 13 Language Java ● Créer une applet Java – Convertir une application en une applet Etapes pour convertir une application en une applet : – Créer une sous-classe de java.applet.Applet dans laquelle la fonction init() doit être surchargée par le code permettant d'initialiser l'applet. – init() peut être appellée plusieurs fois par le navigateur Internet. Son code doit donc être écrit en conséquence. Stéphane GALLAND UTSEUS 2008 14 Créer une applet Java – Etendre Applet ou JApplet Language Java ● ● Une applet est une classe Java héritant du comportement de classes abstraites définissant le comportement général de l'applet et les fonctions accessibles à cette dernière : – communication avec le navigateur – interface graphique Une applet doit hériter de la classe Applet ou JApplet Applet Stéphane GALLAND UTSEUS 2008 JApplet 15 Language Java ● Créer une applet Java – Etendre Applet ou JApplet Exemple « Hello World ! » import javax.swing.JApplet; import java.awt.Graphics; public class HelloWorld extends JApplet { public void paint(Graphics g) { g.drawRect(0, 0, getSize().width - 1, getSize().height - 1); g.drawString("Hello world!", 5, 15); } } Stéphane GALLAND UTSEUS 2008 16 Language Java ● ● Créer une applet Java – Etendre Applet ou JApplet Une applet doit hériter de la classe JApplet si elle doit intégrer des composants graphique provenant de la bibliothèque SWING. La classe JApplet fournit un composant graphique racine ("RootPane"), tout comme le font les classes SWING JFrame et JDialog. Stéphane GALLAND UTSEUS 2008 17 Language Java ● ● Créer une applet Java – Etendre Applet ou JApplet Une applet doit hériter de la classe Applet si elle n'intègre pas de composants graphiques ou si les composants graphiques qu'elle utilise font partie de la bibliothèque AWT. La classe Applet fournit un simple Panel comme composant racine. Stéphane GALLAND UTSEUS 2008 18 Cycle de vie d'une applet Language Java ● ● Le cycle de vie d'une applet décrit la séquence des fonctions qui sont appellée par le navigateur Internet pour informer l'applet d'étapes majeures dans son exécution. Les étapes majeures de l'exécution d'une applet sont : – Chargement – Quitter ou retourner dans la page de l'applet – Rechargement de l'applet – Quitter le navigateur Stéphane GALLAND UTSEUS 2008 19 Cycle de vie d'une applet Language Java Non chargée en mémoire init() start() stop() init() start() En cours d'exécution Arrêtée start() stop() destroy() stop() destroy() Détruite Stéphane GALLAND UTSEUS 2008 20 Cycle de vie d'une applet Language Java Chargement Non chargée en mémoire init() start() Rechargement init() start() stop() En cours d'exécution Quitter ou retourner dans la page HTML Arrêtée start() stop() destroy() stop() destroy() Détruite Stéphane GALLAND UTSEUS 2008 Quitter le navigateur 21 Language Java ● init() – ● Lancement de l'exécution de l'applet, lorsque l'applet est chargée ou lorsque l'utilisateur revisite la page HTML. stop() – ● Initialisation de l'applet lorsquelle est chargée ou rechargée. start() – ● Cycle de vie d'une applet Arrêt de l'exécution de l'applet, lorsque l'utilisateur change de page HTML ou lorsque le navigateur s'arrête. destroy() – Invoquée lorsque le navigateur s'arrête. Stéphane GALLAND UTSEUS 2008 22 Cycle de vie d'une applet Language Java ● Exemple : import javax.swing.JApplet; import java.awt.Graphics; public class HelloWorld extends JApplet { public public public public void void void void init() { } start() { } stop() { } destroy() { } public void paint(Graphics g) { g.drawRect(0, 0, getSize().width – 1, getSize().height - 1); g.drawString("Hello world!", 5, 15); } } Stéphane GALLAND UTSEUS 2008 23 Language Java ● ● ● ● Cycle de vie d'une applet La fonction init() est utile pour réaliser des initialisations rapides. En général, la fonction init() contient du code généralement écrit dans un constructeur. La raison pour laquelle une applet ne possède pas de constructeur est qu'elle ne possède pas d'environnement d'exécution fiable avant l'appet à la fonction init(). Par exemple, le chargement d'une image dans le constructeur de l'applet ne fonctionnera pas. Stéphane GALLAND UTSEUS 2008 24 Language Java ● ● Cycle de vie d'une applet Toutes les applets réalisant des actions après leur initialisation doivent surcharger la fonction start() pour réaliser ces actions (à l'exception des réponses aux actions directes de l'utilisateur). La fonction start() doit également lancer les threads utilisés par l'applet. Stéphane GALLAND UTSEUS 2008 25 Language Java ● ● ● Cycle de vie d'une applet La plupart des applets surchargeant la fonction start() surchargent également la fonction stop(). La fonction stop() doit suspendre toutes les actions de l'applet (threads inclus) afin de ne pas utiliser inutilement des ressources du système d'exploitation. Par exemple, une applet affiche une animation graphique doit arrêter cette animation dans la fonction stop() car l'utilisation ne voit plus l'applet. Stéphane GALLAND UTSEUS 2008 26 Language Java ● ● ● ● Cycle de vie d'une applet Beaucoup d'applets n'ont pas besoin de surcharger la fonction destroy(). En effet, la fonction stop() arrête en grande partie l'exécution de l'applet. Malgré cela, la fonction destroy() est surchargeable pour les applets nécessitant la libération de ressources additionnelles. L'implantation de la fonction destroy() doit rester la plus courte possible. En effet, il n'y a aucune garantie que la machine virtuelle Java ne s'arrête pas avant la fin de l'exécution de destroy(). Stéphane GALLAND UTSEUS 2008 27 Language Java ● ● ● Méthode pour dessiner dans une applet Lorsqu'une applet n'utilise pas des composants graphiques existants, elle doit dessiner son contenu directement. La fonction paint() peut être surchargée pour permettre à une applet de se dessiner. Les applets héritent la fonction paint() de la classe AWT Applet. Stéphane GALLAND UTSEUS 2008 28 Language Java ● Méthode pour dessiner dans une applet Exemple : import javax.swing.JApplet; import java.awt.Graphics; public class HelloWorld extends JApplet { public void paint(Graphics g) { g.drawRect(0, 0, getSize().width - 1, getSize().height - 1); g.drawString("Hello world!", 5, 15); } } Stéphane GALLAND UTSEUS 2008 29 Language Java ● ● ● Méthodes pour gérer les événements Les applets héritent de la classe Container les fonctions permettant de gérer les événements interactifs (souris, clavier, ...) Pour réagir à un événement, une applet doit implanter une interface particulière. L'applet est alors nommée « Listener » sur un ensemble d'événements Exemples d'interfaces de « Listeners » : – MouseListener – pour la souris – KeyListener – pour le clavier Stéphane GALLAND UTSEUS 2008 30 Language Java ● ● ● Méthodes pour gérer les événements Un composant « Listener » doit implanter un ensemble de fonctions (dépendantes de l'interface implantée). Un composant « Listener » doit informer la machine virtuelle qu'il veut recevoir des événements. Cette action est réalisée par l'appel de la fonction addXXX() dans init() où XXX doit être remplacé par le nom du Listener. Prototypes correspondant aux interfaces MouseListener et KeyListener : – void addMouseListener(MouseListener listener) – void addKeyListener(KeyListener Stéphane GALLAND UTSEUS 2008 listener) 31 Language Java ● Méthodes pour gérer les événements Exemple : import javax.swing.JApplet; public class HelloWorld extends JApplet implements MouseListener { public } public } public } public } public } void mouseClicked(MouseEvent event) { void mousePressed(MouseEvent event) { void mouseReleased(MouseEvent event) { void mouseMoved(MouseEvent event) { void mouseDragged(MouseEvent event) { } Stéphane GALLAND UTSEUS 2008 32 Language Java ● Méthodes pour gérer les événements Exemple : import Implantation d'une interface indiquant que les événements javax.swing.JApplet; souris seront gérés par cette applet class HelloWorld extends JApplet public implements MouseListener { public } public } public } public } public } void mouseClicked(MouseEvent event) { void mousePressed(MouseEvent event) { void mouseReleased(MouseEvent event) { void mouseMoved(MouseEvent event) { void mouseDragged(MouseEvent event) { } Stéphane GALLAND UTSEUS 2008 33 Language Java ● Méthodes pour gérer les événements Exemple : import javax.swing.JApplet; Fonctions à surcharger lorsque l'interface MouseListener est implantée public class HelloWorld extends JApplet implements MouseListener { public } public } public } public } public } void mouseClicked(MouseEvent event) { void mousePressed(MouseEvent event) { void mouseReleased(MouseEvent event) { void mouseMoved(MouseEvent event) { void mouseDragged(MouseEvent event) { } Stéphane GALLAND UTSEUS 2008 34 Language Java ● Méthodes pour gérer les événements Exemple : import javax.swing.JApplet; Fonction invoquée par la machine virtuelle à chaque fois que l'utilisateur réalise un clic souris public class HelloWorld extends JApplet dans l'applet implements MouseListener { public } public } public } public } public } void mouseClicked(MouseEvent event) { void mousePressed(MouseEvent event) { void mouseReleased(MouseEvent event) { void mouseMoved(MouseEvent event) { void mouseDragged(MouseEvent event) { } Stéphane GALLAND UTSEUS 2008 35 Language Java ● Méthodes pour gérer les événements Exemple : import javax.swing.JApplet; Fonction invoquée par la machine virtuelle à chaque fois que l'utilisateur appuie sur un bouton public class HelloWorld extends JApplet de la souris implements MouseListener { public } public } public } public } public } void mouseClicked(MouseEvent event) { void mousePressed(MouseEvent event) { void mouseReleased(MouseEvent event) { void mouseMoved(MouseEvent event) { void mouseDragged(MouseEvent event) { } Stéphane GALLAND UTSEUS 2008 36 Language Java ● Méthodes pour gérer les événements Exemple : import javax.swing.JApplet; Fonction invoquée par la machine virtuelle à chaque fois que l'utilisateur relache un bouton de public class HelloWorld extends JApplet la souris implements MouseListener { public } public } public } public } public } void mouseClicked(MouseEvent event) { void mousePressed(MouseEvent event) { void mouseReleased(MouseEvent event) { void mouseMoved(MouseEvent event) { void mouseDragged(MouseEvent event) { } Stéphane GALLAND UTSEUS 2008 37 Language Java ● Méthodes pour gérer les événements Exemple : import javax.swing.JApplet; Fonction invoquée par la machine virtuelle à chaque fois que l'utilisateur bouge la souris sans public class HelloWorld extends JApplet appuyer sur un bouton implements MouseListener { public } public } public } public } public } void mouseClicked(MouseEvent event) { void mousePressed(MouseEvent event) { void mouseReleased(MouseEvent event) { void mouseMoved(MouseEvent event) { void mouseDragged(MouseEvent event) { } Stéphane GALLAND UTSEUS 2008 38 Language Java ● Méthodes pour gérer les événements Exemple : import javax.swing.JApplet; Fonction invoquée par la machine virtuelle à chaque fois que l'utilisateur bouge la souris en public class HelloWorld extends JApplet appuyant sur un bouton implements MouseListener { public } public } public } public } public } void mouseClicked(MouseEvent event) { void mousePressed(MouseEvent event) { void mouseReleased(MouseEvent event) { void mouseMoved(MouseEvent event) { void mouseDragged(MouseEvent event) { } Stéphane GALLAND UTSEUS 2008 39 Language Java ● Méthodes pour gérer les événements Exemple : Paramètre décrivant import javax.swing.JApplet; l'événement. Ce paramètre fournit les informations publicsuivantes class : HelloWorld extends JApplet ● Position de la souris (X, Y) implements MouseListener { ● Liste des boutons appuyés ● Liste des touches du clavier voidAlt) mouseClicked(MouseEvent event) { appuyéespublic (Shift, Control, } public } public } public } public } void mousePressed(MouseEvent event) { void mouseReleased(MouseEvent event) { void mouseMoved(MouseEvent event) { void mouseDragged(MouseEvent event) { } Stéphane GALLAND UTSEUS 2008 40 Language Java ● Méthodes pour gérer les événements Exemple : import javax.swing.JApplet; public class HelloWorld extends JApplet implements MouseListener { ..... public void init() { addMouseListener(this); } } Stéphane GALLAND UTSEUS 2008 41 Limites des applets Language Java ● Restrictions de sécurité – Tous les navigateurs implantent des politiques de sécurité pour interdir à l'applet de compromettre le système. – L'implantation d'une politique de sécurité diffère d'un navigateur à l'autre, mais la plupart des navigateurs proposent les restrictions suivantes : ● ● une applet ne peut pas chargé une bibliothèque (DLL) ou définir une fonction native; une applet ne peut pas lire ou écrire dans un fichier se trouvant sur la machine exécutant le navigateur; Stéphane GALLAND UTSEUS 2008 42 Limites des applets Language Java ● Restrictions de sécurité – Suite des restrictions : ● ● ● ● une applet ne peut pas réaliser de connexion réseau en dehors du serveur HTTP d'où elle provient; une applet ne peut pas exécuter un programme externe. une applet ne peut pas lire certaines propriétés du système d'exploitation exécutant le navigateur; les fenêtres affichées par une applet auront un aspect différent des fenêtres affichées par une application. Stéphane GALLAND UTSEUS 2008 43 Limites des applets Language Java ● Restrictions de sécurité – Chaque navigateur possède un objet de type SecurityManager qui implante les politiques de sécurité du navigateur. – Lorqu'un objet SecurityManager détecte une violation, il génère une exception de type SecurityException. – Une applet peut capturer une exception de type SecurityException pour réagir de manière appropriée. Stéphane GALLAND UTSEUS 2008 44 Limites des applets Language Java ● Capacités d'une applet – Le paquet java.applet fournit un ensemble de fonctionnalités accessibles aux applets, et qui ne sont pas utilisable pas une application classique – Quelques exemples : ● ● ● ● une applet peut créer une connexion réseau vers le serveur HTTP d'où elle provient; une applet peut facilement demander au navigateur d'afficher une page HTML; une applet peut invoquer les fonctions publiques d'une autre applet se trouvant sur la même page; une applet chargée directement depuis le système de fichier local n'est plus soumise aux restrictions de sécurité. Stéphane GALLAND UTSEUS 2008 45 Language Java ● ● Bibliothèque de programmation des applets La bibliothèque de programmation des applets vous permet d'interagir avec le navigateur. La bibliothèque de programmation est accessible via les classes – java.applet.Applet – javax.swing.JApplet – java.applet.AppletContext Stéphane GALLAND UTSEUS 2008 46 Language Java ● ● Bibliothèque de programmation des applets Charger un fichier de données Une applet peut avoir besoin de charger des données à partir d'un fichier. Le nom de ce fichier être décrit par une URL qui est possède un nom de base retourné par l'une des deux fonctions suivantes : – Le nom de base retourné par la fonction getCodeBase() de la classe Japplet est l'URL d'où l'applet a été chargée. – Le nom de base retourné par la fonction getDocumentBase() de la classe Japplet spécifie le nom du répertoire où se trouve la page HTML ayant chargé l'applet. Stéphane GALLAND UTSEUS 2008 47 Language Java ● ● Bibliothèque de programmation des applets Charger un fichier de son ou une image La classe JApplet permet de charger facilement une image ou un son. Exemple : – Soit le système de fichiers suivant: Stéphane GALLAND UTSEUS 2008 48 Language Java ● ● Bibliothèque de programmation des applets Charger un fichier de son ou une image La classe JApplet permet de charger facilement une image ou un son. Exemple : – Soit le système de fichiers suivant: – Pour créer une image : Image image = getImage(getCodeBase(), "imgDir/a.gif"); – Stéphane GALLAND UTSEUS 2008 49 Language Java ● ● Bibliothèque de programmation des applets Afficher dans la barre d'état du navigateur Les navigateurs possèdent en général une barre d'état (en bas de la fenêtre). Une applet peut afficher un texte dans cette barre en utilisant la fonction showStatus(). import javax.swing.JApplet; public class HelloWorld extends Applet { public void start() { showStatus("Hello world. I'm started !"); } } Stéphane GALLAND UTSEUS 2008 50 Language Java ● ● Bibliothèque de programmation des applets Afficher un autre document HTML Une applet peut demander au navigateur d'afficher un document HTML La fonction showDocument() de la classe AppletContext permet d'afficher un document HTML dans le navigateur void showDocument(URL documentURL); void showDocument(URL document URL, String window); Stéphane GALLAND UTSEUS 2008 51 Language Java Bibliothèque de programmation des applets Afficher un autre document HTML void showDocument(URL documentURL); ● Cette version demande au navigateur de remplacer la page courante par celle spécifiée par l'URL Stéphane GALLAND UTSEUS 2008 52 Language Java Bibliothèque de programmation des applets Afficher un autre document HTML void showDocument(URL documentURL, String window); ● ● Cette version demande au navigateur d'afficher la page correspondante à l'URL dans la fenêtre (window) spécifiéé. Le paramètre window peut prendre les valeurs suivantes : – "_blank" ● – affiche le document dans une nouvelle fenêtre "windowName" ● affiche le document dans la fenêtre possédant le nom windowName Stéphane GALLAND UTSEUS 2008 53 Language Java Bibliothèque de programmation des applets Afficher un autre document HTML void showDocument(URL documentURL, String window); ● Suite des valeurs possibles pour le paramètre window : – "_blank" ● – "windowName" ● – affiche le document dans une nouvelle fenêtre affiche le document dans la fenêtre possédant le nom windowName "_self" ● affiche le document dans la fenêtre ou la frame affichant l'applet Stéphane GALLAND UTSEUS 2008 54 Language Java Bibliothèque de programmation des applets Afficher un autre document HTML void showDocument(URL documentURL, String window); ● Suite des valeurs possibles pour le paramètre window : – "_parent" ● – affiche le document dans la frame englobant celle de l'applet ou dans la fenêtre de l'applet si cette frame englobante n'existe pas "_top" ● affiche le document dans la fenêtre courante. Stéphane GALLAND UTSEUS 2008 55 Language Java ● ● Bibliothèque de programmation des applets Liste des applets d'une page La fonction getApplets() retourne la liste de toutes les applets de la page HTML (il s'agit d'une Enumeration pour être plus précis) Pour des raisons de sécurité, les navigateurs implantent la fonction getApplets() en ne retournant que les applets se trouvant sur le même serveur HTTP que l'applet ayant appellé la fonction getApplets(). Stéphane GALLAND UTSEUS 2008 56 Language Java ● Bibliothèque de programmation des applets Liste des applets d'une page Exemple : public void printApplets() { //Enumeration will contain all applets on //this page (including this one) that we can //send messages to. Enumeration e = getAppletContext().getApplets(); while (e.hasMoreElements()) { Applet applet = (Applet)e.nextElement(); String info = ((Applet)applet).getAppletInfo(); if (info != null) { textArea.appendText("- " + info + "\n"); } else { textArea.appendText("- " + applet.getClass().getName() + "\n"); } } } Stéphane GALLAND UTSEUS 2008 57 Language Java ● ● Bibliothèque de programmation des applets Liste des applets d'une page La fonction getApplet(String) retourne l'applet se trouvant sur la même page et possédant le nom spécifié en paramètre de la fonction. Pour des raisons de sécurité, les navigateurs implantent la fonction getApplet() en ne retournant que les applets se trouvant sur le même serveur HTTP que l'applet ayant appellé la fonction getApplet(). Applet receiver = null; String receiverName = "some name"; receiver = getAppletContext().getApplet(receiverName); Stéphane GALLAND UTSEUS 2008 58 Language Java ● Bibliothèque de programmation des applets Liste des applets d'une page Le nom d'une applet est spécifié dans la balise HTML chargeant l'applet : <APPLET CODEBASE=example/ CODE=Sender.class WIDTH=450 HEIGHT=200 NAME="buddy"> ... </APPLET> Stéphane GALLAND UTSEUS 2008 59 Language Java ● ● Bibliothèque de programmation des applets Jouer un son La classe JApplet et l'interface AudioClip fournissent les fonctionnalités de base pour jouer un son. Les fonctions permettant de charger un son sont : AudioClip getAudioClip(URL soundURL); AudioClip getAudioClip(URL baseURL, String soundName); void play(URL soundURL); void play(URL baseURL, String soundName); – Les versions à deux arguments permettent de spécifier l'URL de base et le fichier sonore relativement à cette URL de base. Stéphane GALLAND UTSEUS 2008 60 Language Java ● Bibliothèque de programmation des applets Jouer un son L'interface Audio clip propose les fonctions suivantes : // jouer le son une fois void play(); // jouer le son en boucle void loop(); // arrêter de jouer le son void stop(); Stéphane GALLAND UTSEUS 2008 61 Language Java ● Bibliothèque de programmation des applets Jouer un son Exemple : AudioClip onceClip, loopClip; onceClip = applet.getAudioClip( getCodeBase(), "bark.au"); loopClip = applet.getAudioClip( getCodeBase(), "train.au"); onceClip.play(); loopClip.loop(); loopClip.stop(); Stéphane GALLAND // jouer une fois // jouer en boucle // arrêter le son UTSEUS 2008 62 Language Java ● Bibliothèque de programmation des applets Jouer un son Autre Exemple : public class MyApplet extends Japplet { AudioClip loopClip; public void init() { loopClip = getAudioClip(getCodeBase(),"bark.au"); } public void stop() { loopClip.stop(); } public void start() { loopClip.loop(); } } Stéphane GALLAND UTSEUS 2008 63 Language Java ● Bibliothèque de programmation des applets Paramètres d'une applet Une applet peut lire la valeur d'un de ses paramètres en utilisant la fonction suivante : String getParameter(String parameterName) ● ● Si une valeur est donnée au paramètre spécifié à la fonction getParameter(), elle est retournée. Si aucune valeur n'est spécifiée, la valeur null est retournée. Stéphane GALLAND UTSEUS 2008 64 Référence Language Java ● Ce support de cours est basé sur le tutoriel officiel Java concernant les applets: http://java.sun.com/docs/books/tutorial/deployment/a pplet/index.html Stéphane GALLAND UTSEUS 2008 65 Language Java Exercices Stéphane GALLAND UTSEUS 2008 66 Exercice 1 Language Java ● ● ● ● ● ● Quelles sont les classes mère d'une applet ? Comment une applet peut demander au navigateur de raffraichir son affichage graphique ? Pour quoi utiliser la fonction start() ? Vrai ou faux: Une applet peut réaliser une connexion réseau avec une machine quelconque. Comment obtenir la valeur d'un paramètre spécifié dans la balise APPLET ? Une applet peut-elle exécuter des threads ? Stéphane GALLAND UTSEUS 2008 67 Exercice 2 Language Java ● ● Ecrire une applet affichant la position de la souris lorsque cette dernière survole l'applet. Il n'est pas nécessaire d'appuyer sur un bouton que cet affichage soit réalisé. Afficher cette applet dans un navigateur. Stéphane GALLAND UTSEUS 2008 68 Language Java Cours LOO2 Partie 5 Modèle Vue Contrôleur - MVC Stéphane GALLAND UTSEUS 2008 1 Plan du cours Language Java ● Architecture MVC ● Rôles des 3 élements du MVC ● Intérêts de l'architecture MVC ● L'architecture MVC et SWING ● Implantation d'un MVC en Java ● Exemple : liste d'éléments Stéphane GALLAND UTSEUS 2008 2 Language Java ● ● ● Architecture Modèle Vue Contrôleur (MVC) Architecture logicielle (design pattern) qui permet de séparer : – les objets applicatifs(Model) – leur représentation (View) – les interactions qu'ils subissent (Controler) Utilisée pour la programmation de client/serveur, et d'interfaces graphiques Généralisation du design pattern Observer/observable présenté dans la partie 7 de ce cours. Stéphane GALLAND UTSEUS 2008 3 Language Java ● Architecture Modèle Vue Contrôleur (MVC) Schéma de programmation qui permet de séparer une application en 3 parties : – Applicatif – le modèle contient la logique de l'application. – Visuel – les vues affichent à l'utilisteur des informations sur le modèle. – Evénementiel – le contrôleur agit sur demande de l'utilisateur et effectue les actions nécessaires sur le modèle. Stéphane GALLAND UTSEUS 2008 4 Architecture Modèle Vue Contrôleur (MVC) Language Java Utilisateur Est perçue par Utilise agit sur Vue Met à jour Contrôleur manipule Modèle Stéphane GALLAND UTSEUS 2008 5 Architecture Modèle Vue Contrôleur (MVC) Language Java Evénements graphiques provenant de l'utilisateur Utilisateur Est perçue par Utilise agit sur Vue Met à jour manipule Modèle Signale tout changement de contenu Stéphane GALLAND Contrôleur UTSEUS 2008 Mise à jour en cas de changement de contenu 6 Architecture Modèle Vue Contrôleur (MVC) Language Java Contrôleur Vue Modèle Utilisateur événements graphiques Mise à jour du contenu Notification de changement Lecture du contenu Affichage Stéphane GALLAND UTSEUS 2008 7 Architecture Modèle Vue Contrôleur (MVC) Language Java Contrôleur Vue Modèle Utilisateur événements graphiques Mise à jour de l'affichage Affichage Stéphane GALLAND UTSEUS 2008 8 Exemple 1 Language Java ● ● Document texte (modèle : chaîne de caractères html) peut avoir deux vues : – une vue WYSIWYG (What You See is What you Get) vue par un navigateur – une vue brute : code html source avec balises vue par un éditeur de textes Toute modification sur le modèle se répercute dans les deux vues Stéphane GALLAND UTSEUS 2008 9 Exemple 2 Language Java ● Application de calcul du budget d’une société – le modèle : les données et le procédures de calcul pour le budget prévisionnel de la société – les vues : une représentation sous forme de tableau, une sous forme graphique, une vue pour la direction, une pour la Direction des Ressources Humaines,... – le contrôleur : des éléments de l’interface pour faire varierles paramètres du calcul Stéphane GALLAND UTSEUS 2008 10 Rôle du contrôleur Language Java ● Reçoit les événements de l'interface utilisateur ● Traduit ces événements : – en changement dans la vue s'ils agissent sur le côté visuel ● – exemple : clic dans l'ascenseur de la fenêtre en changement dans le modèle s'ils agissent sur le contenu du modèle ● exemple : on réajuste le camembert, on modifie le diagramme en bâtons en agissant dans la vue Stéphane GALLAND UTSEUS 2008 11 Rôle du modèle Language Java ● ● ● Il peut être modifié sur ordre du contrôleur Il signale à ses vues tout changement de contenu en leur envoyant un événement qui leur spécifie de se mettre à jour Mais il ignore : – comment il est affiché – qui lui a notifié un changement d'état Stéphane GALLAND UTSEUS 2008 12 Rôle de la vue Language Java ● ● La vue se met à jour dès qu'elle reçoit un ordre de notification – du contrôleur – du modèle Quand la notification vient du modèle, elle va consulter le modèle pour se réafficher de manière adéquate Stéphane GALLAND UTSEUS 2008 13 Intérêts de l'architecture MVC Language Java ● Indépendance entre : – la représentation logique d'une application (modèle) – la représentation visuelle qu’on en donne (vue) – les actions que l ’utilisateur effectue (contrôleur) ⇒ Séparation claire entre les données du programme et l’interface graphique affichant ces données ⇒ Possibilités de vues différentes d'un même modèle L'application peut montrer l'état du modèle de différentes façons, avecdifférentes interfaces utilisateurs Stéphane GALLAND UTSEUS 2008 14 Language Java ● Intérêts de l'architecture MVC Cette indépendance favorise le développement et la maintenance des applications : – Modularité dans la conception – vue et contrôleur peuvent être développés indépendamment du modèle (pourvu qu'une interface entre les deux soit définie) Meilleure répartition des tâches ● ● développeurs du modèle/développeurs de l'interface ont des compétences différentes – développeurs du modèle : connaissance métier – développeurs de l ’interface : connaissance des besoins utilisateurs, souci d’ergonomie... ● Stéphane GALLAND UTSEUS 2008 15 Language Java ● ● ● ● Architecture MVC et SWING Chaque composant SWING s'appuie sur une architecture MVC en l'adaptant : la vue et le contrôleur sont combinés en un même objet Pour beaucoup de composants, cette architecture n’est pas exploitée (JButton,...) Pour d’autres, elle est très importante : JList, JTable L’architecture MVC fonctionne en utilisant la notiond’événemen Stéphane GALLAND UTSEUS 2008 16 Language Java ● ● Fonctionnement du MVC avec la notion d'événement notifié aux vues Le modèle doit connaître les vues qui dépendent de lui Dès que le modèle change, il crée un événement correspondant à ce changement – il envoie cet événement à toutes ses vues – ses vues, à la notification de l’événement, réagissent en conséquence, en mettant à jour leur apparence visuelle. – Stéphane GALLAND UTSEUS 2008 17 Language Java ● Implantation en Java des modèles Tous les composants SWING reposent sur le même principe: – les modèles sont des interfaces XXModel des classes abstraites AbstractXXModel implémentent l’interface en fournissant le code de certaines méthodes ● de gestion du modèle (modification,...), ● d'ajouts de vue ● des méthodes de notification d’événements Le modèle mémorise l'ensemble de ses vues – ● Stéphane GALLAND UTSEUS 2008 18 Language Java ● ● ● ● Implantation en Java des vues et contrôleurs Les vues sont interfaces XXListener correspondant à des écouteurs d’événements Les événements correspondant à des changements dans le modèle sont des XXEvent Dès qu’un tel événement est notifié à une vue, elle réagit en déclenchant la méthode appropriée Les vues doivent connaître le modèle vue sur un modèle = composant qui s'est déclaré comme écouteur d'événements de changement sur le modèle Stéphane GALLAND UTSEUS 2008 19 Comment réaliser un MVC en Java Language Java ● ● Définir un modèle Définir le composant qui sera une vue sur ce modèle : – – – – Il doit se déclarer écouteur des événements de changement dans le modèle en implantant l'interface adéquate Il doit mémoriser le modèle en variable membre Il doit donner un corps à chaque méthode de l’interface Il doit se faire ajouter à la liste des écouteurs du modèle ● Stéphane GALLAND UTSEUS 2008 20 Exemple Language Java ● La suite de ce cours illustre l'implantation en Java de l'architecture MVC sur l'exemple d'une liste d'élements Stéphane GALLAND UTSEUS 2008 21 Exemple – Modèle MVC Language Java ● MVC – Modèle : interface ListModel, classe abstraite AbstractListModel et classe DefaultListModel – Vue : interface ListDataListener concernée par les changements sur le modèle : ajout/suppression d'éléments de la liste Evénement transmis du modèle aux vues : ListDataEvent – Stéphane GALLAND UTSEUS 2008 22 Exemple – Le modèle Language Java ● ● Par exemple, une instance de la classe DefaultListModel ou d’une sous-classe que vous créerez Il mémorise l’ensemble des données et fournit des méthodes qui permettent de manipuler ces données void addElement(Object obj) boolean contains(Object elem) Object get(int index) boolean removeElement(Object obj) Object remove (int index) int size() Stéphane GALLAND UTSEUS 2008 23 Exemple – Le modèle Language Java ● Il mémorise la liste des vues (ListDataListener) et fournit des méthodes d'ajout/suppression de tels écouteurs void addListDataListener(ListDataListener listener); void removeListDataListener(ListDataListener listener); Stéphane GALLAND UTSEUS 2008 24 Exemple – Le modèle Language Java ● Il fournit des méthodes de notification d'événements à ses vues qu’il adresse à ses vues quand il se modifie void fireContentsChanged(Object source, int index0, int index1) void fireIntervalAdded(Object source, int index0, int index1) void fireIntervalRemoved(Object source, int index0, int index1) Stéphane GALLAND UTSEUS 2008 25 Language Java Exemple – La vue sur le modèle ● doit implémenter l'interface ListDataListener ● doit donner un corps aux 3 méthodes : – void contentsChanged(ListDataEvent e); en réponse à fireContentsChanged déclenchée dans le modèle ; ● reçu quand le contenu de la liste a changé ● Stéphane GALLAND UTSEUS 2008 26 Language Java ● Exemple – La vue sur le modèle doit donner un corps aux 3 méthodes (suite): – void intervalAdded(ListDataEvent e) en réponse à la méthode fireIntervalAdded déclenchée dans le modèle; ● reçu quand un intervalle (index0,index1) a été inséré dans le modèle ● Stéphane GALLAND UTSEUS 2008 27 Language Java ● Exemple – La vue sur le modèle doit donner un corps aux 3 méthodes (suite) : – void intervalRemoved(ListDataEvent e) en réponse à fireIntervalRemoved; ● reçue quand l'intervalle a été enlevé ● Stéphane GALLAND UTSEUS 2008 28 Language Java ● ● Exemple – L'événement de notification de changement Evénement de la classe ListDataEvent à exploiter par la vue pour savoir ce qui a changé dans le modèle. ListDataEvent posséde les méthodes : public int getIndex0() public int getIndex1() public int getType() //renvoie un mnemonique pour le type de // l'evenement (defini en constante) // CONTENTS_CHANGED // INTERVAL_ADDED // INTERVAL_REMOVED Stéphane GALLAND UTSEUS 2008 29 Language Java ● ● Exemple – Interaction entre modèle et vue Quand le modèle (l’ensemble d’objets) change parce qu'on lui a ajouté ou retiré un (ou plusieurs) élément(s), Le modèle – construit un événement de type ListDataEvent prenant en compte le type de modifications – notifie les écouteurs ListDataListener présents dans sa liste du changement. Pour cela, il déclenche la méthode correspondante, fireYY(). Stéphane GALLAND UTSEUS 2008 30 Language Java ● ● Exemple – Interaction entre modèle et vue Quand le modèle (l’ensemble d’objets) change parce qu'on lui a ajouté ou retiré un (ou plusieurs) élément(s), La vue – – déclenche la méthode correspondante peut utiliser l'événement qu'elle a en paramètre Stéphane GALLAND UTSEUS 2008 31 Language Java ● ● ● Exemple – Composant SWING encapsulant le MVC Classe JList La classe JList est un composant graphique de SWING qui affiche une liste Les données à afficher sont présentes dans un modèle sous-jacent (ListModel) JList est une classe "Wrapper" Elle écoute les événements reçus du modèle – Elle y réagit « toute seule » ⇒ Toute modification du modèle se répercutera dans la liste sans rien avoir à déclarer, ni faire de particulier – ⇒ Transparent pour l’utilisateur Stéphane GALLAND UTSEUS 2008 32 Exemple – Résumé Language Java ● ● ● ● Modèle (ensemble de nombres entiers) à créer et mémoriser : instance de la classe DefaultListModel Vue sur ce modèle : une JList dans le panneau central qui affiche cet ensemble On peut ajouter des entiers à la liste en les entrant dans une zone de texte située dans le panneau nord La vue doit se mettre à jour automatiquement Stéphane GALLAND UTSEUS 2008 33 Exemple – Analyse Language Java Zone de texte où un nombre entier peut être saisie : jNumberInput fournit les données au modèle Modèle de type DefaultListModel : jModel Utilisateur Vue sous la forme d'une liste : jNumberListView Stéphane GALLAND UTSEUS 2008 le modèle s'affiche sous forme d'une liste 34 Exemple – Analyse Language Java ● ● jNumberListView : instance de JList possédant comme modèle : jModel. => utilisation du constructeur : public JList (ListModel m) jNumberInput : instance de JTextField devant prévenir le modèle si l'utilisateur entre un nouveau nombre => lui associer un écouteur de classe ActionListener réalisant ce travail (l'événement ActionEvent est construit quand l'utilisateur tapera sur 'retour chariot' dans la zone de texte). Stéphane GALLAND UTSEUS 2008 35 Exemple – Implantation Language Java public class ExempleMVC extends JFrame { private final JTextField jNumberInput; private final JList jNumberListView; private final DefaultListModel jModel; public FenEnsembleMVC(String titre) { super(titre); jModel = new DefaultListModel(); jNumberListview = new Jlist(jModel); jNumberInput = new JTextField(); initialize(); } ... Stéphane GALLAND UTSEUS 2008 36 Exemple – Implantation Language Java ... public void initialize() { setBorderLayout(new BorderLayout()); add(BorderLayout.CENTER, jNumberListView); add(BorderLayout.TOP, jNumberInput); jNumberInput.addActionListener( new InsertNumberHandler()); } ... Stéphane GALLAND UTSEUS 2008 37 Exemple – Implantation Language Java ... private class InsertNumberHandler // Inner-class implements ActionListener { public void actionPerformed(ActionEvent e) { String s = jNumberInput.getText(); try { jModel.addElement( new Integer(Integer.parseInt(s))); } catch(NumberFormatException ex) { } jNumberInput.setText(""); } } } Stéphane GALLAND UTSEUS 2008 38 Language Java Exemple – Remarque 1 sur l'implantation ... private class InsertNumberHandler // Inner-class implements ActionListener { public void actionPerformed(ActionEvent e) { String s = jNumberInput.getText(); try { jModel.addElement( new Integer(Integer.parseInt(s))); } catch(NumberFormatException ex) { } jNumberInput.setText(""); } } } Le modèle se modifie ici part la méthode addElement() Stéphane GALLAND UTSEUS 2008 39 Language Java Exemple – Remarque 2 sur l'implantation ... private class InsertNumberHandler // Inner-class implements ActionListener { public void actionPerformed(ActionEvent e) { String s = jNumberInput.getText(); try { jModel.addElement( new Integer(Integer.parseInt(s))); } catch(NumberFormatException ex) { } ATTENTION: Dans un DefaultListModel, il est jNumberInput.setText(""); n'y placer que des Object, donc : } } } possible de impossible d'y ranger directment une valeur de type int ● on y rangera la représentation objet d'un int : Integer, après avoir vérifier la validité du format numérique ● Stéphane GALLAND UTSEUS 2008 40 Exemple – Implantation Language Java public class ExempleMVC extends JFrame { private final JTextField jNumberInput; private final JList jNumberListView; private final DefaultListModel jModel; Toute modification du modèle setitre) répercute public FenEnsembleMVC(String { automatiquement dans la Jlist sans que le programmeur fasse quelque chose. super(titre); new DefaultListModel(); EnjModel effet, un= objet de type Jlist est un « wrapper » qui gère automatiquement et sans extérieure les jNumberListview = newintervention Jlist(jModel); intéractions entre =le new modèle et la vue. jNumberInput JTextField(); initialize(); } ... Stéphane GALLAND UTSEUS 2008 41 Language Java Exercices Stéphane GALLAND UTSEUS 2008 42 Exercice 1 Language Java ● ● Proposer l'implantation d'un MVC basé sur l'exemple précédent en introduisant un affichage dans une zone de texte. Remarque : une zone de texte est une instance de la classe JLabel JLabel void setText(String) String getText() Stéphane GALLAND UTSEUS 2008 43 Exercice 2 Language Java ● Proposer une implantation de la classe DefaultListModel afin que celle-ci puisse être utilisée comme cela est illustré dans l'exemple de ce support de cours. Stéphane GALLAND UTSEUS 2008 44 Language Java Cours LO02 Partie 6 Interface graphique AWT et SWING Dr. Stéphane GALLAND [email protected] Université de Technologie de Belfort-Montbéliard (UTBM) Stéphane GALLAND UTSEUS 2008 - LO02 1 Plan du cours Language Java ● Historique ● Propriétés de SWING ● Composants SWING ● SWING et Modèle Vue Contrôleur ● Composants conteneurs, de contrôle, afficheurs ● Layouts ● Gestion des événements (Listeners) ● Composants complexes (JTree, Jtable) ● Dessiner librement des formes Stéphane GALLAND UTSEUS 2008 - LO02 2 Language Java ● ● Références Ce support de cours est une introduction à la programmation avec AWT et SWING Pour avoir plus d'informations et de détails, veuillez consulter les sites Internet suivants : – manuel de référence de Java : http://java.sun.com/javase/reference/api.jsp – explications et tutoriels : http://java.sun.com/javase/6/docs/ Stéphane GALLAND UTSEUS 2008 - LO02 3 Language Java SWING Introduction Stéphane GALLAND UTSEUS 2008 - LO02 4 Historique Language Java ● ● ● ● Au départ il avait AWT (Abstract Windowing Toolkit) Ensuite il a eu dans l’ordre chronologique: – SWING par Sun, – mais également SWT du projet Eclipse, – et plus récemment JFace. Le choix se fait souvent entre AWT et SWING (fournis en standard dans le SDK) Choix, car il est préférable de n'en utiliser qu'un seul à la fois, tant les risques d'erreurs peuvent survenir entre les deux API graphiques (leurs syntaxes sont très proches) Stéphane GALLAND UTSEUS 2008 - LO02 5 Historique Language Java ● Avantages et inconvénients: – Swing, plus récent que AWT, est également plus optimisé, et donc plus rapide. De son côté, AWT existe depuis plus longtemps, il est donc reconnu par plus de systèmes/outils. – Swing prend en compte un plus grand nombre de widgets. De plus, étant le remplaçant officiel d'AWT, il est donc encore amélioré avec les nouvelles versions de Java. – AWT garde encore pour lui son intégration à J2ME, et donc sa reconnaissance au sein d'un plus grand nombre de téléphones. – Les inconvénients de Swing sont susceptibles de disparaître avec les évolutions de Java. Stéphane GALLAND UTSEUS 2008 - LO02 6 Historique Language Java ● ● ● ● Existent également les gestionnaires SWT et JFace, créés par Eclipse pour palier les manques des gestionnaires de Sun pour le propre usage d'Eclipse. SWT se veut plus léger que AWT et Swing réunis, tout en fournissant un large jeu de widgets et bibliothèques graphiques. Ce framework est indépendant du système tout en étant capable d'utiliser des éléments natifs. JFace, de son côté, est une boîte à outils qui permet de simplifier la plupart des tâches graphiques. Il est construit à partir de SWT. Ces deux frameworks graphiques sont accessibles à tous ceux ayant installé le SDK d'Eclipse… Stéphane GALLAND UTSEUS 2008 - LO02 7 Language Java ● ● ● Propriétés de SWING Beaucoup de widgets : boutons, panel, … Pluggable Look and Feel – on peut changer l’apparence en faisant très peu de changements dans le code et en utilisant des packages graphiques: windows-like, Mac-like,… Accessibilité à des éléments d’IHM non usuels : interface braille, écrans tactiles,… ● Intègre une partie des graphiques Java2D ● Supporte le drag and drop Stéphane GALLAND UTSEUS 2008 - LO02 8 Propriétés de SWING Language Java ● Différentes apparences (« look & feel ») Java GTK+ Windows Classique Mac OS Stéphane GALLAND UTSEUS 2008 - LO02 9 Propriétés de SWING Language Java ● Différentes apparences (« look & feel ») Java GTK+ UIManager.setLookAndFeel(lnfName); SwingUtilities.updateComponentTreeUI(frame); frame.pack(); Windows Classique Stéphane GALLAND UTSEUS 2008 - LO02 Mac OS 10 Language Java ● Composants SWING Plusieurs types de composants: – conteneurs (containers) : ● de haut niveau ● généraux ● spéciaux – objets de contrôle (control objects) – afficheurs (displayers) : ● non-éditables ● interactifs spéciaux – Layouts Stéphane GALLAND UTSEUS 2008 - LO02 11 Language Java ● ● ● ● ● Composants Lourds et composants légers Il est utile de faire la différence entre composants « lourds » et composants « légers ». Les composants « lourds » sont gérés par le système d’exploitation Les composants « légers » sont des dessins gérés par l’API SWING. Il est donc possible de contrôler leur rafraîchissement contrairement aux composants lourds. Les composants « légers » ont en plus quelques propriétés : transparence, superposition, ... Dans AWT la plupart des composants sont gérés par le système d’exploitation. Ils sont donc « lourds ». Stéphane GALLAND UTSEUS 2008 - LO02 12 Language Java Arborescence de composants SWING Composants AWT Composants SWING Stéphane GALLAND UTSEUS 2008 - LO02 13 Language Java ● ● ● SWING et Modèle Vue Contrôleur Plusieurs composants SWING sont implémentés suivant l’architecture « Modèle Vue Contrôleur » (MVC), c’est à dire que les fonctionnalités suivantes sont implémentées de manière séparées : – modèle : la logique de fonctionnement du composant (combien d’états, est-il activé ?, ...); – vue : comment ce composant est affiché, aspect du composant; – contrôleur : en charge des actions utilisateur. Dans SWING les rôles vue et contrôleur sont souvent joués par les mêmes entités. Stéphane GALLAND UTSEUS 2008 - LO02 14 Language Java Composants graphiques d'affichage Stéphane GALLAND UTSEUS 2008 - LO02 15 Composants d'affichage Language Java ● ● ● Les composants d'affichage sont des composants graphiques permettant d'afficher une information. Généralement ces composants ne proposent pas de moyen d'interaction avec l'utilisateur. Les composants d'affichage abordés dans ce cours sont : – les étiquettes – les barres de progression – les bulles d'information Stéphane GALLAND UTSEUS 2008 - LO02 16 Language Java ● ● Les étiquettes sont des composants graphiques capables d'afficher un Component Composant d'affichage : Etiquette texte et/ou une image. Classe Java : JLabel Container JComponent JLabel Stéphane GALLAND UTSEUS 2008 - LO02 17 Language Java ● Composant d'affichage : Etiquette Illustration : Icon ic = new ImageIcon("splash.png"); JLabel et1 = new JLabel("Image and Text",ic); Stéphane GALLAND UTSEUS 2008 - LO02 18 Language Java ● Composant d'affichage : Etiquette Illustration : Icon ic = new ImageIcon("splash.png"); JLabel et1 = new JLabel("Image and Text",ic); JLabel et2 = new JLabel("Text-only Label"); Stéphane GALLAND UTSEUS 2008 - LO02 19 Language Java ● Composant d'affichage : Etiquette Illustration : Icon ic = new ImageIcon("splash.png"); JLabel et1 = new JLabel("Image and Text",ic); JLabel et2 = new JLabel("Text-only Label"); JLabel et3 = new JLabel(ic); Stéphane GALLAND UTSEUS 2008 - LO02 20 Language Java ● ● Composant d'affichage : Barre de progression Une barre de progression permet d'afficher l'état d'avancement de la réalisation d'une tâche. En général, cet état d'avancement est affiché sous la forme d'une barre colorée et d'un pourcentage. Component Container Classe Java : JProgressBar JComponent JProgressBar Stéphane GALLAND UTSEUS 2008 - LO02 21 Language Java ● Composant d'affichage : Barre de progression Illustration : JProgressBar jpb = new JProgressBar(); //when the task of (initially) unknown length begins: jpb.setIndeterminate(true); //do some work; get length of task... jpb.setMaximum(newLength); jpb.setValue(newValue); jpb.setIndeterminate(false); Stéphane GALLAND UTSEUS 2008 - LO02 22 Language Java ● ● ● Composant d'affichage : Bulle d'information Une bulle d'information est un composant graphique affichant un texte expliquant l'état ou les fonctionnalités d'un autre composant. Les bulles d'information apparaîssent en général lorsque la souris reste immobile au dessus du composant. Component Container JComponent Classe Java : JToolTip JToolTip Stéphane GALLAND UTSEUS 2008 - LO02 23 Language Java ● Composant d'affichage : Bulle d'information Illustration : JButton bt = new JButton("Disable middle button"); bt.setToolTipText("Click this button to disable middle button"); String txt = bt.getToolTipText(); ● Lorsqu'elle est surchargée, la fonction suivante permet de créer des bulles d'information pouvant s'afficher de manière particulière : JToolTip Component.createToolTip(); Stéphane GALLAND UTSEUS 2008 - LO02 24 Language Java Composants graphiques de contrôle Stéphane GALLAND UTSEUS 2008 - LO02 25 Objets de contrôle Language Java ● ● Les objets de contrôle sont des composants graphiques permettant de « contrôler » une application Les objets de contrôle abordés dans ce cours sont : – les boutons (standard, radio, ou à cocher) – les listes (déroulantes ou non) – les barres de menu et les menus – les champs de texte – les sélecteurs numériques Stéphane GALLAND UTSEUS 2008 - LO02 26 Language Java ● ● Objet de contrôle : Bouton classique Un bouton est un composant sur lequel il est possible de cliquer avec la souris afin de réaliser une action. Un bouton peut afficher un texte et/ou une image. Classe Java : JButton Container JComponent AbstractButton JButton Stéphane GALLAND UTSEUS 2008 - LO02 27 Language Java ● Objet de contrôle : Bouton classique Illustration : JButton bt1 = new JButton("Text only"); JButton bt2 = new JButton( new ImageIcon("icone.png")); JButton bt3 = new JButton( "Text and icon", new ImageIcon("icone.png")); Stéphane GALLAND UTSEUS 2008 - LO02 28 Language Java ● ● ● Objet de contrôle : Bouton radio Un bouton radio est un bouton fesant partie d'un groupe de boutons. Un seul bouton peut être sélectionné par groupe. Lorque l'utilisateur sélectionne un bouton appartenant à un groupe, les autres boutons sont automatiquement désélectionnés. Classe Java : JRadioButton Stéphane GALLAND UTSEUS 2008 - LO02 JComponent AbstractButton JToggleButton JRadioButton 29 Objet de contrôle : Bouton radio Language Java ● Illustration : ButtonGroup grp = new ButtonGroup(); JRadioButton JRadioButton JRadioButton JRadioButton JRadioButton bt1 bt2 bt3 bt4 bt5 = = = = = new new new new new JRadioButton("Bird"); JRadioButton("Cat"); JRadioButton("Dog"); JRadioButton("Rabbit"); JRadioButton("Pig"); grp.add(bt1); grp.add(bt2); grp.add(bt3); grp.add(bt4); grp.add(bt5); bt5.doClick(); Stéphane GALLAND UTSEUS 2008 - LO02 30 Language Java ● ● ● Objet de contrôle : Case à cocher Une case à cocher est un bouton pouvant être sélectionné ou non. Lorque l'utilisateur clique sur une case à cocher, la valeur booléenne associée à cette case change de valeur. JComponent AbstractButton JToggleButton Classe Java : JCheckBox JCheckBox Stéphane GALLAND UTSEUS 2008 - LO02 31 Objet de contrôle : Case à cocher Language Java ● Illustration : JCheckBox JCheckBox JCheckBox JCheckBox bt1 bt2 bt3 bt4 = = = = new new new new JCheckBox("Chin"); JCheckBox("Glasses"); JCheckBox("Hair"); JCheckBox("Teeth"); bt1.setSelected(true); bt2.setSelected(true); bt3.setSelected(true); bt4.setSelected(true); assert(bt1.isSelected() assert(bt2.isSelected() assert(bt3.isSelected() assert(bt4.isSelected() Stéphane GALLAND == == == == true); true); true); true); UTSEUS 2008 - LO02 32 Language Java ● ● ● Objet de contrôle : Liste d'items Une liste d'items permet : – d'afficher des items (texte et/ou image) – de sélectionner un ou plusieurs items Classe Java : JList Une liste d'items respecte une approche MVC. L'objet JList étant une vue et un contrôleur. Component Container JComponent JList ListModel Stéphane GALLAND UTSEUS 2008 - LO02 33 Language Java ● Objet de contrôle : Liste d'items Illustration : String[] data = {"one", "two", "three", "four"}; JList dataList = new JList(data); Vector superClasses = new Vector(); Class rootClass = javax.swing.JList.class; for(Class cls=rootClass; cls!=null; cls=cls.getSuperclass()) { superClasses.addElement(cls); } JList classList = new JList(superClasses); Stéphane GALLAND UTSEUS 2008 - LO02 34 Language Java ● Objet de contrôle : Liste d'items Illustration : String[] data = {"one", "two", "three", "four"}; Les ascenseurs dans cet JList dataList = affichés new JList(data); exemple ne font pas partie des JList. Vector superClasses = new Vector(); Ces ascenseurs = ontjavax.swing.JList.class; été obtenus à Class rootClass l'aide de composants JScrollPane for(Class cls=rootClass; dans lesquels les composants JList cls!=null; ont été ajoutés. cls=cls.getSuperclass()) { superClasses.addElement(cls); } JList classList = new JList(superClasses); Stéphane GALLAND UTSEUS 2008 - LO02 35 Objet de contrôle : Liste d'items Language Java ● Une liste d'items respecte l'approche Modèle Vue Contrôleur (MVC) : – Modèle Représenté par une instance de l'interface ListModel ● Fonctions d'accès : « interface » ListModel ● « abstract » AbstractListModel ListModel JList.getModel() void JList.setModel(ListModel model) – DefaultListModel Vue et Contrôleur ● Ces deux aspects sont gérés par l'instance de l'objet JList Stéphane GALLAND UTSEUS 2008 - LO02 36 Language Java ● Objet de contrôle : Liste d'items Illustration : DefaultListModel model = new DefaultListModel(); JList dataList = new JList(model); model.addElement("one"); model.addElement("two"); model.addElement("three"); model.addElement("four"); Stéphane GALLAND UTSEUS 2008 - LO02 37 Language Java ● ● ● Objet de contrôle : Liste déroulante Une liste déroulante permet : – d'afficher un champs de saisie – d'afficher une liste déroulante de valeurs pour le champs de saisie Component Container Classe Java : JComboBox Une liste déroulante respecte une approche MVC. L'objet JComboBox étant une vue et un contrôleur. JComponent JComboBox ComboBoxModel Stéphane GALLAND UTSEUS 2008 - LO02 38 Language Java ● Objet de contrôle : Liste déroulante Illustration : String[] data = {"one", "two", "three", "four"}; JComboBox dataList = new JComboBox(data); Vector superClasses = new Vector(); Class rootClass = javax.swing.JList.class; for(Class cls=rootClass; cls!=null; cls=cls.getSuperclass()) { superClasses.addElement(cls); } JComboBox classList = new JComboBox(superClasses); Stéphane GALLAND UTSEUS 2008 - LO02 39 Language Java ● Objet de contrôle : liste déroulante Une liste déroulante respecte l'approche Modèle Vue Contrôleur (MVC) : – Modèle Représenté par une instance de l'interface ComboBoxModel ● Fonctions d'accès : « interface » ComboBoxModel ● «interface» MutableCombo BoxModel ComboBoxModel JCombobox.getModel() void JComboBox.setModel(ComboBoxModel model) – DefaultComboBox Model Vue et Contrôleur ● Ces deux aspects sont gérés par l'instance de l'objet JComboBox Stéphane GALLAND UTSEUS 2008 - LO02 40 Language Java ● Objet de contrôle : Liste déroulante Illustration : DefaultComboBoxModel model = new DefaultComboBoxModel(); JComboBox dataList = new JComboBox(model); model.addElement("one"); model.addElement("two"); model.addElement("three"); model.addElement("four"); Stéphane GALLAND UTSEUS 2008 - LO02 41 Language Java ● ● Objet de contrôle : Liste déroulante Une liste déroulante est composée d'un champs de saisie et d'une liste déroulante. Le champs de saisie ne permet pas toujours à l'utilisateur de saisir une information librement : void JComboBox.setEditable(boolean isEditable); boolean JComboBox.isEditable(); ● Si le champs de saisie est disponible, alors il est possible d'utiliser une liste déroulante comme un champs de saisie classique (voir la suite de ce cours pour plus de détails sur les champs de saisie) Stéphane GALLAND UTSEUS 2008 - LO02 42 Language Java ● ● Objet de contrôle : Barres de menus et menus Le concept de menu est très utilisé dans les applications graphiques. Classes Java : JMenuBar, JMenu, JMenuItem Component Container AbstractButton JComponent JMenuItem JMenuBar JMenu Stéphane GALLAND UTSEUS 2008 - LO02 43 Language Java Objet de contrôle : Barres de menus et menus Component Container AbstractButton JComponent JMenuItem JMenuBar JMenu Stéphane GALLAND UTSEUS 2008 - LO02 44 Language Java Objet de contrôle : Barres de menus et menus Component Container AbstractButton JComponent JMenuItem JMenuBar JMenu Stéphane GALLAND UTSEUS 2008 - LO02 45 Language Java Objet de contrôle : Barres de menus et menus Component Container AbstractButton JComponent JMenuItem JMenuBar JMenu Stéphane GALLAND UTSEUS 2008 - LO02 46 Language Java Objet de contrôle : Barres de menus et menus Component Container AbstractButton JComponent JMenuItem JMenuBar JMenu Stéphane GALLAND UTSEUS 2008 - LO02 47 Language Java ● Objet de contrôle : Liste déroulante Illustration : JMenuBar bar = new JMenuBar(); JMenu menu1 = new JMenu() bar.add(menu1); JMenuItem it1 = new JMenuItem("A text-only menu item"); menu1.add(it1); ... Stéphane GALLAND UTSEUS 2008 - LO02 48 Objet de contrôle : Liste déroulante Language Java ● Les options d'un menu peuvent être de trois types : – une étiquette avec un texte et/ou une image : JMenuItem 2 – un bouton radio : JRadioButtonMenuItem 3 – une case à cocher : JCheckBoxMenuItem 1 JMenuItem 1 JRadioButtonMenuItem JCheckBoxMenuItem 2 3 Stéphane GALLAND UTSEUS 2008 - LO02 49 Language Java ● ● Objet de contrôle : Champs de saisie Une zone (ou champs) de saisie permet à l'utilisateur d'entrer une information au clavier. Container JComponent Classe Java : JTextField JTextComponent JTextField Stéphane GALLAND UTSEUS 2008 - LO02 50 Language Java ● Objet de contrôle : Champs de saisie Illustration : JTextField field = new JTextField(); field.setText("My default value"); String value = field.getText(); Stéphane GALLAND UTSEUS 2008 - LO02 51 Language Java ● Objet de contrôle : Champs de saisie Deux extensions d'un champs de saisie existent dans la biliothèque SWING : – un champs de saisie avec formattage automatique de la valeur saisie – un champs de saisie cachant la valeur saisie (utile pour la saisie de mots de passe) JTextField JFormattedTextField Stéphane GALLAND UTSEUS 2008 - LO02 JPasswordField 52 Language Java ● ● Objet de contrôle : Potentiomètre Un potentiomètre est un composant permettant de sélectionner une valeur numérique en déplaçant un curseur avec la souris Classe Java : JSlider Stéphane GALLAND UTSEUS 2008 - LO02 Container JComponent JSlider 53 Language Java ● ● ● Objet de contrôle : Sélecteur ensembliste Un sélecteur ensembliste est un composant permettant de sélectionner une valeur dans un ensemble de valeurs L'ensemble des valeurs est doté des opérateurs « suivant » et « précédent ». Ces opérateurs sont utilisés par le composant pour changer de valeur. Container JComponent JSpinner Classe Java : JSpinner Stéphane GALLAND UTSEUS 2008 - LO02 54 Language Java ● ● ● Objet de contrôle : Sélecteur de couleur Un sélecteur de couleur est un composant permettant à l'utilisateur de choisir une couleur Container JComponent Classe Java : JColorChooser Ce composant affiche l'interface graphique utilisée par le système d'exploitation pour la sélection d'une couleur Stéphane GALLAND UTSEUS 2008 - LO02 JColorChooser 55 Language Java ● ● ● Objet de contrôle : Sélecteur de fichier Un sélecteur de fichier est un composant permettant à l'utilisateur de choisir un fichier à ouvrir ou à enregistrer Container JComponent Classe Java : JFileChooser Ce composant utilise la boîte de dialogue « Ouvrir » ou « Enregistrer » du système d'exploitation Stéphane GALLAND UTSEUS 2008 - LO02 JFileChooser 56 Language Java Composants conteneurs de haut niveau Stéphane GALLAND UTSEUS 2008 - LO02 57 Language Java ● ● ● ● Composants conteneurs de haut niveau Aussi nommés : « Top-level Containers » Ils permettent de construire l'interface graphique en proposant un objet graphique pouvant contenir d'autres objets graphiques Une application possède au moins un composant conteneur de haut-niveau Les composants conteneurs de haut niveau sont de trois types principaux : – Les applets Java (applets) – Les fenêtres de dialogue (dialog/message windows) – Les fenêtres classiques (frames or windows) Stéphane GALLAND UTSEUS 2008 - LO02 58 Language Java ● Composants conteneurs de haut niveau Applet – Application pouvant être exécutée dans un navigateur internet – Pour définir une applet il faut hériter de la classe JApplet et redéfinir un certain nombre de méthode (init,…) Applet JApplet Stéphane GALLAND UTSEUS 2008 - LO02 59 Composants conteneurs de haut niveau Language Java ● Fenêtre de Dialogue – C’est une fenêtre classique en programmation – On utilise la classe JDialog dans laquelle un JOptionPane est instancié. Dialog JDialog Stéphane GALLAND UTSEUS 2008 - LO02 60 Language Java ● Composants conteneurs de haut niveau Fenêtre de Dialogue – exemple public class MyDialog extends JDialog { public MyDialog(JDialog parent) { super(parent,"An lname Question"); JOptionPane theContent = new JOptionPane( "Would you like green eggs and ham?", QUESTION_MESSAGE, YES_NO_OPTION); getContentPane().add(theContent); setPreferredSize(new Dimension(300,200)); pack(); } } Stéphane GALLAND UTSEUS 2008 - LO02 61 Composants conteneurs de haut niveau Language Java ● Fenêtre classique – C’est le type de fenêtre que vous allez le plus utiliser – Pour définir une nouvelle fenêtre il suffit de créer un objet héritant de JFrame (cf. exemple un peu plus loin) Frame JFrame Stéphane GALLAND UTSEUS 2008 - LO02 62 Language Java ● Composants conteneurs de haut niveau Fenêtre classique – exemple public class MyFrame extends JFrame { public MyFrame() { super("FrameDemo"); JPanel theContent = new JPanel(); add(theContent); setPreferredSize(new Dimension(300,200)); } } Stéphane GALLAND UTSEUS 2008 - LO02 63 Language Java Autres composants conteneurs Stéphane GALLAND UTSEUS 2008 - LO02 64 Composants conteneurs généraux Language Java ● ● Les composants conteneurs sont des composants graphiques contenant un ensemble de composants graphiques auxquels sont appliquées les règles d'interaction et d'affichage du composant conteneur Les composants conteneurs généraux présentés dans ce support de cours sont : – les panneaux – les panneaux avec ascenseurs – les onglets – les barres d'outils – les panneaux séparés – les panneaux multi-couches Stéphane GALLAND UTSEUS 2008 - LO02 65 Composant JPanel Language Java ● ● Un panneau classique est un composant léger pouvant contenir d'autres composants. Classe Java : JPanel Component Container JPanel p = new JPanel(); JButton b = new JButton(); JComponent p.add(b); JPanel Stéphane GALLAND UTSEUS 2008 - LO02 66 Composant JPanel Language Java ● Un panneau classique est un composant léger pouvant Création contenir d'une d'autres composants. instance Classede Java : JPanel panneau Component ● Container JPanel p = new JPanel(); JButton b = new JButton(); JComponent p.add(b); JPanel Stéphane GALLAND UTSEUS 2008 - LO02 67 Composant JPanel Language Java ● Un panneau classique est un composant léger pouvant Création contenir d'autres composants. d'un composant Classe Java : JPanel bouton Component ● Container JPanel p = new JPanel(); JButton b = new JButton(); JComponent p.add(b); JPanel Stéphane GALLAND UTSEUS 2008 - LO02 68 Language Java ● ● Composant JPanel Un panneau classique est un composant léger pouvant contenir d'autres composants. Ajout du bouton dans le panneau Classe Java : JPanel classique. Component Container JPanel p = new JPanel(); JButton b = new JButton(); JComponent p.add(b); JPanel Stéphane GALLAND UTSEUS 2008 - LO02 69 Composant JScrollPane Language Java ● ● Un panneau avec ascenseurs est un panneau pouvant contenir un autre composant. Il affiche des ascenseurs lorsque la taille du composant à l'intérieur est supérieure à la taille du panneau avec ascenseurs Component Container JComponent Classe Java : JscrollPane JButton p = new JButton(); JScrollPane JScrollPane sp = new JScrollPane(p); Stéphane GALLAND UTSEUS 2008 - LO02 70 Language Java ● Composant JScrollPane Illustration : img : ImageIcon JLabel jimg = new Jlabel( new ImageIcon("voiture.png")); jimg : JLabel Création d'un composant pouvant afficher une image Stéphane GALLAND UTSEUS 2008 - LO02 71 Composant JScrollPane Language Java ● Illustration : img : ImageIcon JLabel jimg = new Jlabel( new ImageIcon("voiture.png")); JScrollPane jsp = new jimg : JLabel JScrollPane(jimg); jsp : JScrollPane Création d'un panneau affichant des ascenseurs lorsque la taille du contenu est plus grand que la taille du panneau Stéphane GALLAND UTSEUS 2008 - LO02 72 Language Java ● ● Composant JTabbedPane Un panneau avec onglets permet d'afficher des composants spécifiques en fonction de l'onglet sélectionné Classe Java : JTabbedPane JTabbedPane jtp = new JTabbedPane(); JPanel onglet1 = new JPanel(); JPanel onglet2 = new Jpanel(); jtp.add("Onglet 1", onglet1); jtp.add("Onglet 2", onglet2); Stéphane GALLAND UTSEUS 2008 - LO02 Component Container JComponent JTabbedPane 73 Composant JScrollPane Language Java ● Illustration : JLabel JPanel JPanel JPanel onglet1 onglet2 onglet3 onglet4 onglet1 : JLabel = = = = new new new new JLabel("blah"); JPanel(); JPanel(); JPanel(); onglet2 : JPanel onglet3 : JPanel onglet4 : JPanel Création des quatre composants qui correspondront aux contenus des quatre onglets Stéphane GALLAND UTSEUS 2008 - LO02 74 Composant JScrollPane Language Java ● Illustration : JLabel JPanel JPanel JPanel onglet1 onglet2 onglet3 onglet4 onglet1 : JLabel = = = = new new new new JLabel("blah"); JPanel(); JPanel(); Jpanel(); onglet2 : JPanel onglet3 : JPanel JTabbedPane jtb = new JTabbedPane(); jtb : JTabbedPane onglet4 : JPanel Création de l'instance du composant pouvant contenir des onglets Stéphane GALLAND UTSEUS 2008 - LO02 75 Composant JScrollPane Language Java ● Illustration : JLabel JPanel JPanel JPanel onglet1 onglet2 onglet3 onglet4 onglet1 : JLabel = = = = new new new new JLabel("blah"); JPanel(); JPanel(); Jpanel(); onglet2 : JPanel onglet3 : JPanel JTabbedPane jtb = new JtabbedPane(); jtb.add("one",onglet1); jtb : JTabbedPane jtb.add("Two",onglet2); jtb.add("Three",onglet3); jtb.add("Four",onglet3); onglet4 : JPanel Ajout des onglets Stéphane GALLAND UTSEUS 2008 - LO02 76 Language Java ● ● Composant JToolBar Une barre d'outils est un composant graphique regroupant des contrôles simples (boutons, listes déroulantes, ...). Une barre d'outils est généralement située en haut d'une fenêtre. Classe Java : JToolBar JToolBar jtb = new JToolBar(); JButton bouton = new JButton(); jtb.add(bouton); Stéphane GALLAND UTSEUS 2008 - LO02 Component Container JComponent JToolBar 77 Language Java ● Composant JToolBar Illustration : bt1 : JButton i1 : ImageIcon JButton bt1 = new JButton( new ImageIcon("left.png")); bt2 : JButton i2 : ImageIcon bt3 : JButton i3 : ImageIcon bt4 : JButton i4 : ImageIcon JButton bt2 = new JButton( new ImageIcon("right.png")); JButton bt3 = new Jbutton( new ImageIcon("home.png")); JButton bt4 = new Jbutton( new ImageIcon("notes.png")); Création des quatre boutons de la barre d'outils Stéphane GALLAND UTSEUS 2008 - LO02 78 Language Java ● Composant JToolBar Illustration : bt1 : JButton i1 : ImageIcon JButton bt1 = new JButton( new ImageIcon("left.png")); bt2 : JButton i2 : ImageIcon bt3 : JButton i3 : ImageIcon bt4 : JButton i4 : ImageIcon JButton bt2 = new JButton( new ImageIcon("right.png")); JButton bt3 = new JButton( new ImageIcon("home.png")); JButton bt4 = new JButton( new ImageIcon("notes.png")); JToolBar jtb = new JToolBar(); jtb : JToolBar Création de l'instance de la barre d'outils (vide) Stéphane GALLAND UTSEUS 2008 - LO02 79 Language Java ● Composant JToolBar Illustration : bt1 : JButton i1 : ImageIcon JButton bt1 = new JButton( new ImageIcon("left.png")); bt2 : JButton i2 : ImageIcon bt3 : JButton i3 : ImageIcon bt4 : JButton i4 : ImageIcon JButton bt2 = new JButton( new ImageIcon("right.png")); JButton bt3 = new JButton( new ImageIcon("home.png")); JButton bt4 = new JButton( new ImageIcon("notes.png")); JToolBar jtb = new JToolBar(); jtb.add(bt1); jtb.add(bt2); jtb.add(bt3); jtb.add(bt4); jtb : JToolBar Ajout des boutons dans la barre d'outils Stéphane GALLAND UTSEUS 2008 - LO02 80 Language Java ● ● Composant JSplitPane Un panneau de séparation contient deux panneaux séparé par une barre que l'utilisateur peut déplacer avec la souris. Classe Java : JSplitPane JPanel left = new JPanel(); JPanel right = new JPanel(); JSplitPane jsp = new JSplitPane(); jsp.setLeftComponent(left); jsp.setRightComponent(right); Stéphane GALLAND UTSEUS 2008 - LO02 Component Container JComponent JSplitPane 81 Language Java ● Composant JSplitPane Illustration : left : JLabel JLabel left = new JLabel("left"); JLabel right = new JLabel("right"); right : JLabel Création des deux panneaux qui seront à l'intérieur du panneau avec séparation Stéphane GALLAND UTSEUS 2008 - LO02 82 Language Java ● Composant JSplitPane Illustration : left : JLabel JLabel left = new JLabel("left"); JLabel right = new Jlabel("right"); right : JLabel JSplitPane jsp = new JSplitPane(); jsp : JSplitPane Création d'un panneau avec séparation. Ce panneau incluse une barre de séparation Stéphane GALLAND UTSEUS 2008 - LO02 83 Language Java ● Composant JSplitPane Illustration : left : JLabel JLabel left = new JLabel("left"); JLabel right = new Jlabel("right"); right : JLabel JSplitPane jsp = new JSplitPane(); jsp.setLeftComponent(left); jsp.setRightComponent(right); jsp : JSplitPane Ajout des deux composants comme partie gauche et partie droite du panneau avec séparation Stéphane GALLAND UTSEUS 2008 - LO02 84 Composant JInternalFrame Language Java ● ● Une fenêtre interne est un composant léger représentant une fenêtre à l'intérieur d'une fenêtre « mère » (généralement un composant JDesktopPane) Classe Java : JInternalFrame Component Container JComponent JInternalFrame Stéphane GALLAND UTSEUS 2008 - LO02 85 Language Java ● ● ● Composant JLayeredPane Le panneau contenant des calque permet d'afficher des composants les uns au dessus des autres. Component Classe Java : JLayeredPane Un JLayeredPane contient différentes couches (calques) dans lesquelles des composants peuvent être insérés (affichés) Container JComponent JLayeredPane Stéphane GALLAND UTSEUS 2008 - LO02 86 Composant JLayeredPane Language Java ● Les couches accessibles sont : – DEFAULT_LAYER La couche par défaut dans laquelle la plupart des composants sont insérés. ● C'est la couche la plus profonde. ● Stéphane GALLAND UTSEUS 2008 - LO02 87 Composant JLayeredPane Language Java ● Les couches accessibles sont : – DEFAULT_LAYER – PALETTE_LAYER ● Couche généralement utilisée pour placer des composants flotants comme les barres d'outils ou les palettes d'outils. Stéphane GALLAND UTSEUS 2008 - LO02 88 Composant JLayeredPane Language Java ● Les couches accessibles sont : – DEFAULT_LAYER – PALETTE_LAYER – MODAL_LAYER ● La couche où sont placés les composants modaux. Stéphane GALLAND UTSEUS 2008 - LO02 89 Composant JLayeredPane Language Java ● Les couches accessibles sont : – DEFAULT_LAYER – PALETTE_LAYER – MODAL_LAYER – POPUP_LAYER ● Cette couche affiche les composants « Popup » ce qui permet d'afficher les listes déroulantes correctement par exemple. Stéphane GALLAND UTSEUS 2008 - LO02 90 Composant JLayeredPane Language Java ● Les couches accessibles sont : – DEFAULT_LAYER – PALETTE_LAYER – MODAL_LAYER – POPUP_LAYER – DRAG_LAYER ● Lorsqu'un composant est déplacé à la souris, ce calque permet de l'afficher au dessus de tous les autres composants. Stéphane GALLAND UTSEUS 2008 - LO02 91 Composant JLayeredPane Language Java ● Illustration : JPanel JPanel JPanel JPanel JPanel JLabel cyan = new JPanel(); yellow = new JPanel(); magenta = new JPanel(); green = new JPanel(); red = new JPanel(); manIcon = new JLabel(); Création des différents composants devant apparaître dans un panneau avec calques Stéphane GALLAND UTSEUS 2008 - LO02 92 Composant JLayeredPane Language Java ● Illustration : JPanel JPanel JPanel JPanel JPanel JLabel cyan = new JPanel(); yellow = new JPanel(); magenta = new JPanel(); green = new JPanel(); red = new JPanel(); manIcon = new JLabel(); JLayeredPane jlp = new JLayeredPane(); Création d'un panneau avec calques ne contenant aucun composant Stéphane GALLAND UTSEUS 2008 - LO02 93 Composant JLayeredPane Language Java ● Illustration : JPanel JPanel JPanel JPanel JPanel JLabel cyan = new JPanel(); yellow = new JPanel(); magenta = new JPanel(); green = new JPanel(); red = new JPanel(); manIcon = new JLabel(); JLayeredPane jlp = new JLayeredPane(); jlp.add(red,JLayeredPane.MODAL_LAYER); jlp.add(green,JLayeredPane.MODAL_LAYER); jlp.add(yellow,JLayeredPane.DEFAULT_LAYER); jlp.add(magenta,JLayeredPane.DEFAULT_LAYER); jlp.add(cyan,JLayeredPane.PALETTE_LAYER); jlp.add(manIcon,JLayeredPane.PALETTE_LAYER); Ajout des composants dans les calques Stéphane GALLAND UTSEUS 2008 - LO02 94 Composant JDesktopPane Language Java ● ● Les fenêtres MDI (Multi-Document Interface) sont des fenêtres pouvant contenir d'autres fenêtres Classe Java : JDesktopPane Component Container JDesktopPane JComponent JLayeredPane JDesktopIcon Stéphane GALLAND JInternalFrame UTSEUS 2008 - LO02 JDesktopPane 95 Language Java Layouts Stéphane GALLAND UTSEUS 2008 - LO02 96 Language Java ● ● ● ● LayoutManager Lorsque vous ajoutez un composant à un composant conteneur, ce dernier doit calculer la position et la taille du nouveau composant. Pour cela, le composant conteneur utilise un gestionnaire de disposition appellé « LayoutManager » Un « LayoutManager » implante différentes règles pour placer les composants les uns par rapport aux autres. Ainsi, la position et la taille des composants dans une interface graphique n'est pas décidée par les composants, mais par un « LayoutManager » Stéphane GALLAND UTSEUS 2008 - LO02 97 Language Java ● ● LayoutManager Le changement de « LayoutManager » pour un composant conteneur est réalisé par la fonction : void setLayout(LayoutManager manager); Pour aider le « LayoutManager », les composants peuvent indiquer la taille qu'ils préfèrent avoir : void setPreferredSize(Dimension dim); Dimension getPreferredSize(); – Ces fonctions doivent être appellées sur les composants internes Stéphane GALLAND UTSEUS 2008 - LO02 98 Language Java ● LayoutManager Plusieurs types de « LayoutManager » sont disponibles: – – – – – – – BorderLayout : initialisé pour tous les composants de haut niveau BoxLayout : simple ligne ou colonne CardLayout : zone qui contient des composants pouvant changer en cours de fonctionnement FlowLayout : par défaut pour tous les JPanel – une ligne avec passage à la ligne par manque de place GridLayout : utilisation d’une grille de cellules ayant la même taille GridBagLayout : utilisation d’une grille de cellules qui peuvent être de tailles différentes, les composants peuvent en outre être sur plusieurs cellules SpringLayout : layout dynamique pour le redimensionnement Stéphane GALLAND UTSEUS 2008 - LO02 99 FlowLayout Language Java ● ● ● Le FlowLayout est un gestionnaire de positionnement qui place les composants les un à la suite des autres. Ce gestionnaire utilise les tailles préférées des composants pour calculer les tailles réelles de ceux-ci. Ce gestionnaire est le gestionnaire par défaut des composants de type JPanel. Les composants sont placés sur deux lignes car la largeur de la fenêtre ne permet pas de les placer sur une seule ligne Stéphane GALLAND UTSEUS 2008 - LO02 100 FlowLayout Language Java ● Exemple : JPanel pnl = new JPanel(); pnl.setLayout(new FlowLayout()); pnl.add(new Jbutton("Button 1")); pnl.add(new Jbutton("Button 2")); pnl.add(new Jbutton("Button 3")); pnl.add(new Jbutton("Long-Named Button 4")); pnl.add(new JButton("5")); Stéphane GALLAND UTSEUS 2008 - LO02 101 Language Java ● BorderLayout Le BorderLayout est un gestionnaire de positionnement qui divise l'espace en cinq zones : début de page (en général en haut) – début de ligne (en général à gauche) – centre – fin de ligne (en général à droite) – fin de page (en général en bas) Ce gestionnaire utilise les tailles préférées des composants uniquement pour les zones autres de le centre. Pour cette dernière, le composant occupera la place la plus grande possible – ● Stéphane GALLAND UTSEUS 2008 - LO02 102 BorderLayout Language Java ● Exemple : JPanel pnl = new JPanel(); pnl.setLayout(new BorderLayout()); pnl.add(new Jbutton("Button 1"), BorderLayout.PAGE_START); pnl.add(new JButton("Button 2"), BorderLayout.LINE_START); pnl.add(new JButton("Button 3"), BorderLayout.PAGE_END); pnl.add(new JButton("Button 4"), BorderLayout.CENTER); pnl.add(new JButton("Button 5"), BorderLayout.LINE_END); Stéphane GALLAND UTSEUS 2008 - LO02 103 BoxLayout Language Java ● ● ● ● Le BoxLayout est un gestionnaire de positionnement qui place les composants verticalement ou horizontalement (en fonction d'une option donnée à son constructeur) Lorsque ce gestionnaire doit placer les composants horizontalement, il utilise uniquement les hauteurs préférées des composants Lorsque ce gestionnaire doit placer les composants verticalement, il utilise uniquement les largeurs préférées des composants Ce gestionnaire de positionnement supporte également un alignement des composants par rapport au centre vertical ou horizontal Stéphane GALLAND UTSEUS 2008 - LO02 104 BoxLayout Language Java ● Exemple : JPanel pnl = new JPanel(); pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS)); //pnl.setLayout(new BoxLayout(pnl, BoxLayout.X_AXIS)); pnl.add(new JButton("Button 1")); pnl.add(new JButton("2")); pnl.add(new JButton("Button 3")); pnl.add(new Jbutton("Long-Named Button 4")); pnl.add(new JButton("Button 5")); Stéphane GALLAND UTSEUS 2008 - LO02 105 GridLayout Language Java ● ● ● Le GridLayout est un gestionnaire de positionnement qui place les composants sur une grille régulière. Le nombre de colonnes et le nombre de lignes doivent être passés en paramètre du constructeur. Grille régulière : grille dont toutes les cellules possèdent la même largeur et la même hauteur Stéphane GALLAND UTSEUS 2008 - LO02 106 GridLayout Language Java ● Exemple : JPanel pnl = new JPanel(); // 3 lignes, 2 colonnes pnl.setLayout(new GridLayout(3,2)); pnl.add(new JButton("Button 1")); pnl.add(new JButton("Button 2")); pnl.add(new JButton("Button 3")); pnl.add(new Jbutton("Long-Name Button 4")); pnl.add(new JButton("5")); Stéphane GALLAND UTSEUS 2008 - LO02 107 Language Java GridBagLayout ● Le GridBagLayout est une extension du GridLayout. ● Il permet : – – d'avoir des tailles différentes de cellules de placer un composant sur plusieurs cellules Stéphane GALLAND UTSEUS 2008 - LO02 108 GridBagLayout Language Java ● Exemple : JPanel pnl = new JPanel(); GridBagLayout gb = new GridBagLayout(); pnl.setLayout(gb); GridBagConstraint c = new GridBagConstraint(); c.gridx = 0; c.gridy = 0; c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraint.NONE; JButton bt = new JButton("Button 1"); gb.setConstraint(bt,c); pnl.add(bt); ... Stéphane GALLAND UTSEUS 2008 - LO02 109 GridBagLayout Language Java ● Exemple : JPanel pnl = new JPanel(); GridBagLayout gb = new GridBagLayout(); pnl.setLayout(gb); GridBagConstraint c = new GridBagConstraint(); c.gridx = 0; c.gridy = 0; c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraint.NONE; JButton bt = new JButton("Button 1"); Les conditions permettant de positionner un composant gb.setConstraint(bt,c); doivent être données à l'aide pnl.add(bt); d'une instance de cet objet ... Stéphane GALLAND UTSEUS 2008 - LO02 110 GridBagLayout Language Java ● Exemple : JPanel pnl = new JPanel(); GridBagLayout gb = new GridBagLayout(); pnl.setLayout(gb); GridBagConstraint c = new GridBagConstraint(); c.gridx = 0; c.gridy = 0; c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraint.NONE; JButton bt = new JButton("Button 1"); Position du composant dans gb.setConstraint(bt,c); la grille pnl.add(bt); ... Stéphane GALLAND UTSEUS 2008 - LO02 111 GridBagLayout Language Java ● Exemple : JPanel pnl = new JPanel(); GridBagLayout gb = new GridBagLayout(); pnl.setLayout(gb); GridBagConstraint c = new GridBagConstraint(); c.gridx = 0; c.gridy = 0; c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraint.NONE; JButton bt = new JButton("Button 1");Nombre de cellules en largeur gb.setConstraint(bt,c); et en hauteur devant être pnl.add(bt); prises par le composant ... Stéphane GALLAND UTSEUS 2008 - LO02 112 GridBagLayout Language Java ● Exemple : JPanel pnl = new JPanel(); GridBagLayout gb = new GridBagLayout(); pnl.setLayout(gb); GridBagConstraint c = new GridBagConstraint(); c.gridx = 0; c.gridy = 0; c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraint.NONE; Précise si le composant peut JButton bt = new JButton("Button 1"); remplir tout l'espace gb.setConstraint(bt,c); verticalement ou pnl.add(bt); horizontalement : NONE, VERTICAL, HORIZONTAL ... Stéphane GALLAND UTSEUS 2008 - LO02 113 GridBagLayout Language Java ● Exemple : JPanel pnl = new JPanel(); GridBagLayout gb = new GridBagLayout(); pnl.setLayout(gb); GridBagConstraint c = new GridBagConstraint(); c.gridx = 0; c.gridy = 0; c.gridwidth = 1; c.gridheight = 1; Cet appel de fonction permet c.fill = GridBagConstraint.NONE; d'indiquer au gestionnaire de JButton bt = new JButton("Button 1"); positionnement que le gb.setConstraint(bt,c); composant passé en premier pnl.add(bt); paramètre utilisera les valeurs de la contrainte passée en second paramètre ... Stéphane GALLAND UTSEUS 2008 - LO02 114 GridBagLayout Language Java ● Exemple (suite) : ... c.gridx = 1; c.gridy = 0; bt = new JButton("Button 2"); gb.setConstraint(bt,c); pnl.add(bt); c.gridx = 2; c.gridy = 0; bt = new JButton("Button 3"); gb.setConstraint(bt,c); pnl.add(bt); ... Stéphane GALLAND UTSEUS 2008 - LO02 115 GridBagLayout Language Java ● Exemple (suite) : ... c.gridx = 0; c.gridy = 1; c.griwidth = 3; c.gridheight = 1; c.ipadx = 40; // margins bt = new Jbutton("Long-Named Button 4"); gb.setConstraint(bt,c); pnl.add(bt); ... Stéphane GALLAND UTSEUS 2008 - LO02 116 GridBagLayout Language Java ● Exemple (suite) : ... c.gridx = 1; c.gridy = 2; c.fill = GridBagConstraint.REMAINDER; c.ipadx = 0; // reset to default bt = new JButton("5"); gb.setConstraint(bt,c); pnl.add(bt); ... Code équivalent : pnl.add(bt, c); Stéphane GALLAND UTSEUS 2008 - LO02 117 Language Java Exercice corrigé Stéphane GALLAND UTSEUS 2008 - LO02 118 Exercice 1 Language Java ● Réaliser une fenêtre ressemblant à : Stéphane GALLAND UTSEUS 2008 - LO02 119 Solution exercice 1 Language Java ● Solution : – Liste des composants graphiques JScrollPane JLabel JList JLabel JButton JList JButton Stéphane GALLAND UTSEUS 2008 - LO02 JScrollPane caché 120 Solution exercice 1 Language Java public class MyFrame extends JFrame { public MyFrame() { JLabel listLabel1 = new JLabel("What MultiListener hears:"); JList list1 = new Jlist(); JScrollPane scroll1 = new JScrollPane(list1); JLabel listLabel2 = new JLabel("What Eavesdropper hears:"); JList list2 = new Jlist(); JScrollPane scroll2 = new JScrollPane(list2); JButton leftButton = new JButton("Blah blah blah"); JButton rightButton = new JButton("You don't say!"); ... Stéphane GALLAND UTSEUS 2008 - LO02 121 Language Java ● Solution exercice 1 Solution : – Deux panneaux possèdent des organisations différentes (layouts) Un grand panneau place son contenu verticalement : BoxLayout Stéphane GALLAND Un petit panneau place son contenu horizontalement : BoxLayout UTSEUS 2008 - LO02 122 Language Java Solution exercice 1 ... JPanel smallPanel = new JPanel(); smallPanel.setLayout( new BoxLayout(smallPanel,BoxLayout.X_AXIS)); smallPanel.add(leftButton); smallPanel.add(rightButton); JPanel bigPanel = new JPanel(); bigPanel.setLayout( new BoxLayout(bigPanel,BoxLayout.Y_AXIS)); bigPanel.add(listLabel1); bigPanel.add(scroll1); bigPanel.add(listLabel2); bigPanel.add(scroll2); bigPanel.add(smallPanel); ... Stéphane GALLAND UTSEUS 2008 - LO02 123 Solution exercice 1 Language Java ... // Ajoute le grand panneau dans la fenêtre getContentPane().add(bigPanel); // Initialisation de la taille préférée de la fenêtre setPreferredSize(new Dimension(400,400)); // Demande à la fenêtre de calculer la position réel // de tous ses composants pack(); } // End of constructor ... Stéphane GALLAND UTSEUS 2008 - LO02 124 Language Java ● ● Solution exercice 1 Les deux listes utilisent une approche MVC. Pour remplir ces listes, il faut utiliser deux modèles de type DefaultTreeModel JList JList Stéphane GALLAND UTSEUS 2008 - LO02 125 Language Java Solution exercice 1 ... // Création des deux modèles, et association de // chacun d'eux à une liste DefaultTreeModel model1 = new DefaultTreeModel(); list1.setModel(model1); DefaultTreeModel model2 = new DefaultTreeModel(); list2.setModel(model2); ... Stéphane GALLAND UTSEUS 2008 - LO02 126 Language Java Solution exercice 1 ... // Ajoute des données dans les listes model1.addElement("Blah blah blah"); model1.addElement("You don't say!"); model1.addElement("You don't say!"); model1.addElement("Blah blah blah"); model1.addElement("You don't say!"); model2.addElement("You don't say!"); model2.addElement("You don't say!"); model2.addElement("You don't say!"); } // end of MyFrame() } // end of class MyFrame Stéphane GALLAND UTSEUS 2008 - LO02 127 Solution exercice 1 Language Java ● Le résultat est : Stéphane GALLAND UTSEUS 2008 - LO02 128 Language Java ● Solution exercice 1 La solution précédente possède quelques problèmes Problème d'alignement Problème d'alignement Pas d'espace Stéphane GALLAND UTSEUS 2008 - LO02 129 Language Java ● Solution exercice 1 Un composant possède un attribut d'alignement par défaut : – pour un JLabel : aligné à gauche (LEFT_ALIGNMENT) – pour une JList : alignée au centre (CENTER_ALIGNMENT) Ligne d'alignement utilisée par BoxLayout avec Y_AXIS. Tous les composants sont alignés sur cette ligne. Stéphane GALLAND UTSEUS 2008 - LO02 130 Language Java ● ● ● Solution exercice 1 Pour corrigé ce problème d'alignement, il faut que tous les composants possède la même valeur de leurs paramètres d'alignement. Pour changer la valeur d'alignement : void setAlignmentX(int alignment); void setAlignmentY(int alignment); La valeur du paramètre alignement peut être : Component.LEFT_ALIGNMENT (valeur égale à 0) Component.CENTER_ALIGNMENT (valeur égale à 0.5) Component.RIGHT_ALIGNMENT (valeur égale à 1) Stéphane GALLAND UTSEUS 2008 - LO02 131 Language Java Solution exercice 1 ... scroll1.setAlignmentX( Component.LEFT_ALIGNMENT ); ... scroll2.setAlignmentX( Component.LEFT_ALIGNMENT ); ... smallPanel.setAlignmentX( Component.LEFT_ALIGNMENT ); ... Stéphane GALLAND UTSEUS 2008 - LO02 132 Language Java ● Solution exercice 1 Résoudre le problème de la position des boutons : ... smallPanel.add(Box.createHorizontalGlue()); smallPanel.add(leftButton); smallPanel.add(Box.createRigidArea(new Dimension(20,0))); smallPanel.add(rightButton); smallPanel.add(Box.createHorizontalGlue()); ... Stéphane GALLAND UTSEUS 2008 - LO02 133 Language Java Gestion des événements provenant de l'utilisateur Stéphane GALLAND UTSEUS 2008 - LO02 134 Language Java ● ● ● Gestionnaire d'événements Lorsque l'utilisateur réalise une action sur l'interface graphique, cette action est transformer en un événement la décrivant. Tout composant SWING peut produire un événement. Il sera alors qualifié de source de cet événement. La gestion des événements est basée sur l'utilisation de Listeners. Un listener reçoit les événements qu'il veut écouter. Stéphane GALLAND UTSEUS 2008 - LO02 135 Gestionnaire d'événements Language Java c : JComponent l1 : Listener l2 : Listener Utilisateur action graphique notification événement notification événement Stéphane GALLAND UTSEUS 2008 - LO02 136 Language Java ● ● Gestionnaire d'événements Les listeners sont en général des interfaces que doivent implanter des classes pour être autorisées à recevoir un événement. Chaque composant utilise un ou plusieurs types de Listeners : – – – – ActionListener (le plus utilisé) – en général touche « Enter » MouseListener – mouvements et boutons de la souris MouseWheelListener – roulette de la souris … Stéphane GALLAND UTSEUS 2008 - LO02 137 Language Java ● ● ActionListener L'ActionListener est une interface de Listener permettant de recevoir les événements de la catégorie « action », exemples : – clique sur un JBouton – appuie sur la touche « Enter » dans un JTextField L'interface ActionListener définie la fonction suivante : void actionPerformed(ActionEvent event); ● Cette fonction est appellée par le composant source pour chacun des Listeners. Le paramètre corresponds à l'événement. Stéphane GALLAND UTSEUS 2008 - LO02 138 Language Java ● Procédure pour gérer des événements La procédure « classique » pour gérer les événements est la suivante : 1.Créer un instance du composant source 2.Créer une instance de Listener 3.Enregistrer le Listener créé à l'étape 2 auprès du composant créé à l'étape 1. Cette étape est nécessaire pour informer le composant de la présence d'un nouveau Listener. Stéphane GALLAND UTSEUS 2008 - LO02 139 Language Java ● ● Procédure pour gérer des événements Cette procédure est illustrée sur l'exemple suivant : – A chaque clique sur un bouton graphique nommé « Fenêtre », le message « bouton cliqué » est affiché sur la console. Nous proposerons deux versions : – une version avec une classe nommée pour Listener – une version avec une classe anonyme pour Listener Stéphane GALLAND UTSEUS 2008 - LO02 140 Language Java Exemple : version 1 class MyListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("bouton cliqué"); } } class MyWin extends JFrame { public MyWin() { JButton bouton = new JButton("Fenêtre"); ActionListener listener = new MyListener(); bouton.addActionListener(listener); add(bouton); } } Stéphane GALLAND UTSEUS 2008 - LO02 1 2 3 141 Language Java Exemple : version 2 class MyWin extends JFrame { public MyWin() { JButton bouton = new JButton("Fenêtre"); ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("bouton cliqué"); } }; bouton.addActionListener(listener); add(bouton); 1 2 3 } } Stéphane GALLAND UTSEUS 2008 - LO02 142 Language Java Exercice corrigé Stéphane GALLAND UTSEUS 2008 - LO02 143 Exercice 2 Language Java ● ● ● Réaliser un convertisseur monétaire pour le dollars, l'euro, et le yuan. Les taux de convertion entre ces différentes devises monétaires devront être enregistrés dans des constantes. Conseil : utiliser une approche MVC Stéphane GALLAND UTSEUS 2008 - LO02 144 Language Java ● Solution exercice 2 L'approche MVC nous permet de proposer une solution en trois parties : – partie « modèle » – partie « vue » – partie « contrôleur » Stéphane GALLAND UTSEUS 2008 - LO02 145 Language Java ● Solution exercice 2 La partie « modèle » est une classe définie par : – un attribut contenant la valeur monétaire à convertir – un attribut indiquant le type de la convertion : ● euro vers dollars ● euro vers yuan ● dollars vers euro ● dollars vers yuan ● yuan vers euro ● yuan vers dollars – les fonctions permettant de convertir une valeur donnée dans une monnaie vers une valeur donnée dans une autre monnaie Stéphane GALLAND UTSEUS 2008 - LO02 146 Solution exercice 2 Language Java public class MonetaryModel { // Fonctions permettant de convertir une monnaie dans une autre public static double euro2yuan(double amount) { return amount * 10.7; } public static double yuan2euro(double amount) { return amount / 10.7; } public static double euro2dollars(double amount) return amount / 1.6; } public static double dollars2euro(double amount) return amount * 1.6; } public static double yuan2dollars(double amount) return euro2dollars(yuan2euro(amount)); } public static double dollars2yuan(double amount) return euro2yuan(dollars2euro(amount)); } ... Stéphane GALLAND UTSEUS 2008 - LO02 { { { { 147 Solution exercice 2 Language Java ... // Attributs du modèle private double amountToConvert; private int convertionType; // Valeurs pouvant être prises par l'attribut convertionType public public public public public public static static static static static static final final final final final final int int int int int int EURO_TO_YUAN = 0; EURO_TO_DOLLARS = DOLLARS_TO_YUAN = DOLLARS_TO_EURO = YUAN_TO_DOLLARS = YUAN_TO_EURO = 5; 1; 2; 3; 4; // Constructeur public MonetaryModel() { amountToConvert = 0; convertionType = YUAN_TO_EURO; } ... Stéphane GALLAND UTSEUS 2008 - LO02 148 Solution exercice 2 Language Java ... // Fonctions pour lire et changer les valeurs // des attributs du modèle public void setConvertionType(int type) { convertionType = type; } public int getConvertionType() { return convertionType; } public void setAmount(double amount) { amountToConvert = amount; } public double getAmountBeforeConvertion() { return amountToConvert; } ... Stéphane GALLAND UTSEUS 2008 - LO02 149 Solution exercice 2 Language Java ... public double getAmountAfterConvertion() { switch(convertionType) { case DOLLARS_TO_EURO: return dollars2euro(amountToConvert); case DOLLARS_TO_YUAN: return dollars2yuan(amountToConvert); case EURO_TO_DOLLARS: return euro2dollars(amountToConvert); case EURO_TO_YUAN: return euro2yuan(amountToConvert); case YUAN_TO_DOLLARS: return yuan2dollars(amountToConvert); case YUAN_TO_EURO: return yuan2euro(amountToConvert); default: return amountToConvert; } } } // End of class MonetaryModel Stéphane GALLAND UTSEUS 2008 - LO02 150 Language Java ● ● Solution exercice 2 Selon la définition de l'approche MVC, un modèle doit avertir ses représentations graphiques (vues) que l'une des valeurs du modèle a changé. Pour cela, il faut créer un mécanisme de création et de notification des événements. En Java ce mécanisme est basé sur les concepts de « Listener » et de « Event » Stéphane GALLAND UTSEUS 2008 - LO02 151 Language Java ● ● Un « Listener » est un objet qui veut être informé à chaque fois qu'un événement se produit. Quels sont les événements qui peuvent se produire dans le modèle que nous venons d'écrire ? – ● Solution exercice 2 Réponse : ● « Le montant a changé » ● « Le type de la convertion a changé » En Java, un « Listener » est une interface qui fournit une déclaration d'une fonction pour chaque type d'événement. Stéphane GALLAND UTSEUS 2008 - LO02 152 Solution exercice 2 Language Java public interface MonetaryModelListener extends EventListener { public void onAmountChangedEvent(MonetaryModelEvent event); public void onTypeChangedEvent(MonetaryModelEvent event); } Cette classe représente la description de l'événement. Elle est définie dans le transparent suivant. Stéphane GALLAND UTSEUS 2008 - LO02 153 Solution exercice 2 Language Java public class MonetaryModelEvent extends EventObject { private final double amount; private final int type; public MonetaryModelEvent(MonetaryModel source, double amount, int type) { super(source); this.amount = amount; this.type = type; } public double getAmount() { return amount; } public int getType() { return type; } } Stéphane GALLAND UTSEUS 2008 - LO02 154 Solution exercice 2 Language Java ● Une fois que les classes du « Listener » et de l'événement sont créées, il faut modifier la classe du modèle en ajoutant les fonctions permettant à un « Listener » de s'enregistrer pour recevoir l'événement public class MonetaryModel { ... private final Vector listeners = new Vector(); public void addMonetaryModelListener(MonetaryModelListener listener) { listeners.add(listener); } public void removeMonetaryModelListener(MonetaryModelListener listener) { listeners.remove(listener); } } Stéphane GALLAND UTSEUS 2008 - LO02 155 Solution exercice 2 Language Java ● Il faut ensuite créer une fonction par type d'événement qui permette d'envoyer l'événement aux « Listeners » public class MonetaryModel { ... protected void fireAmountChangedEvent() { MonetaryModelEvent event = new MonetaryModelEvent(this, amountToConvert, convertionType); for(int i=0; i<listeners.size(); i++) { MonetaryModelEvent oneListener = listeners.get(i); oneListener.onAmountChangedEvent(event); } } protected void fireTypeChangedEvent() { MonetaryModelEvent event = new MonetaryModelEvent(this, amountToConvert, convertionType); for(int i=0; i<listeners.size(); i++) { MonetaryModelEvent oneListener = listeners.get(i); oneListener.onTypeChangedEvent(event); } } } Stéphane GALLAND UTSEUS 2008 - LO02 156 Solution exercice 2 Language Java ● Enfin, la dernière étape pour implanter le modèle est la modification des fonctions qui permettent de changer les valeurs des attributs du modèle. Cette modification consiste à informer les « Listeners » que la valeur a changée. public class MonetaryModel { ... public void setAmount(double amount) { amountToConvert = amount; fireAmountChangedEvent(); } ... public void setConvertionType(int type) { convertionType = type; fireTypeChangedEvent(); } ... } Stéphane GALLAND UTSEUS 2008 - LO02 157 Language Java ● ● Solution exercice 2 La partie « vue » est un ensemble de composants graphiques correspondant à l'image suivante : Il faut créer une fenêtre avec ces composants Stéphane GALLAND UTSEUS 2008 - LO02 158 Language Java Solution exercice 2 public class MonetaryConvertionFrame extends JFrame { // Constantes pour l'affichage public static final String EURO_TO_YUAN = "Euro -> Yuan"; public static final String EURO_TO_DOLLARS = "Euro -> Dollars"; public static final String DOLLARS_TO_YUAN = "Dollars -> Yuan"; public static final String DOLLARS_TO_EURO = "Dollars -> Euro"; public static final String YUAN_TO_DOLLARS = "Yuan -> Dollars"; public static final String YUAN_TO_EURO = "Yuan -> Euro"; public static final String EURO = " €"; public static final String DOLLARS = " $US"; public static final String YUAN = " RMB"; // Modèle utilisé par cette vue private final MonetaryModel model; // Composants graphiques nécessitant des // changements dans leurs affichages private JTextField valueField; private JComboBox typeList; private JLabel resultLabel; ... Stéphane GALLAND UTSEUS 2008 - LO02 159 Language Java Solution exercice 2 ... public MonetaryConvertionFrame(MonetaryModel model) { super("Convertion monétaire"); // La vue se souvient de son modèle this.model = model; // La vue veut recevoir les événements du modèle this.model.addMonetaryModelListener(this); // Création des composants graphiques JLabel label1 = new JLabel("Valeur à convertir :"); valueField = new JTextField(); JLabel label2 = new JLabel("Type de convertion :"); typeList = new JComboBox(); typeList.setEditable(false); DefaultComboBoxModel listModel = new DefaultComboBoxModel(); typeList.setModel(listModel); JButton convertButton = new JButton("Convertir"); resultLabel = new JLabel(); ... Stéphane GALLAND UTSEUS 2008 - LO02 160 Solution exercice 2 Language Java ... // Le constructeur continue ici JPanel panel = new JPanel(); panel.setLayout(new GridLayout(3,2)); panel.add(label1); panel.add(valueField); panel.add(label2); panel.add(typeList); panel.add(convertButton); panel.add(resultLabel); getContentPane().setLayout(new BorderLayout()); getContentPane().add(panel, BorderLayout.CENTER); panel.setPreferredSize(new Dimension(400,200)); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); pack(); ... Stéphane GALLAND UTSEUS 2008 - LO02 161 Solution exercice 2 Language Java ... // Le constructeur continue ici // Remplir la liste des types de convertion listModel.addElement(EURO_TO_YUAN); listModel.addElement(EURO_TO_DOLLARS); listModel.addElement(DOLLARS_TO_YUAN); listModel.addElement(DOLLARS_TO_EURO); listModel.addElement(YUAN_TO_DOLLARS); listModel.addElement(YUAN_TO_EURO); // Mise à jour du contenu des composants graphiques // avec les informations extraites du modèle updateViewContent(); } // End of the constructor ... Stéphane GALLAND UTSEUS 2008 - LO02 162 Solution exercice 2 Language Java ... public void updateViewContent() { valueField.setText(Double.toString(model.getAmo untBeforeConvertion())); String devise; switch(model.getConvertionType()) { case MonetaryModel.DOLLARS_TO_EURO: typeList.setSelectedItem(DOLLARS_TO_EURO); devise = EURO; break; case MonetaryModel.DOLLARS_TO_YUAN: typeList.setSelectedItem(DOLLARS_TO_YUAN); devise = YUAN; break; case MonetaryModel.YUAN_TO_EURO: typeList.setSelectedItem(YUAN_TO_EURO); devise = EURO; break; ... Stéphane GALLAND UTSEUS 2008 - LO02 163 Language Java Solution exercice 2 ... case MonetaryModel.YUAN_TO_DOLLARS: typeList.setSelectedItem(YUAN_TO_DOLLARS); devise = DOLLARS; break; case MonetaryModel.EURO_TO_YUAN: typeList.setSelectedItem(EURO_TO_YUAN); devise = YUAN; break; case MonetaryModel.EURO_TO_DOLLARS: typeList.setSelectedItem(EURO_TO_DOLLARS); devise = DOLLARS; break; default: return; } resultLabel.setText(Double.toString(model.getAm ountAfterConvertion()) + devise); } // End of updateViewContent() ... Stéphane GALLAND UTSEUS 2008 - LO02 164 Solution exercice 2 Language Java ... public static final void main(String[] args) { // Création du modèle MonetaryModel model = new MonetaryModel(); // Création de la vue ET du contrôleur MonetaryConvertionFrame view = new MonetaryConvertionFrame(model); // Affichage de la fenêtre view.setVisible(true); } } // End of class Stéphane GALLAND UTSEUS 2008 - LO02 165 Language Java ● ● ● ● Solution exercice 2 Selon la définition de l'approche MVC, la partie « vue » doit être informée de chaque changement dans le modèle afin qu'elle puisse raffraichir son contenu. Dans cet exercice, la « vue » doit écouter le modèle concernant les événéments de modification. Nous en déduisons que la vue est un écouteur de type MonetaryModelListener Il faut donc modifier la classe MonetaryModelFrame comme indiqué dans le transparent suivant. Stéphane GALLAND UTSEUS 2008 - LO02 166 Language Java Solution exercice 2 public class MonetaryConvertionFrame extends JFrame implements MonetaryModelListener { ... public void onAmountChange(MonetaryModelEvent event) { // Lorsque le montant à convertir dans le modèle // change, il faut modifier les valeurs affichées // dans les composants graphiques updateViewContent(); } public void onTypeChange(MonetaryModelEvent event) { // Lorsque le type de convertion dans le modèle // change, il faut modifier les valeurs affichées // dans les composants graphiques updateViewContent(); } } // End of class Stéphane GALLAND UTSEUS 2008 - LO02 167 Language Java ● Solution exercice 2 La partie « contrôleur » définie comment l'utilisateur peut interagir avec l'interface graphique, et ce qui doit être fait en retour : Quand l'utilisateur clique sur le bouton, le modèle est mis à jour avec les données dans cette fenêtre Stéphane GALLAND UTSEUS 2008 - LO02 168 Language Java ● ● ● Solution exercice 2 En accord avec le modèle de gestion des événéments de SWING, un bouton informe un ActionListener lorsque l'utilisateur clique sur le bouton. Dans cet exercice, le contrôleur est un ActionListener qui écoute les événements du bouton « Convertir » Le code de la classe MonetaryConvertionFrame est modifié comme cela est indiqué dans la diapositive suivante : Stéphane GALLAND UTSEUS 2008 - LO02 169 Language Java Solution exercice 2 public class MonetaryConvertionFrame extends JFrame implements MonetaryModelListener, ActionListener { ... public void actionPerformed(ActionEvent event) { // quelles sont les valeurs dans le modèle ? double currentModelAmount = model.getAmountBeforeConvertion(); int currentModelType = model.getConvertionType(); ... Stéphane GALLAND UTSEUS 2008 - LO02 170 Language Java Solution exercice 2 ... // quelles sont les valeurs saisie par l'utilisateur ? double inputAmount = Double.parseDouble(valueField.getText()); int inputType; String selectedType = (String)typeList.getSelectedItem(); if (EURO_TO_YUAN.equals(selectedType)) inputType = MonetaryModel.EURO_TO_YUAN; else if (EURO_TO_DOLLARS.equals(selectedType)) inputType = MonetaryModel.EURO_TO_DOLLARS; else if (YUAN_TO_DOLLARS.equals(selectedType)) inputType = MonetaryModel.YUAN_TO_DOLLARS; else if (YUAN_TO_EURO.equals(selectedType)) inputType = MonetaryModel.YUAN_TO_EURO; else if (DOLLARS_TO_YUAN.equals(selectedType)) inputType = MonetaryModel.DOLLARS_TO_YUAN; else inputType = MonetaryModel.DOLLARS_TO_EURO; ... Stéphane GALLAND UTSEUS 2008 - LO02 171 Solution exercice 2 Language Java ... // Si la valeur saisie par l'utilisateur est différente // de la valeur dand le modèle, alors la valeur du modèle est // changée if (currentModelAmount!=inputAmount) { model.setAmount(inputAmount); } // // // if } Si le type saisie par l'utilisateur est différent du type dans le modèle, alors le type dans le modèle est changée (currentModelType!=inputType) { model.setConvertionType(inputType); } // End of actionPerformed() } // End of class MonetaryConverterFrame Stéphane GALLAND UTSEUS 2008 - LO02 172 Language Java Composants complexes JTree et JTable Stéphane GALLAND UTSEUS 2008 - LO02 173 Language Java ● Composants complexes La suite de ce cours est consacrée à deux composants graphiques complexes : – JTree : affichage d'informations dans un arbre – JTable : affichage d'informations dans un tableau Stéphane GALLAND UTSEUS 2008 - LO02 174 Language Java ● ● ● Composant complexe : JTree La classe JTree permet d'afficher des données hiérarchiques Un objet JTree ne contient pas les données utilisateur; il fournit une vue sur ces données Comme la plupart des composants SWING, la classe JTree utilise une approche Modèle Vue Contrôleur (MVC) : – modèle : TreeModel – vue et contrôleur : JTree Stéphane GALLAND UTSEUS 2008 - LO02 175 Language Java ● ● ● Composant complexe : JTree Chaque ligne dans un JTree contient exactement un item, qui est appelé noeud (ou node) Chaque JTree possède un noeud racine (root). Par défaut un JTree affiche le noeud racine, mais il peut ne pas l'être si cela est nécessaire. Un noeud peut avoir des fils ou non. Les noeuds pouvant avoir des fils sont nommés noeuds de branche (branch node). Les noeuds ne pouvant pas avoir de fils sont nommés noeuds feuilles (leaf node) Stéphane GALLAND UTSEUS 2008 - LO02 176 Language Java ● ● Composant complexe : JTree Les noeuds de branche peuvent être ouverts ou fermés par l'utilisateur, rendant ainsi les noeuds fils visibles ou invisibles. Ces deux actions sont réalisables en : – cliquant sur le signe ou – en double cliquant sur le noeud Une application peut détecter ces changements en écoutant (listening) les événements d'expansion de l'arbre. Stéphane GALLAND UTSEUS 2008 - LO02 177 Language Java ● ● Créer un JTree Un JTree utilise un modèle basé sur des noeuds. La classe Java la plus utilisée pour représenter un noeud est DefaultMutableTreeNode. Un JTree étant une représentation hiérarchique, il est obligatoire d'avoir un noeud racine, généralement spécifié lors de la construction du JTree : DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root Node"); JTree tree = new JTree(root); JScrollPane treeView = new JScrollPane(tree); Stéphane GALLAND UTSEUS 2008 - LO02 178 Créer un JTree Language Java ● ● Un JTree utilise un modèle basé sur des noeuds. La classe Java la plus utilisée pour représenter un noeud est DefaultMutableTreeNode. Création d'une instance Un JTree étant une représentation hiérarchique, il est représentant le noeud obligatoire d'avoir un noeud racine, généralement spécifié lors racine de la construction du JTree : DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root Node"); JTree tree = new JTree(root); JScrollPane treeView = new JScrollPane(tree); Création d'une instance de JTree en spécifiant le noeud racine Stéphane GALLAND UTSEUS 2008 - LO02 En général un objet de type JTree est inséré dans un JScrollPane afin de permettre l'apparition des ascenseurs si le contenu du JTree ne peut pas apparaître totalement à l'écran 179 JTree : Créer des noeuds Language Java ● Les noeud d'un JTree sont en général des DefaultMutableTreeNode car cette classe possède les fonctions suivantes : – support de la hiérarchie : void add(MutableTreeNode child); int getChildCount(); MutableTreeNode getChildAt(int index); TreeNode getParent(); ... – support de données utilisateur : void setUserObject(Object data); Object getUserObject(); Stéphane GALLAND UTSEUS 2008 - LO02 180 JTree : Créer des noeuds Language Java ● Illustration (version 1): DefaultMutableTreeNode parent1 = new DefaultMutableTreeNode("Parent 1"); root.add(parent1); DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1"); parent1.add(child1); DefaultMutableTreeNode newNode1 = new DefaultMutableTreeNode("New Node 1"); DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child 2"); parent1.add(child2); Afin de mettre à jour la vue, il est nécessaire d'appeller la fonction reload(). child2.add(newNode1); Celle-ci va notifier le JTree que le contenu du modèle a été changé. tree.getModel().reload(); D'autres fonctions existent afin d'informer ... plus finement la vue des changements. Stéphane GALLAND UTSEUS 2008 - LO02 181 JTree : Créer des noeuds Language Java ● Illustration (version 2): DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); DefaultMutableTreeNode parent1 = new DefaultMutableTreeNode("Parent 1"); model.insertNodeInto(parent1,root,0); DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1"); model.insertNodeInto(child1,parent1,0); ... Les fonctions d'insertion proposées par le modèle informe automatiquement la vue (l'objet JTree) qu'elle doit se mettre à jour. Stéphane GALLAND UTSEUS 2008 - LO02 182 Language Java ● ● Répondre aux événements de sélection dans un JTree Intercepter et répondre à un événement de sélection sur un JTree est simple. Il faut implanter un TreeSelectionListener et l'enregistrer auprès du Jtree avec la fonction addTreeSelectionListener() : TreeSelectionListener listener = new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { // Réaction à une selection décrite par // l'événement e } }; tree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION); tree.addTreeSelectionListener(listener); Stéphane GALLAND UTSEUS 2008 - LO02 183 Language Java ● ● Répondre aux événements de sélection dans un JTree Intercepter et répondre à un événement de sélection sur un JTree est simple. Il faut implanter un TreeSelectionListener et l'enregistrer auprès du Jtree avec la fonction addTreeSelectionListener() : TreeSelectionListener listener = new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { // Réaction à une selection décrite par // l'événement e } }; tree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION); tree.addTreeSelectionListener(listener); Création d'un Listener devant réagir à un événement de sélection Stéphane GALLAND UTSEUS 2008 - LO02 184 Language Java ● ● Répondre aux événements de sélection dans un JTree Intercepter et répondre à un événement de sélection sur un JTree est simple. Il faut implanter un TreeSelectionListener et l'enregistrer auprès du Jtree avec la fonction addTreeSelectionListener() : TreeSelectionListener listener = new TreeSelectionListener() { Enregistrement du listener créée) auprès public void valueChanged(TreeSelectionEvent { de l'objet JTree afin qu'il soit notifié à chaque // Réaction à une selection décrite fois qu'une sélection par se produit dans le // l'événement e JTree. } }; tree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION); tree.addTreeSelectionListener(listener); Stéphane GALLAND UTSEUS 2008 - LO02 185 Language Java ● Répondre aux événements de sélection dans un JTree Intercepter et répondre à un événement de sélection sur un JTree est simple. ● L'objet JTree implanter incluse un modèle de Il faut un TreeSelectionListener et l'enregistrer auprès sélection des noeuds du Jtree avec(getSelectionModel). la fonction addTreeSelectionListener() : Ce modèle permet de spécifier le type de TreeSelectionListener listener = new sélection autorisé : TreeSelectionListener() { - SINGLE_TREE_SELECTION : un seul noeud peut être sélectionné à la fois. public void valueChanged(TreeSelectionEvent e) { - CONTIGUOUS_TREE_SELECTION : // peuvent Réaction plusieurs noeuds être à une selection décrite par //même l'événement e sélectionnés en temps. Tous les noeuds sélectionnés sont contigus. } - DISCONTIGUOUS_TREE_SELECTION : }; plusieurs noeuds peuvent être sélectionnés en même temps. Les tree.getSelectionModel().setSelectionMode noeuds sélectionnés peuvent ne pas être (TreeSelectionModel.SINGLE_TREE_SELECTION); contigus. tree.addTreeSelectionListener(listener); Stéphane GALLAND UTSEUS 2008 - LO02 186 Language Java ● ● Répondre aux événements de modification du contenu d'un JTree Intercepter et répondre à un événement de changement du contenu d'un JTree est simple. Il faut implanter un TreeModelListener et l'enregistrer auprès du modèle du JTree avec la fonction addTreeModelListener() : TreeModelListener listener = new TreeModelListener() { public } public } public } public } void treeNodesChanged(TreeModelEvent e) { void treeNodesInserted(TreeModelEvent e) { void treeNodesRemoved(TreeModelEvent e) { void treeStructureChanged(TreeModelEvent e) { }; tree.getModel().addTreeModelListener(listener); Stéphane GALLAND UTSEUS 2008 - LO02 187 Language Java ● ● Changer l'affichage dans un JTree Voici quelques exemples d'affichages différents d'un même JTree : Quelques fonctions simples du JTree permettent de modifier l'affichage : – Affiche ou non le noeud racine : void JTree.setRootVisible(boolean visible) – Affiche ou non la poignée du noeud racine : void JTree.setShowsRootHandles(boolean visible) – Change le style des lignes entre les noeuds : void JTree.putClientProperty("JTree.lineStyle", v); où v est "Angled" (défaut), "Horizontal" ou "None" Stéphane GALLAND UTSEUS 2008 - LO02 188 Language Java ● ● ● Changer l'affichage dans un JTree Voici quelques exemples d'affichages différents d'un même JTree : Un JTree utilise un objet particulier pour dessiner les noeuds : un TreeCellRenderer ou DefaultTreeCellRenderer Il est alors possible de changer l'affichage d'un noeud en implantant un nouveau TreeRenderer et en le fournissant au JTree grâce à la fonction void setRenderer(TreeCellRenderer renderer); Stéphane GALLAND UTSEUS 2008 - LO02 189 Language Java ● ● ● Composant complexe : JTable La classe JTable permet d'afficher des données au sein d'une table, et permet également d'éditer ces données Un objet JTable ne contient pas les données utilisateur; il fournit une vue sur ces données Comme la plupart des composants SWING, la classe JTable utilise une approche Modèle Vue Contrôleur (MVC) : – modèle : TableModel – vue et contrôleur : JTable Stéphane GALLAND UTSEUS 2008 - LO02 190 Language Java ● ● ● Composant complexe : JTable Une table est composée de colonnes de valeurs. Toutes les valeurs appartenant à une colonne sont du même type. Chaque cellule de la table est associée à une donnée utilisateur qui est alors affichée (en utilisant le plus souvant le résultat de la fonction toString()). Une table peut posséder une entête permettant : – de donner un nom aux colonnes – de trier les éléments de la colonne – de changer le type des élements de la colonnes Stéphane GALLAND UTSEUS 2008 - LO02 191 Language Java ● ● Créer une JTable Une JTable utilise un modèle basé sur des cellules. La classe Java la plus utilisée pour représenter ce modèle est DefaultTableModel. Une manière simple de créer une JTable est : JTable table = new JTable(); JScrollPane tableView = new JScrollPane(table); table.setFillsViewportHeight(true); Stéphane GALLAND UTSEUS 2008 - LO02 192 Language Java ● Modèle de données pour une JTable Le modèle de donnée utilisé par une JTable est accessible via les fonctions : void JTable.setModel(TableModel model); TableModel JTable.getModel(); ● Le modèle de données pour une JTable implante l'interface TableModel qui propose les fonctions suivantes : – int TableModel.getColumnCount(); ● – String TableModel.getColumnName(int index); ● – retourne le nom de la colonne à l'index spécifié Class TableModel.getColumnClass(int index); ● – retourne le nombre de colonnes dans la table retourne le type des valeurs d'une colonne int TableModel.getRowCount(); ● retourne le nombre de lignes dans la table Stéphane GALLAND UTSEUS 2008 - LO02 193 Language Java ● Modèle de données pour une JTable Suite des fonctions proposées par le TableModel : – Object TableModel.getValueAt(int rowIndex, int columnIndex); ● – void TableModel.setValueAt(Object newValue, int rowIndex, int columnIndex); ● – retourne la valeur d'une cellule change la valeur d'une cellule boolean TableModel.isCellEditable(int rowIndex, int columnIndex); ● retourne une valeur indiquant si la cellule spécifiée est éditable ou non Stéphane GALLAND UTSEUS 2008 - LO02 194 Language Java ● ● Répondre aux événements de sélection dans une JTable Par défaut, une JTable supporte une sélection de une ou plusieurs lignes (contigües ou non). L'utilisateur peut utiliser la souris ou le clavier pour réaliser une sélection, comme cela est décrit dans la table suivante : Opération Action Souris Action Clavier Séléction d'une seule Clic Haut ou Bas ligne Etendre une sélection Shift+Clic ou drag sur Shift+Haut ou Shift continue plusieurs lignes +Bas Déplacer la cellule Ajouter une ligne à la Control+Clic courante avec Haut et sélection ou inverser Bas, puis appuyer sur la sélection d'une Espace pour modifier ligne la sélection de la cellule Stéphane GALLAND UTSEUS 2008 - LO02 195 Language Java ● ● Répondre aux événements de sélection dans une JTable Le modèle de sélection (TableSelectionModel) utilisé par une JTable autorise plusieurs modes de sélection : – ListSelectionModel.MULTIPLE_INTERVAL_SELECTION – ListSelectionModel.SINGLE_INTERVAL_SELECTION – ListSelectionModel.SINGLE_SELECTION Ces modes de sélection peuvent être utilisé en paramètre de la fonction : – void TableSelectionModel.setSelectionMode(int mode); Stéphane GALLAND UTSEUS 2008 - LO02 196 Language Java ● Répondre aux événements de sélection dans une JTable Le modèle de sélection (TableSelectionModel) utilise également des possibilités de restriction de la sélection : – sélectionner uniquement les lignes – sélectionner uniquement les colonnes – sélectionner les cellules individuellement void TableSelectionModel.setRowSelectionAllowed(boolean) boolean TableSelectionModel.getRowSelectionAllowed(); void TableSelectionModel.setColumnSelectionAllowed(boolean) boolean TableSelectionModel.getColumnSelectionAllowed(); void TableSelectionModel.setCellSelectionAllowed(boolean) boolean TableSelectionModel.getCellSelectionAllowed(); Stéphane GALLAND UTSEUS 2008 - LO02 197 Language Java ● ● Répondre aux événements de sélection dans une JTable Intercepter et répondre à un événement de sélection sur une JTable est simple. Il faut implanter un ListSelectionListener et l'enregistrer auprès du JTable avec la fonction addListSelectionListener() : ListSelectionListener listener = new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { // Réaction à une selection décrite par // l'événement e } }; table.getSelectionModel(). addListSelectionListener(listener); Stéphane GALLAND UTSEUS 2008 - LO02 198 Répondre aux événements de changement des données dans une JTable Language Java ● ● Intercepter et répondre à un événement de changement des données dans une JTable est simple. Il faut implanter un TableModelListener et l'enregistrer auprès du modèle de la JTable avec la fonction addTableModelListener() : TableModelListener listener = new TableModelListener() { public void tableChanged(TableModelEvent e) { // Réaction à un changement dans les données } }; table.getModel(). addTableModelListener(listener); Stéphane GALLAND UTSEUS 2008 - LO02 199 Language Java Dessiner librement des formes Stéphane GALLAND UTSEUS 2008 - LO02 200 Bibliothèque AWT Language Java ● ● ● La bibliothèque AWT est à la base des applications graphiques écritent en Java. La bibliothèque SWING est une extension de la bibliothèque AWT. La bibliothèque AWT fournit un ensemble d'outils permettant de gérer l'affichage des composants. Chaque composant graphique possède une fonction qui permet de le dessiner à l'écran. Cette fonction s'appelle : – ● void paint(Graphics g) La fonction paint() est appelée à chaque fois que le contenu du composant doit être dessiné : – – la 1ére fois qu'il est dessiné, quand le composant est masqué puis démasqué, ... Stéphane GALLAND UTSEUS 2008 - LO02 201 Language Java Comment dessiner librement ● Un composant peut dessiner ce qu'il veut sur l'écran. ● Pour cela il doit implanter une fonction paint(). ● ● En général les composants qui se dessine de cette manière sont des classes filles du composant JPanel. Exemple d'un panneau qui affiche l'heure actuelle : class ClockDisplayer extends JPanel { public void paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; Date currentDate = new Date(); g2d.drawString(currentDate.toString(), 0, 0); } } Stéphane GALLAND UTSEUS 2008 - LO02 202 Language Java ● Contexte graphique La fonction paint() prend en paramètre un contexte graphique (une représentation informatique d'écran d'ordinateur). La bibliothèque AWT appelle la fonction paint() en passant un paramètre un objet de type Graphics2D class ClockDisplayer extends JPanel { public void paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; Date currentDate = new Date(); g.drawString(currentDate.toString(), 0, 0); } } ● ● Le contexte graphique est un objet qui est capable de dessiner directement sur l'écran. Par conséquent, les classes Graphics et Graphics2D proposent des fonctions permettant de dessiner. Stéphane GALLAND UTSEUS 2008 - LO02 203 Language Java ● Dessiner une chaîne de caractères Dessiner une chaîne de caractère est possible avec la fonction : void drawString(String text, int x, int y); ● Exemple : class ClockDisplayer extends JPanel { public void paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; Date currentDate = new Date(); g.drawString(currentDate.toString(), 0, 0); } } Stéphane GALLAND UTSEUS 2008 - LO02 204 Language Java ● Dessiner une ligne Dessiner une ligne entre deux points est possible avec la fonction : void drawLine(int x1, int y1, int x2, int y2); ● Exemple : class LineDisplayer extends JPanel { public void paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; Dimension size = getSize(); int x1, x2, y1, y2; x1 = y1 = 0; x2 = 0 + size.width; y2 = 0 + size.height; g.drawLine(x1,y1,x2,y2); } } Stéphane GALLAND UTSEUS 2008 - LO02 205 Changer la couleur Language Java ● Changer la couleur d'affichage : void setColor(Color red); ● Exemple : class LineDisplayer extends JPanel { public void paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; g2d.setColor(new Color(255,0,0)); g2d.drawString("Exemple", 0,0); } } ● L'objet Color définie une couleur à partir des composantes Rouge, Verte et Bleue. Stéphane GALLAND UTSEUS 2008 - LO02 206 Language Java ● ● Autres fonctions Les classes Graphics et Graphics2D proposent de nombreuses fonctions permettant de dessiner sur l'écran. Ce support de cours ne fait pas la liste de toutes les fonctions. Veuillez regarder la documentation officiel Java des classes Graphics et Graphics2D pour avoir une liste complète – – manuel de référence : http://java.sun.com/javase/reference/api.jsp explications et tutoriels : http://java.sun.com/javase/6/docs/ Stéphane GALLAND UTSEUS 2008 - LO02 207 Language Java Exercice corrigé Stéphane GALLAND UTSEUS 2008 - LO02 208 Exercice 3 Language Java ● ● Réaliser une application permettant d'explorer le contenu d'un système de fichier. L'application devra avoir l'interface suivante (vous pourrez changer les images à votre convenance) : Stéphane GALLAND UTSEUS 2008 - LO02 209 Language Java ● Solution exercice 3 La correction de cet exercice est proposée dans des sources Java distribuées. Stéphane GALLAND UTSEUS 2008 - LO02 210 Language Java Cours LOO2 Partie 7 Design Patterns Dr. Stéphane GALLAND [email protected] Université de Technologie de Belfort-Montbéliard (UTBM) Stéphane GALLAND UTSEUS 2008 1 Plan du cours Language Java ● Introduction ● Modèle Singleton Stéphane GALLAND UTSEUS 2008 2 Introduction Language Java ● ● Les design patterns sont des modèles de conception réutilisables. Ils constituent des solutions concernant des problèmes récurrents architecturaux dans la conception de logiciels. Ces modèles se divisent en trois grands domaines : – création, – structure, – comportement. Stéphane GALLAND UTSEUS 2008 3 Language Java ● Modèle de création - Modèle Singleton Modèle Singleton – Un des modèles relativement simple concernant la création est le modèle du Singleton. – Ce modèle s’utilise lorsque il n’y a qu’une unique instance d’une classe et qu’elle doit être accessible de manière connue (exemple : la compagnie de transport). – Modèle de code : class Singleton { private static Singleton unique = new Singleton(); public static Singleton instance() { return unique; } } Stéphane GALLAND UTSEUS 2008 4 Modèle de structure Language Java ● Ces modèles concernent la manière dont les objets sont assemblés. Ils sont complémentaires entre eux. Stéphane GALLAND UTSEUS 2008 5 Language Java ● ● Modèle de structure - Modèle Adapter Un exemple simple de modèle de structure est le modèle Adapter assez utilisé dans la bibliothèque Java (notamment dans Swing). Ce modèle s’utilise lorsqu’on souhaite : – implémenter plusieurs interfaces mais seulement quelques méthodes doivent être définies et qu’il il est coûteux de redéfinir les autres méthodes, – adapter l’interface d’une classe existante. Stéphane GALLAND UTSEUS 2008 6 Language Java Modèle de structure - Modèle Adapter « interface » MouseAdapter mouseClicked(MouseEvent) mousePressed(MouseEvent) mouseReleased(MouseEvent) mouseMoved(MouseEvent) mouseDragged(MouseEvent) Component fireClick() MouseAdapter mouseClicked(MouseEvent) mousePressed(MouseEvent) mouseReleased(MouseEvent) mouseMoved(MouseEvent) mouseDragged(MouseEvent) MyAdapter MyObject mouseClicked(MouseEvent) Stéphane GALLAND UTSEUS 2008 7 Language Java ● Modèle de structure - Modèle Bridge On utilise le modèle Bridge lorsque : – on veut éviter un lien permanent entre l'abstraction et l'implantation (ex: l'implantation est choisie à l'exécution), – l'abstraction et l'implantation sont toutes les deux susceptibles d'être raffinées, – les modifications subies par l'implantation ou l'abstraction ne doivent pas avoir d'impacts sur le client (pas de recompilation). Stéphane GALLAND UTSEUS 2008 8 Language Java Modèle de structure - Modèle Bridge Client launchOperation() « interface » Abstraction operation() RefinedAbstraction operation() Stéphane GALLAND UTSEUS 2008 « interface » Implementation runOperation() ConcreteImplementation runOperation() 9 Language Java ● Modèle de structure - Modèle Composite On utilise Composite lorsque l’on veut : – représenter une hiérarchie d'objets (arbre), – ignorer la différence entre un composant simple et un composant en contenant d'autres (interface uniforme). Stéphane GALLAND UTSEUS 2008 10 Language Java Modèle de structure - Modèle Composite « abstract » Component * operation() 0..1 Leaf Stéphane GALLAND Composite UTSEUS 2008 11 Language Java ● Modèle de comportement Les modèles de comportement concernent la manière dont les objets interagissent entre eux. Stéphane GALLAND UTSEUS 2008 12 Language Java ● ● Modèle de comportement – Modèle Iterator Un exemple simple de modèle de comportement est le modèle Iterator (Itérateur) implémenté dans l’API Java via l’interface java.util.Iterator. Ce modèle s’utilise lorsqu’on souhaite : – accéder aux éléments d’un objet sans en exposer la structure, – offrir une interface uniforme pour parcourir différents types d’objets. Stéphane GALLAND UTSEUS 2008 13 Language Java Modèle de comportement - Modèle Iterator Client operation() « interface » Iterator « interface » Collection hasNext() : booléen next() : Objet iterator() : Iterator ConcreteCollection ConcreteIterator hasNext() : booléen next() : Objet Stéphane GALLAND UTSEUS 2008 manipulate iterator() : Iterator 14 Language Java ● ● ● Modèle de comportement – Modèle Observer Un autre exemple, plus complexe, est le modèle Observer implémenté dans l’API via la classe java.util.Observable et l’interface java.util.Observer. Ce modèle s’utilise lorsqu’on souhaite : – que le changement d’un objet affecte d’autres objets, – que cet objet ne connaisse pas a priori les objets à notifier. Ce modèle peut être rapproché du modèle Listener, également utilisé par l'API Java Stéphane GALLAND UTSEUS 2008 15 Language Java Modèle de comportement - Modèle Observer Client manipulate operation() « interface » Observer update(Observable) Observable addObserver(Oberver) notifiesObservers() ConcreteObserver manipulate Stéphane GALLAND update(Obersable) UTSEUS 2008 16 Language Java Exercices Stéphane GALLAND UTSEUS 2008 17 Exercice 1 Language Java ● Proposer l'implantation d'un arbre binaire en utilisant le modèle Composite. Stéphane GALLAND UTSEUS 2008 18 Exercice 2 Language Java ● A partir de la solution de l'exercice 1, implanter le modèle Iterator sur les feuilles de l'arbre. Stéphane GALLAND UTSEUS 2008 19 Exercice 3 Language Java ● A partir de la solution de l'exercice 2, implanter le modèle Observer en utilisant deux threads : – le premier thread ajoute ou suprime aléatoirement des noeuds dans un arbre; – le second thread affichera sur la console toutes les modifications apportées par le premier thread. Stéphane GALLAND UTSEUS 2008 20 Language Java Cours LOO2 Partie 8 Java 5 et Java 6 Nouvelles syntaxes et fonctionnalités Dr. Stéphane GALLAND [email protected] Université de Technologie de Belfort-Montbéliard (UTBM) Stéphane GALLAND UTSEUS 2008 1 Plan du cours Language Java ● Introduction ● Autoboxing ● Foreach ● Type énuméré ● Méthodes à arguments variables ● Méta-programmation par annotations ● Génériques ● Nouvelles fonctionnalités dans la bibliothèque Stéphane GALLAND UTSEUS 2008 2 Plan du cours Language Java ● Introduction ● Autoboxing ● Foreach ● Type énuméré ● Méthodes à arguments variables ● Méta-programmation par annotations ● Génériques ● Nouvelles fonctionnalités dans la bibliothèque Stéphane GALLAND UTSEUS 2008 3 Introduction Language Java ● ● La version 5 de Java introduit de nombreux changements dans la syntaxe et dans les fonctionnalités proposées. Ce cours introduit certaines nouveautés, et n'aborde pas dans les détails celles-ci. Stéphane GALLAND UTSEUS 2008 4 Autoboxing des types primitifs Language Java ● Problème initial : – On veut utiliser une collection pour stocker des éléments de types primitifs (int, boolean, double, …) – Lors de l’ajout d’un élément dans la collection il faut le « Wrapper » dans une classe de référence (Integer, Boolean, Double,…). C’est le boxing. – De même l’opération inverse est nécessaire pour retrouver le type initial. (unboxing) Stéphane GALLAND UTSEUS 2008 5 Language Java ● Solution : – ● Autoboxing des types primitifs Le compilateur se charge automatiquement de la conversion Exemple : Avant Après List intList = new ArrayList(); int monInt = 100; list.add (new Integer (monInt)); List intList = new ArrayList(); int monInt = 100; list.add (monInt); Stéphane GALLAND UTSEUS 2008 6 Foreach et itérateurs Language Java ● Problème initial : – ● ● Parcourir une collection en utilisant un itérateur et une boucle for requiert une syntaxe parfois lourde et fastidieuse. Solution : – Simplification de la syntaxe du for dans ce cas précis de façon à alléger le code – Le for ressemble alors à un « for each » algorithmique Problème persistant: – Il peut y avoir ambiguïté du fait de l’absence de nouveau mot clé Stéphane GALLAND UTSEUS 2008 7 Foreach et itérateurs Language Java ● Avant : List stringList = new ArrayList(); … for (Iterator it = new stringList.iterator(); it.hasNext; ) { … String maString = (String) it.next(); … } ● Après : List stringList = new ArrayList(); … for (String maString : stringList) { … } Stéphane GALLAND UTSEUS 2008 8 Type énuméré Language Java ● Problème initial: – – – ● Il n’y avait pas de type énuméré prévu dans Java Il fallait jusqu’alors se débrouiller avec les classes. Cette bidouille ne permettait pas d’éviter certaines erreurs (valeurs non conformes) Solution: – – – Ajout d’un type enum dans java (remplace le mot clé class dans ce cas) Pour chaque énumération une classe supplémentaire est générée qui implémente les interfaces Comparable et Serializable Cette classe contient des variables statiques correspondant aux différentes valeurs ainsi que des méthodes automatiquement rédéfinies (values( ), toString( ), compareTo( ),…) Stéphane GALLAND UTSEUS 2008 9 Type énuméré Language Java ● Avant : public class Numbers { public static final int ZERO = 0; public static final int UN = 1; public static final int DEUX = 2; … } … int num = Numbers.ZERO; ● Après : public enum Numbers {ZERO, UN, DEUX, …}; Numbers num = Numbers.ZERO; Stéphane GALLAND UTSEUS 2008 10 Language Java ● Problème initial: – – ● Ellipse – nombre variable de paramètres On a parfois besoin d’utiliser un nombre variable de paramètres. La solution couramment utilisée jusqu’à présent était l’utilisation d’un tableau de paramètres. Solution : – – Rendre possible l’utilisation de paramètres dont le nombre n’est pas connu à l’avance Ceci est possible grâce à l’arrivée du for each Stéphane GALLAND UTSEUS 2008 11 Language Java ● Ellipse – nombre variable de paramètres Avant : int sum(Integer[] numbers) { int mysum = 0; for(int i: numbers) mysum += i; return mysum; } … sum(new Integer[] {12,13,20}); ● Après : int sum(Integer... numbers) { int mysum = 0; for(int i: numbers) mysum += i; return mysum; } … sum(12,13,20); Stéphane GALLAND UTSEUS 2008 12 Type générique Language Java ● ● Problème initial : – Le langage Java ne dispose pas de type générique depuis son introduction. (polymorphisme paramétrique de type) – Ceci était un inconvénient par rapport au C++ qui donne la possibilité d’utiliser les templates Solution : – Un nouveau type fait son apparition : les generics Stéphane GALLAND UTSEUS 2008 13 Type générique Language Java ● Avant : List listeEntier = new ArrayList(); listeEntier.add(new Integer(1)); … Integer monEntier = (Integer) ListeEntier.get(0); //Ceci est licite pour le compilateur listeEntier.add("toto"); //mais peut poser des problèmes lors de l’execution ● Après : List listeEntier<Integer> = new ArrayList<Integer>(); listeEntier.add(new Integer(1)); … Integer monEntier = ListeEntier.get(0); //Ceci génère une erreur de compilation listeEntier.add("toto"); Stéphane GALLAND UTSEUS 2008 14 Language Java Avantages des types génériques ● Suppression du contrôle de type à l’exécution ● Modification très faible du code initial ● Meilleur visibilité et robustesse des programmes ● Factorisation de code pour un ensemble de types génériques Stéphane GALLAND UTSEUS 2008 15 Exemple de type générique – Liste d'objets Language Java ● ● La syntaxe est très proche du C++, mais on ne peut pas pour autant dire que les generics sont des templates et inversement. Il existe des différences: – un generics est compilé une fois pour toute cette instance est alors partagée pour toutes les utilisations du generics. – Il n’y a donc pas de multiple copie du code en fonction des différentes invocations public interface List<T> { void add (T t); Iterator<T> iterator(); } Stéphane GALLAND UTSEUS 2008 16 Language Java ● ● Exemple de type générique – Liste d'objets Comme avec les templates en C++, deux generics identiques spécialisés par deux classes héritant l’une de l’autre n’ont pas de lien d’héritage particulier. Par contre on peut spécifier et restreindre la généricité en utilisant les wildcards class Mammiferes<T extends Mammifere> { private Vector<T> items = new Vector<T>(); void add(T item) { items.add(item); } T get(int index) { return items.get(index); } } Stéphane GALLAND UTSEUS 2008 17 Référence Language Java ● Ce support de cours est basé sur le support de cours de LO43 (automne 2005) écrit par Franck Gechter Stéphane GALLAND UTSEUS 2008 18