next up previous
Next: Exercice 1 : pour Up: No Title Previous: No Title

Subsections

Présentation avancée de Java

La deuxième partie de cette présentation de Java porte sur les notions d'interfaces et de paquetages, pour ensuite décrire les applets, le modèle graphique et la gestion des événements. Elle repose sur le jdk 1.1.

Interfaces

Une interface définit un type en déclarant un ensemble d'entêtes de méthodes (comme les méthodes abstraites) et de constantes. On peut alors déclarer des variables de ce type.

Une classe peut indiquer dans sa définition qu'elle implante une ou plusieurs interfaces. Elle doit alors à fournir une définition pour les méthodes de l'interface. L'intérêt des interfaces est de pouvoir rendre des classes, compatibles au niveau des types, sans forcément effectuer une liaison d'héritage. D'autre part le fait de pouvoir implanter plusieurs interfaces permet de simuler l'héritage multiple. Néanmoins les interfaces ne peuvent pas implanter de méthodes, ce qui rendra plus difficile la réutilisation de code que peut offrir un véritable héritage multiple.

Paquetages

Les paquetages (package) regroupent des classes et des interfaces. Ce sont les modules de Java. Ils permettent d'avoir accès à un nom sans ambiguité. Par exemple la classe java.lang.Applet indique la classe applet du sous-paquetage lang du paquetage java. On indique son appartenance à un paquetage par la déclaration package TD5.exemples;. Pour éviter d'avoir à écrire le nom complet d'une classe, il est possible d'importer un paquetage (import TD5.* indique d'importer tous les paquetages de racine TD5). Enfin sans déclaration spéciale une classe est disponible au niveau du paquetage. Si on désire la rendre publique, il faut l'indiquer explicitement.

Classes internes

Une évolution, à partir de la version 1.1 du langage Java, est la possibilité de déclarer des classes internes (locales). Une classe interne peut être définie comme membre d'une classe (comme les champs de données ou de méthodes) ou bien à l'intérieur d'un bloc d'instructions (à l'intérieur d'une méthode).

Si la classe interne est déclarée comme champs de sa classe englobante, elle pourra être accessible par la notation qualifiée "point" indiquant le chemin d'accès. Par contre si elle est déclarée à l'intérieur d'un bloc d'instruction, elle ne sera visible qu'à l'intérieur de ce bloc. Néanmoins une valeur de cette classe interne pourra être retourné comme résultat, et surtout utilisé par la suite, comme valeur d'un certain type, si cette classe implantait l'interface correspondante.

Comme le nom de la classe n'a que peu d'importance dans ce dernier cas, il est autorisé de déclarer localement des classes anonymes.

L'intérêt des classes internes provient principalement du nouveau mécanisme de gestion des évènements des applets (que nous verrons par la suite).

Applet, interface graphique et événements

On présente les principales classes pour définir des applets (classe Applet), dessiner (classe Graphics) et pour interagir (classe Event). Une applet est une petite application graphique. Le paquetage principale pour gérer le graphisme et l'interaction s'appelle AWT (Abstract Window Toolkit). Ce paquetage a été fortement modifié entre la version 1.0 et la version 1.1, principalement pour la gestion des évènements.

Applet (class Applet)

cycle de vie d'une applet : init()start()stop()destroy() où :

Une applet se lance soit avec appletviewer, soit avec netscape, suivi d'un fichier HTML indiquant le fichier .class de la manière suivante :

Fichier : passwdTest.html
<html>
 <head> Exercices en Java
 </head>
<body>
 <H1> Test </H1>
  <P>
  <applet code="Test1" height=400 width=400>
  <P><EM> Not a java-powered browser! </EM>
  </applet>
</body>
</html>

Ce fichier correspond à l'exemple Test1 développé par la suite.

Feuille de dessin (class Graphics)

La feuille de dessin d'une applet est un objet de la classe Graphics. Elle est représentée par une matrice de points (class Points) dont les coordonnées sont (0,0) en haut à gauche et vont jusqu'à (size.width()-1,size().height-1) en bas à droite. La classe Applet utilise principalement la méthode paint(Graphics g) correspondant à son affichage graphique. L'exemple suivant :

import java.awt.*;
import java.applet.*;

public class Test1 extends Applet {
  public void paint(Graphics g) {
    g.drawString("Salut tout le monde",100,10);
  }
}

est une applet affichant un texte aux coordonnées (100,10).

Les méthodes principales de dessins sont : drawLine, drawRect, fillRect, drawOval, fillOval, setColor, drawString, setFont ...

Evènements (class Event)

On s'intéresse aux interactions d'une applet. Elles sont gérées comme des événements (dérivés de EventObject) produits par un composant graphique (dérivé de Component) de l'applet, que l'on appellera la source, et traités par un délégué qui a indiqué qu'il s'intéressait à cet évènement en s'enregistrant prealablment auprès dè la source. On retrouve ici le modèle de gestion des évènements du système NextStep.

La source doit donc définir des méthodes d'enregistrement des délégués qui doivent respecter la forme suivante :

public <TypeEvt>Listener set<TypeEvt>Listener(<TypeEvt>Listener monDelegue)
public <TypeEvt>Listener add<TypeEvt>Listener(<TypeEvt>Listener monDelegue)
public <TypeEvt>Listener remove<TypeEvt>Listener(<TypeEvt>Listener monDelegue)

comme par exemple la méthode prédéfinie addMouseListener utilisée de la manière suivante : addMouseListener(MouseListener monDelegue). La première forme indique une diffusion simple (vers un seul délégué), et la deuxième permet une diffusion multiple.

L'exemple suivant montre une applet qui affiche une chaîne à l'endroit cliqué par la souris :

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class Test3 extends Applet {

  public Test3() {
    MouseListener clic = new MouseAdapter () {
      public void mousePressed (MouseEvent e)
      {
        int x = e.getX();
        int y = e.getY();
        System.out.println("x = " + x + "  y = "+y);
        getGraphics().drawString("salut tout le monde",x,y);
      }
     };
    addMouseListener(clic);
  }

  public void init () {
    this.setBackground(Color.white);
  }
}

<TypeEvt> correspond à un type d'évènement, par exemple MouseListener pour les évènements souris ou plus généralement ActionListener pour les évènements de type action. Le délégué clic est une instance de la classe anonyme étendant la classe MouseAdapter. Il traite les les évènements souris MouseListener, respectant l'interface MouseListener et redéfinit la méthode mousePressed.

Il n'est pas nécessaire de définir une classe anonyme. Par exemple le texte suivant :

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class Test3 extends Applet {

  class AdaptateurSouris extends MouseAdapter implements MouseListener {
      public void mousePressed (MouseEvent e)
      {
        int x = e.getX();
        int y = e.getY();
        System.out.println("x = " + x + "  y = "+y);
        getGraphics().drawString("salut tout le monde",x,y);
      }
     }


  public Test3() {
    MouseListener clic = new AdaptateurSouris()

    addMouseListener(clic);
  }

  public void init () {
    this.setBackground(Color.white);
  }
}

Enfin il est aussi possible d'implanter directement une interface Listener dans l'applet que l'on construit. Dans ce dernier cas, il est donc nécessaire d'écrire toutes les méthodes de l'interface implantée.

Il est fréquent d'utiliser une classe intermédiaire entre la source d'un évènement et le délegué qui traitera l'évènement. On appelle cet intermédiaire un adaptateur. Cela permet de rendre plus indépendant l'interface utilisateur du code de traitement. De plus l'adaptateur permet des opérations sur les évènements, de gérer une queue d'évènements et d'utiliser un seul délégué pour plusieurs sources d'évènements.

la diffusion d'un évènement à un ou des délégués, ou adaptateurs, dépend uniquement des objets, respectant l'interface Listener et abonnés à cette source. L'ordre de diffusion n'est pas garanti. Pour le garantir il est nécessaire de coder une chaine de délégués partant d'un adaptateur unique.

Autres classes pour l'interaction

Le paquetage java.awt définit des composants d'interaction fort pratiques. On peut citer les labels, les boutons, les boites à choix multiple ou exclusif, les menus déroulants, les listes de choix, les champs de texte en entrée, les ascenseurs, les fonds, ...

L'exemple suivant reprend l'exemple du login et des mots de passe du TD4 :

Fichier : passwdTest.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class passwdTest extends Applet { 

String monlogin  ="tartempi";
String monpasswd ="itaparit";
TextField login;
TextField passwd;
boolean OK = false;

ActionListener RC = new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    if ((e.getSource() == login) || (e.getSource() == passwd))
    { if ((login.getText().equals(monlogin)) &&
         (passwd.getText().equals(monpasswd)))
      {OK=true; good();}
      else {nogood();}
    }
  }
};

  public void init() {
    login = new TextField(8);
    passwd = new TextField(8);
    add(new Label("Login : "));
    add(login);
    add(new Label("Password : "));
    passwd.setEchoChar('*');
    add(passwd);
    login.addActionListener(RC);
    passwd.addActionListener(RC);  
  }
 
  public void good() {
    resize(120,180);
    this.getGraphics().drawString("c'est parti...",10,150);
  }
 
  public void nogood() {
    this.getGraphics().drawString("identification incorrecte",10,100);
  }
}

Les composants login et passwd engendrent des évènements (comme par exemple un retour chariot) vers le délégué RC qui s'est enregistré auprès de ces deux composants par les messages addActionListener. La méthode actionPerformed traitera l'évènement action e en vérifiant bien que la source de l'évènement est un de ces deux composants.

On ajoute des composants par la méthode add envoyée à un conteneur, par exemple celui de la page graphique d'une applet, comme dans les exemples sur la saisie d'un mot de passe et la lecture d'une expression. Des protocoles de mise en page permettent de placer de manière précise les composants dans un conteneur.

Conteneurs et mise en page

Un conteneur (classe Container) est un espace graphique permettant de recevoir plusieurs composants graphiques. Cette classe se découpe en deux sous-classes : les panneaux (Panel) dont la classe applet hérite et les fenêtres (Window). L'exemple du mot de passe montrait différents composants graphiques dans l'espace graphique de l'applet.

La mise en page des conteneurs peut suivre différentes disciplines :


next up previous
Next: Exercice 1 : pour Up: No Title Previous: No Title
Emmanuel CHAILLOUX
12/7/1997