|
||
| Généralités sur JAVA | Spécification du langage JAVA | Complément du langage JAVA |
L'utilisation des réels avec le langage JAVA nécessite de prendre quelques précautions. Cette section précise quelques points concernant les réels et leur utilisation. De plus, le langage JAVA possède quelques différences par rapport à la norme IEEE 754, qui seront expliquées ici. L'utilisation des réels ne produit aucune exception en langage JAVA.
A.1. Valeurs Spéciales
Il existe en JAVA un zéro positif, et un zéro négatif. Le zéro négatif peut se distinguer du positif dans les cas suivants :
le dépassement de la borne minimale, lors d'une multiplication, ou d'une division de termes de signes différents,
l'addition du zéro négatif à lui-même, ou la soustraction du zéro positif au zéro négatif,
la racine carré du zéro négatif
Transformer un zéro négatif en une chaîne de caractères donnera un '-'. Mis à part ces cas, les deux zéros sont indifférenciables.
Certains calculs qui produiraient une valeur au delà des bornes des réels, donneraient comme résultat un nombre signé fixe, nommé Inf (infini). Ce nombre ne peut être défini, ni utilisé comme les autres. Deux nombres Inf ne peuvent pas être distingués. Ainsi, on a :
(1./0.)+(1./0.) == (1./0.)
La division d'un nombre fini par Inf donne zéro comme résultat.
Certains autres calculs qui ne produiraient pas de valeur numérique significative donneraient comme résultat une valeur spéciale appelée Not A Number ou NaN. Toute opération ayant un NaN comme opérande produirait un NaN comme résultat. NaN n'est ni signé, ni ordonné. La division d'un infini par un autre donne un NaN comme résultat.
A.2. Ordre des Réels
Tous les opérateurs relationnels peuvent être appliqués aux réels. Toutes les valeurs réelles, à l'exception de NaN, sont ordonnées : -inf< Valeurs Finies < inf. Les relations d'ordre sont transitives, et l'égalité et l'inégalité sont réflectifs.
La valeur NaN n'est pas ordonnée. Cela signifie donc que le résultat de toute opération de relation entre un NaN et une autre valeur donnera false comme résultat. Seule la relation "Nan != n'importe quoi" est vraie.
A.3. Les Différences avec la norme IEEE-754
Voici un rapide aperçu des différences qui existent par rapport à la norme IEEE-754 :
Le langage JAVA ne lève aucune exception dans les opérations concernant les réels: il ne signale pas une opération invalide, la division par zéro, les dépassements de bornes.
Les arrondis : lorsqu'un résultat n'est pas exact, le langage JAVA l'arrondit à la valeur représentable la plus proche. C'est le mode par défaut de l'IEEE. Cependant, lors de la conversion d'un réel vers un entier, JAVA arrondit en se rapprochant de la valeur zéro. -6.3 deviendra -6, et 6.3 deviendra 6. Il n'existe pas de possibilités de définir la manière dont JAVA arrondit les valeurs : à l'entier supérieur, inférieur, ou vers zéro.
La langage JAVA ne supporte aucune extension des formats qui existent. La seule exception est l'extension des réels à simple précision (float) vers les réels à double précision (double).
Appendice B : Aperçu sur les API de Java
B.1 Présentation globale
Le sigle API est l'abréviation de Application Programming Interface. Il désigne l'ensemble des classes existantes dans le Java Developper's Kit (JDK) qui permettent de développer des interfaces entre ordinateur et utilisateur.
Les API de Java sont regroupées dans différents packages par type d'utilisation. Dans la documentation fournie par Sun, les packages sont découpés en deux catégories : les Applet API packages, et les autres packages. Seules les API de la première catégorie seront abordées dans cette section, les autres packages étant peu utiles dans une première approche du langage.
Il existe huit packages appartenant à la catégorie Applet API packages :
java.applet : les éléments de ce package concernent la gestion des Applets, et la structure utilisée pour cela.
java.awt : ce package contient toutes les structures graphiques de base : les fenêtres, les images, les boutons, les ascenceurs, les événements, etc...Le sigle AWT signifie Abstract Window Toolkit.
java.awt.image : les éléments de ce package concernent plus précisement la gestion de toutes les images graphiques.
java.awt.peer : tous les éléments de ce package sont des interfaces. Etant donné que nous ne l'avons pas utilisé, nous n'avons pas eu l'occasion de l'étudier.
java.io: ce package contient les éléments nécessaires pour pratiquer des opérations en entrée/sortie. Les classes contenues dans ce package permettent de créer des flux d'entrée/sortie, ou de manipuler des fichiers.
java.lang : tous les éléments de ce package sont les " briques de base " du langage. Il contient notamment toutes les classes équivalentes aux types existant dans Java : Boolean, Integer,... Il contient aussi les éléments de gestion de processus.
java.net : ce package contient tous les éléments relatifs au réseau Internet : Socket, URL, etc...
java.util : les éléments de ce package ne peuvent pas être regroupés dans une catégorie particulière : on y trouve des classes de gestion de collection d'éléments, avec des méthodes de tris.
Tous les éléments qui sont expliqués dans cette section se trouvent dans ces packages. Les classes qui sont expliquées font partie des éléments incontournables de la programmation dans le langage Java. Elles ont d'ailleurs été utilisées à un moment ou à un autre dans l'ensemble des programmes qui ont été développés.
Dans toutes les explications qui suivent nous avons pris soin de donner un exemple concret provenant de l'un des programmes développés au cours du projet. Chacune des sections débute par un intitulé " Documentation complète ", indiquant l'adresse exacte où se trouve la documentation de la classe.
B.2 La classe java.applet.Applet
Documentation complète : http://java.sun.com/JDK-1.0/api/java.applet.Applet.html
B.2.1 Description générale
La classe Applet est la superclasse de tous les programmes Java intégrés au sein d'une page HTML. Il s'agit de la classe de base en programmation Java. Une classe qui n'est pas sous-classe de la classe Applet ne pourra pas être spécifiée dans une page HTML. Par extension, le mot Applet signifie d'ailleurs aussi Programme Java.
La classe Applet est une sous-classe de la classe Panel, et possède à ce titre les même propriétés qu'elle. Ainsi, une instance de la classe Applet pourra contenir un ensemble d'éléments graphiques de type Component. De même, la classe Applet possède un contexte graphique qui permet les dessins et les affichages d'objets graphiques en tous genres. C'est le cas des trois programmes qui ont été développés.
L'Applet Glyphe démontre bien l'imbrication d'éléments graphiques dans un Applet. Les deux autres programmes sont plus orientés vers l'affichage graphique et la programmation parallèle.
B.2.2 Les principales méthodes utilisées
Lorsqu' une sous-classe d'Applet spécifiée dans une page HTML est chargée en mémoire, les premières méthodes qui sont exécutées sont dans l'ordre, init et start.
La méthode start est appelée automatiquement lors du démarrage de l'Applet. Ce démarrage a lieu lors du premier chargement, lors d'une réouverture de la page HTML, ou lorsque la fenêtre du browser est modifiée (changement de taille).
La méthode init n'est appelée que lors du premier chargement de l'Applet. Elle permet d'initialiser l'ensemble des variables de l'Applet. Dans les sous-classes de Applet, la méthode init est très souvent surchargée afin de pouvoir initialiser le programme. C'est le cas des trois Applets qui ont été développés. Une explication complète de la méthode init est donnée dans le rapport sur la maquette AREMM. (section 2.1.2). Dans ce programme, la méthode init permet de charger des données à partir d'un fichier et de garder ces données en mémoire, sans avoir à les recharger par la suite. Elle permet aussi de définir la structure de l'Applet Glyphe et de placer les différents éléments qui le compose.
Comme toutes les sous-classes de Component, la classe Applet utilise la méthode paint afin de pouvoir afficher sur l'écran. Cette méthode est expliquée dans la classe Component. Les événements qui se produisent dans l'Applet sont aussi gérés par la classe Component.
La méthode stop est aussi très souvent utilisée. Elle est automatiquement appelée lorsque l'exécution du programme doit être stoppée. C'est le cas lorsque la fenêtre du browser est iconisée, par exemple. Une très bonne illustration des méthodes start et stop est donnée dans le programme de présentation du projet. La méthode start permet de démarrer l'exécution d'une tâche de fond parallèle (en plus de la tâche gérant l'exécution de l'Applet). La méthode stop, elle, permet au contraire de la suspendre. Ces deux méthodes fonctionnent souvent en dépendance l'une de l'autre.
Employée très souvent, la méthode resize permet de redéfinir la taille de l'Applet dans la page HTML. Un exemple de cela est donné dans l'Applet MagicMouse. L'image qui est affichée en fond de l'Applet est un paramètre. La taille de l'Applet dépend donc de la taille de l'image. Lorsque l'image est chargée, l'Applet peut redéfinir sa propre taille en fonction de la taille de l'image.
La classe Applet possède quelques autres méthodes utilitaires qui permettent de la rendre plus dynamique :
getParameter : il est possible de faire passer dans la page HTML des paramètres à l'Applet. Cette méthode permet de récupérer un des paramètres en fonction de son nom. Un exemple d'utilisation de cette méthode est donné dans l'Applet MagicMouse.
getDocumentBase : cette méthode permet de récuperer l'URL du serveur où se trouve la page HTML contenant l'Applet. Cette méthode a été utilisée dans MagicMouse lors du chargement de l'image de fond de l'Applet.
getCodeBase : cette méthode permet de récuperer l'URL du serveur où se trouve l'Applet qui est exécuté. Cette méthode est similaire à la précédente.
getImage : cette méthode permet de charger une image pour pouvoir ensuite la manipuler dans l'Applet. Cette méthode a été utilisée lors du chargement de l'image dans l'Applet MagicMouse. Un problème d'utilisation de cette méthode vient du fait que l'image n'est réellement chargée que lorsque l'image doit être affichée. Cela cause des ralentissements lors du premier affichage. C'est ce qui se produit lors du premier affichage des images d'animation de la tasse dans la classe Present3D. L'animation semble saccadée, puis s'accélère ensuite, une fois que toutes les images ont été affichées une première fois.
La gestion des événements, autre élément essentiel à l'Applet, est décrite dans la classe qui gère réellement cela : la classe Component.
B.3 La classe java.awt.Component
Documentation complète : http://java.sun.com/JDK-1.0/api/java.awt.Component.html
B.3.1 Description générale
Cette classe est une sous-classe directe de Object. Il s'agit d'une classe abstraite qui est à la base de tous les autres composants graphiques d'un programme Java. Les classes Panel, Applet, Button, Canvas, etc... sont toutes des sous-classes de la classe Component.
Toutes les classes issues de la classe Component seront des objets graphiques à événements. Cela signifie que les instances des sous-classes de Component pourront gérer les événements dûs à la souris ou au clavier et possèderont un contexte graphique permettant d'afficher des informations à l'écran. Tous les paramètres concernant ces informations - taille, forme, couleur, police de caractères - pourront être modifiés et contrôlés.
B.3.2 Les principales méthodes utilisées
Paint, repaint et update :
La méthode qui est la plus utilisée dans la classe Component et ses sous-classes, est la méthode paint. Celle-ci est automatiquement appelée par le runtime Java lorsque l'objet graphique, instance d'une sous-classe de Component, doit être affiché. La méthode paint possède un paramètre, de type Graphics. Ce paramètre correspond au contexte graphique dans lequel tous les affichages doivent être faits (voir explication de la classe Graphics pour plus de détails à ce sujet).
La méthode paint fonctionne souvent en parallèle avec les méthodes repaint et update. Un appel à la méthode repaint correspond à appeler la méthode update, sans avoir à préciser le contexte graphique (c'est la méthode repaint qui s'en charge). La méthode update appelle à son tour la méthode paint, en ayant auparavant effectué quelques mises à jour dans le contexte graphique. Par défaut, la méthode update dessine un carré de la taille du Component, à l'emplacement (0,0). Cela a pour effet d'effacer tout ce qui se trouvait dans le contexte graphique du Component. Pour éviter cela et des problèmes de clignotement à l'écran, il peut être utile de surcharger la méthode update et de ne faire effacer le fond d'écran que lorsque cela est nécessaire et/ou aux endroits où cela est nécessaire.
Un exemple de surcharge de la méthode update est donné dans l'Applet MagicMouse. Dans ce cas, la méthode update ne raffraîchit l'écran que si cela est nécessaire. Un autre exemple et des explications plus complètes sont données à l'adresse : http://java.sun.com/./people/avh/flash.html.
Gestion des évènements de la souris :
Les évènements de la souris sont gérés par un ensemble de méthodes, automatiquement appelées lorsque l'évènement correspondant se produit. Voici la liste des évènements, et la méthode qui est appelée lorsqu'il se produit :
Evènement Méthode appelée
Le curseur de la souris rentre dans le mouseEnter
Component.
Le curseur de la souris sort du mouseExit
Component.
Le curseur de la souris bouge dans le mouseMove
Component (sans qu'aucun bouton ne soit
appuyé).
Le curseur de la souris bouge dans le mouseDrag
Component et un bouton est appuyé.
Un bouton de la souris est appuyé. mouseDown
Un bouton qui était appuyé est relaché. mouseUp
Pour ce qui est des méthodes mouseDown, et mouseUp, elles ne sont appelées qu'une fois. La méthode mouseDown n'est appelée qu'une fois lorsque le bouton a été appuyé et n'est plus rappelée tant que la méthode mouseUp n'a pas été appelée.
La surcharge d'une ou de plusieurs de ces méthodes permet de gérer les événements correspondants. Toutes ces méthodes ont été surchargées dans l'Applet MagicMouse. Elles ont permis de gérer le déplacement de la souris (et le dessin des étoiles) et la gestion de la sélection dans le menu contextuel.
Gestion des événements du clavier :
Les événements dûs au clavier sont gérés par six fonctions : gotFocus, LostFocus, requestFocus, nextFocus, keyDown et keyUp.
Les deux premières méthodes permettent au Component de préciser s'il a reçu (gotFocus) ou perdu (lostFocus) le focus. Cela signifie savoir s'il a ou non la main pour traiter les événements dûs au clavier. La méthode requestFocus permet au Component de demander la main pour traiter les événements du clavier. Si cette méthode réussit à prendre la main, elle fera un appel à la méthode gotFocus. La méthode nextFocus passe la main au Component suivant (s'il existe), dans la liste des objets Components actifs.
Les deux dernières méthodes citées, keyDown, et keyUp, sont automatiquement appelées lorsque le Component correspondant a pris le focus. Elles permettent de gérer respectivement l'appui sur une touche du clavier et la relâche de cette touche. La méthode keyDown a été utilisée dans la classe Graphe de l'application AREMM.
Gestion des paramètres graphiques :
Les paramètres graphiques sont tous gérés par la classe Graphics. Tout objet instance d'une sous-classe de Component possède donc un pointeur sur un objet de la classe Graphics (c'est ce qu'on appelle un contexte graphique).
Il est possible cependant de gérer la taille du Component, sous certaines réserves. En principe, la méthode resize se trouve dans la classe Component et permet, tout comme pour la classe Applet, de redimensionner le Component. Cependant, dans certains cas, le redimensionnement ne fonctionne pas correctement : notamment lorsque le Component se trouve dans un Container, avec d'autres Components (voir classe Container).
Quelques autres méthodes pratiques :
Les méthodes inside et locate permettent de gérer la position du curseur de la souris lorsque plusieurs Component se trouvent dans un même Component. La méthode inside permet de renvoyer un booléen indiquant si le curseur de la souris se trouve ou non à l'intérieur du Component.
La méthode locate permet de savoir quel est le Component qui se trouve sous le curseur de la souris.
B.4 La classe java.awt.Container
Documentation complète : http://java.sun.com/JDK-1.0/api/java.awt.Container.html
B.4.1 Description générale
Comme la classe Component, la classe Container est une classe générique abstraite. Il s'agit d'une sous-classe de Component. Il s'agit d'un Component qui peut contenir d'autres Components. Tous les objets qui devront contenir plusieurs Components devront être instances d'une sous-classe de la classe Container. C'est le cas de la classe Panel. Ainsi, un Container pourra lui-même contenir un autre Container.
Un objet instance de la classe Container possède cependant une certaine structure, qui est gérée par un objet implementant l'interface LayoutManager. L'interface LayoutManager contient les méthodes que doivent implémenter les classes gérant la structure des Containers : il s'agit des classes suivantes :
BorderLayout : c'est la structure la plus simple. Les éléments qui sont contenus dans ce type de structure peuvent être placés suivant les mots clés "North", "South", "East", "West" et "Center". Les Components qui sont placés suivant les quatre premiers termes auront leur taille préférentielle; les autres Components, placés avec le terme "Center" occuperont par défaut toute la place laissée libre. C'est la structure utilisée par l'Applet Glyphe.
CardLayout : cette structure est faite pour les Containers qui doivent contenir plusieurs éléments dont un seul est visible à la fois. Il est possible d'alterner les différents éléments.
FlowLayout : cette structure est utilisée pour organiser les boutons dans un Container. Les boutons sont organisés de la gauche vers la droite jusqu'à ce qu'il ne rentrent plus sur une même ligne. Chacune des lignes de boutons sera centrée. Tous les éléments auront alors la même taille.
GridBagLayout : cette structure permet d'organiser les éléments horizontalement et verticalement, sans pour autant que ces éléments aient la même taille. Il semble très délicat d'utiliser ce type de structure d'autant plus que l'exemple donné dans la documentation ne donne pas le résultat présenté.
L'utilisation de cette structure est associée à l'utilisation d'une instance de la classe GridBagConstraints, fixant les différents paramètres pour chaque Component inclus dans le Container. Ces paramètres sont définis par les variables d'instance de l'objet GridBagConstraints. Certains paramètres ont des effets qu'il est difficile de définir.
Pour plus de documentation, voir l'exemple donné à l'adresse: http://java.sun.com/JDK-1.0/api/java.awt.GridBagLayout.html
GridLayout : ce gestionnaire de structure est utilisé pour diviser l'espace d'un Container en grille. C'est la structure qui est utilisée dans la classe ListeGraphe créée dans la maquette AREMM. Elle permet de découper le Container en m lignes et n colonnes de taille égale. Cependant, il existe quelques problèmes quant à la taille du découpage : nous avons constaté, par exemple, que l'objet ListeGraphe devait avoir une taille en largeur égale à la taille en hauteur. Si cela n'est pas respecté, le dernier élément de chaque ligne est tronqué.
B.4.2 Les principales méthodes utilisées
Les deux méthodes qui servent à gérer l'ajout et le retrait de Components dans un Container sont respectivement add et remove. La méthode add possède différentes formes :
- add (Component) : l'objet Component qui sera ajouté sera placé par le gestionnaire de structure choisi. Si aucun gestionnaire spécifique n'a été choisi, l'élément sera placé au centre du Container, à la suite des éléments déjà présents dans le Container.
- add (Component, int) : l'objet Component va être ajouté à la position désignée par le paramètre int.
- add (Component, String) : l'objet Component sera placé à l'endroit désigné par la variable String : "North", "East", "West", "South" ou "Center".
La méthode remove permet de retirer du Container l'élément spécifié. L'utilisation des méthodes add et remove trouve une bonne illustration dans l'application Glyphe : voir notamment les méthodes init et Modifier de la classe Glyphe. La méthode removeAll permet de retirer du Container l'ensemble des Components qui s'y trouvent.
La définition de la structure du Container est régie par la méthode setLayout. Celle-ci permet de spécifier au Container quel type de layout celui-ci possèdera. La méthode getLayout permet de savoir quel type de layout est défini pour le Container. La méthode setLayout a été utilisée dans la classe Glyphe.
B.5 La classe java.awt.Graphics
Documentation complète : http://java.sun.com/JDK-1.0/api/java.awt.Graphics.html
B.5.1 Description générale
Cette classe gère tous les affichages graphiques. Une instance de cette classe représente un contexte graphique pour un objet graphique auquel elle est associée. Le contexte graphique associé à un Applet est l'écran.
De même, il est possible de créer des contextes graphiques associés à une image. On peut alors effectuer toutes les actions graphiques sur cette image (tracé de traits, rectangles, ovales, images au format GIF...).
Cette classe est souvent liée aux méthodes paint et update des sous-classes de Component. Les objets de type Graphics sont utilisés dans ces méthodes pour effectuer des mises à jour sur l'écran. Une utilisation spéciale de Graphics et de la classe Image a notamment été effectuée dans l'Applet Present3D. Elle a permis l'utilisation d'une technique appelée Double-Buffering, permettant d'optimiser les affichages graphiques à l'écran (voir section correpondante dans la maquette).
La classe Graphics permet de gérer un ensemble de paramètres concernant l'affichage : la couleur de tracé, le type de police de caractère utilisée pour le texte, le mode d'affichage des couleurs (paramètre non utilisé dans les Applets réalisés). Le type de police de caractères inclue la police, sa taille, son orientation et son style (gras, italique, souligné,...).
B.5.2 Les principales méthodes utilisées
Gestion des paramètres graphiques :
Pour fixer les différents paramètres graphiques, il existe quatre méthodes :
setColor : permet de fixer la couleur courante de tracé pour tout type d'affichage (affichage de traits, ou de textes.)
setFont : permet de fixer la police de caractère utilisée pour les affichages de textes (voir section suivante sur la couleur et les fontes).
setPaintMode : permet de fixer le mode d'affichage à "remplacement de la couleur précédente". Ce mode permet à tout point affiché de remplacer le point précédent qui était affiché.
setXORMode : permet de fixer le mode d'affichage à "OU exclusif" avec la couleur spécifiée. Ainsi, tout point à afficher sur un point de la couleur spécifiée ne sera pas affiché.
Il existe des méthodes similaires pour connaitre les paramètres utilisés :
getColor : permet de connaître la couleur courante d'affichage.
getFont : permet d'avoir une référence sur l'objet Font contenant toutes les caractéristiques de la police de caractères utilisée.
Méthodes d'affichage :
Les méthodes pour afficher dans un contexte graphique sont très nombreuses. Il existe des méthodes de dessins et des méthodes d'affichage d'images, de textes ou de chiffres.
Les différentes méthodes de dessin permettent d'afficher les formes géométriques de base : ligne, rectangle, ovale, arc de cercle, polygone, rectangle aux bords arrondis. Ces formes géométriques peuvent être tracées à vide ou en forme pleine. Le tableau ci-après récapitule l'ensemble des formes géométriques possibles et les méthodes correspondantes pour les tracer à plein ou à vide :
Forme géométrique Tracé du contour Tracé plein
Ligne drawLine -
Rectangle drawRect fillRect
Ovale et cercle drawOval fillOval
Polygone drawPolygon fillPolygon
Rectangle à coin drawRoundRect fillRoundRect
arrondi
Arc de cercle drawArc fillArc
Rectangle avec effet draw3DRect fill3DRect
3D
Les méthodes d'affichage d'image, texte, chiffre... sont les suivantes :
drawImage : permet d'afficher un objet Image à la position spécifiée. Il existe différentes versions de cette méthode que nous n'avons pas pu tester.
drawChar : permet d'afficher un ensemble de caractères à la position spécifiée, avec la couleur courante et la police courante.
drawString : permet de d'afficher une chaine de caractères, avec la couleur et la police courantes.
Une autre méthode assez utile existe : il s'agit de clearRect qui permet d'effacer une portion du contexte graphique. Cette portion a la forme d'un rectangle. Cette méthode peut être utile notamment pour raffraîchir seulement certaines zones d'écran.
B.5.3 Quelques précisions sur les couleurs et les polices de caractères
Les couleurs et les polices de caractères sont gérées respectivement par les classes java.awt.Color et java.awt.Font.
La classe Color possède un ensemble de variables statiques définissant quelques couleurs usuelles. Le tableau ci-dessous donne la correpondance entre ces noms de variables, et la couleur.
Couleur Nom de variable
Noir black
Bleu blue
Bleu ciel cyan
Gris foncé darkGray
Gris gray
Vert green
Gris Clair lightGray
Violet magenta
Orange orange
Rose pink
Rouge red
Blanc white
Jaune yellow
Il est possible de définir des couleurs différentes de ces couleurs pré-définies. La couleur affichée dépendra alors du type de carte graphique possédée. En général, Java affiche la couleur la plus proche. Pour définir une nouvelle couleur, il suffit d'utiliser l'un des constructeurs de la classe Color.
Les deux qui ont été utilisés dans les Applets que nous avons développés sont :
Color(int,int,int) : permet de définir une couleur suivant les valeurs RGB (Red,Green,Blue), comprises entre 0 et 255. La couleur (0,0,0) est le noir, alors que la couleur (255,255,255) est le blanc. Ce mode de création de couleur a été beaucoup utilisé dans l'Applet Present3D.
Color(int) : permet de définir une couleur suivant les valeurs RGB combinées dans une seule variable. Les bits 0 à 7 désignent la composante Bleue, les bits de 8 à 15 la composante Verte et les bits de 16 à 23 la composante Rouge. Ce constructeur a été utilisé une fois dans l'Applet Present3D, dans la méthode run.
L'utilisation des polices de caractères est gérée avec les classes Font et FontMetrics. La classe Font permet de créer une police de caractères et de l'attribuer à un contexte graphique. La classe FontMetrics permet notamment d'effectuer certains calculs concernant les polices.
Ainsi, il est possible d'utiliser la classe FontMetrics pour calculer la taille en largeur exprimée en pixels, d'une chaine de caractères écrite avec une certaine police. C'est la méthode stringWidth qui effectue ce type de calcul. Un exemple complet d'utilisation est donné dans la méthode paint de la classe Graphe (Maquette AREMM).
L'ensemble des polices de caractères qu'il est possible d'obtenir avec Java est présentée à l'adresse : http://www.neosoft.com/~wendt/FontTest/FontTest.html. La création d'une police requiert trois paramètres :
- le nom de la police
- son style : défini par l'une des variables (ou une de leur combinaisons) BOLD (Gras), ITALIC (Italique) ou PLAIN (Normal)
- sa taille : la hauteur des lettres en pixels
De nombreux exemples d'utilisation de polices de caractères sont données dans l'Applet Present3D (méthode afficheEvent).
B.6 La classe java.lang.Thread et l'interface java.lang.Runnable
Documentation complète : http://java.sun.com/JDK-1.0/api/java.lang.Thread.html
http://java.sun.com/JDK-1.0/api/java.lang.Runnable.html
B.6.1 Présentation générale
La classe Thread permet de gérer différents processus dans un programme Java. Les instances de Thread représentent des tâches qui s'exécutent en parallèle. Ainsi, les Threads sont les objets de base pour la programmation en parallèle en Java. La programmation parallèle permet à un même programme de faire exécuter par des Threads différentes tâches en même temps.
La classe Thread et l'interface Runnable sont extrêmement liées puisque la classe Thread implémente Runnable. L'interface Runnable a été créée pour fournir aux objets qui doivent faire exécuter du code, un protocole commun. Ainsi, il existe plusieurs manières de faire lorsqu'un programmeur désire créer des éléments qui peuvent être des tâches s'exécutant en parallèle. Soit il peut créer une sous-classe de la classe Thread, soit il peut créer une classe implémentant l'interface Runnable. Cette seconde solution est plus recommandée, surtout si l'objet ne doit implémenter que la méthode run. Il vaut mieux ne pas faire de sous-classe de la classe Thread, à moins de vouloir complètement changer le comportement de celle-ci.
Toute tâche gérée par l'intermédiaire de Thread possède un début, une séquence d'exécution, et une fin. Ainsi, la machine virtuelle de Java fonctionne jusqu'à ce que tous les Threads (qui ne sont pas de type Daemon) soient terminés. Un Thread est terminé lorsque sa méthode run est terminée, ou lorsque la méthode stop a été appelée, suite à un changement de page, ou à une fermeture du Browser.
B.6.2 Les principales méthodes utilisées
La seule méthode contenue dans l'interface Runnable est la méthode run. C'est aussi la méthode la plus importante de la classe Thread, puisqu'elle contient le code qui sera exécuté par un objet Thread.
Il existe deux manières principales de créer un objet Thread :
Faire une sous-classe de Thread possèdant le comportement désiré et dont la méthode run a été surchargée. Par exemple :
class Tache extends Thread {
....
public void run(){
// Code de la tâche
....
}
}
class Test extends Applet {
....
void init(){
Tache t=new Tache();
}
}
Faire une classe implémentant l'interface Runnable et créer ensuite un Thread basé sur cette classe. En reprenant le même exemple que ci-dessus, cela donnerait :
class Tache implements Runnable {
....
public void run(){
// Code de la tâche
....
}
}
class Test extends Applet {
....
public void init(){
Tache maTache=new Tache();
Thread t=new Thread(maTache);
}
}
La seconde solution est souvent la meilleure puisqu'elle évite de faire une sous-classe d'un objet pour rien (le comportement de l'objet Tache est le même que Thread dans la première solution). C'est celle qui a été adoptée dans les Applets MagicMouse et Present3D. La classe sur laquelle se base le Thread est l'Applet lui-même dans les deux cas. L'exemple précédant traité avec le même type de logique donnerait :
class Test extends Applet implements Runnable {
....
public void init(){
Thread t=new Thread(this);
}
public void run(){
// Code de la tache
....
}
}
La méthode run qui exécute le code de la tâche ne s'exécute cependant pas automatiquement après la création du Thread. Pour démarrer la tâche, il faut utiliser la méthode start de la classe Thread. Dans l'exemple ci-dessus, cela donnerait :
t.start();
De même, il est possible d'utiliser la méthode stop de la classe Thread pour stopper une tâche en cours. Dans ce cas, la tâche est définitivement stoppée, il n'est pas possible de la réactiver après l'appel de cette méthode.
Les méthodes suspend et resume permettent de suspendre l'exécution d'une tâche et de la reprendre après à l'endroit où elle s'était arrêtée. C'est cette solution qui a été utilisée dans l'Applet Present3D. Lorsque la méthode stop de l'Applet (à ne pas confondre avec la méthode stop de la tâche!) est appelée, la tâche doit être suspendue mais pas définitivement arrêtée. La méthode suspend est alors utilisée. Après cela, lorsque la méthode start de l'Applet (à ne pas confondre avec la méthode start de la tâche!) est appelée, la tâche est réactivée à l'endroit où elle avait été arrêtée.
Une dernière méthode a été très utilisée dans les deux Applets MagicMouse et Present3D. Il s'agit de la méthode sleep qui est une méthode statique, permettant d'arrêter l'exécution de la tâche courante pendant un nombre n de millisecondes. La tâche courante est la tâche qui était en train de s'exécuter lorsque l'appel de la méthode est fait. Dans les deux Applets, c'est la tâche elle-même qui fait appel à la méthode sleep. C'est donc elle qui est interrompue.
Appendice C : Les Applets dans les pages HTML
C.1 Introduction
Comme nous l'avons déjà vu dans les précédentes pages de ce rapport, un programme JAVA, appelé applet, est associé à une page HTML spécifiée. Le langage HTML (HyperText Markup Language) est utilisé pour créer des documents qui sont affichés sur les browsers Web.
Une page HTML est constituée de texte et de balises qui définissent la structure du document. Dans un tel document, les balises sont délimitées par les crochets < et >. De la même manière qu'on inclut du texte dans une page HTML, on peut inclure un applet JAVA en utilisant une balise spéciale appelée APPLET.
Lorsqu'un browser Web, doté d'un interpréteur JAVA, lit une page HTML contenant une balise APPLET, il sait qu'un programme JAVA est associé à cette page. Ainsi, automatiquement, il charge et exécute le programme JAVA associé. Dans le cas où le browser utilisé n'est pas doté de l'interpréteur JAVA, il peut tout de même lire la page. Cependant, il ignorera la balise APPLET et donc n'exécutera pas le programme.
Dans cette partie de la spécification nous allons vous expliquer en détails comment inclure un applet dans une page HTML.
C.2 Ajouter un Applet dans une Page HTML
C.2.1 Syntaxe Générale
Pour ajouter un applet dans une page HTML, il faut utiliser la balise APPLET.
Voici la syntaxe générale :
<APPLET
Codebase = "chemin du répertoire contenant les fichiers .class"
Code = "nom du fichier .class de l'applet à inclure"
Alt = "texte"
Name = "nom pour l'instance de l'applet"
Width = "largeur de l'applet en pixels"
Height = "hauteur de l'applet en pixels"
Align = "alignement de l'image"
Vspace = "espace au dessus et au dessous de l'applet, en pixels"
Hspace = "espace à gauche et à droite de l'applet, en pixels
>
<PARAM Name = "nom du paramètre" Value = "valeur du paramètre>
<PARAM Name = "nom du paramètre" Value = "valeur du paramètre>
</APPLET>
Codebase, Code et les autres sont des attributs; ils fournissent aux browsers des informations concernant l'applet.
L'attribut Codebase
Cet attribut est optionnel. Il spécifie le chemin du répertoire contenant le code précompilé de l'applet. Si ce répertoire est sous répertoire du répertoire contenant la page HTML, cet attribut spécifie seulement le nom du répertoire.
Si cet attribut n'est pas spécifié, c'est l'URL de la page qui est utilisée.
L'attribut Code
Cet attribut est obligatoire. Il spécifie le nom du fichier .class contenant le code précompilé de la sous classe Applet de l'applet à inclure.Si par exemple votre sous classe Applet s'appelle MonApplet, alors son fichier compilé se nomme MonApplet.class, ainsi pour l'inclure dans une page HTML vous spécifierez :
Code="MonApplet.class"
L'attribut Alt
Cet attribut est optionnel. Il spécifie le texte qui devra être affiché dans le cas où le browser comprend la balise APPLET mais ne peut exécuter les applets JAVA.
L'attribut Name
Cet attribut est optionnel. Il spécifie un nom pour l'instance de l'applet. Cela permet aux applets situés sur la même page HTML de s'identifier et de communiquer ensemble.
Les attributs Width et Height
Ces attributs sont obligatoires. Ils indiquent au browser la largeur et la hauteur initiales de la zone d'affichage de l'applet, sans prendre en compte les fenêtres et les boîtes de dialogue que l'applet ouvrira.
L'attribut Align
Cet attribut est obligatoire. C'est un moyen de spécifier l'alignement de l'applet par rapport au texte qui suit. Si vous ne spécifiez pas cet attribut, le bas de l'applet sera aligné avec le texte qui suit.
Les valeurs possibles pour cet attribut sont : left, right, top, texttop, middle, absmiddle, baseline, bottom, absbottom. Par exemple, si vous spécifiez Align=Top, alors le texte adjacent est aligné avec le sommet de l'applet. Si vous spécifiez Align=Middle, alors le texte sera aligné avec le centre de l'applet.
Les attributs Vspace et Hspace
Ces attributs sont optionnels. Ils spécifient le nombre de pixels au dessus et au dessous de l'applet (Vspace) mais aussi de chaque côté de l'applet (Hspace).
< PARAM Name = "nom paramètre" Value = "valeur paramètre">
Il est possible d'ajouter des paramètres. Pour cela, on utilise la balise PARAM. Cette dernière doit apparaître entre les balises <APPLET> et </APPLET>. Pour chaque paramètre, on définit son nom: NAME et sa valeur: VALUE. L'applet récupèrera ces valeurs en utilisant la méthode prédéfinie getParameter().
C.2.2 Quelques Exemples
Voici l'exemple d'une balise APPLET très simple :
< Applet Code="MyApplet.class" Width=100 Height=140 > </Applet>
Cela indique au browser de charger l'applet dont le code précompilé se trouve dans le fichier MyApplet.class. Ce fichier se trouve dans le même répertoire que celui de la page HTML. De plus, le browser est informé qu'il devra intialisé la taille de l'applet : 100 pixels en largeur et 140 pixels en hauteur.
Voici un exemple plus complexe :
<Applet Codebase="http://java.sun.com/applets/NervousText"
Code="NervousText.class"
Width=400 Height=75 Align=center
<PARAM Name="text" Value="Ceci est l'Applet Viewer">
<hr>
Si vous aviez utilisé un browser doté de l'interpréteur JAVA,
vous auriez vu un texte animé au lieu de ce paragraphe.
</hr>
</Applet>
Cela indique au browser de charger l'applet dont le code précompilé se trouve à l'URL http://java.sun.com/applets/NervousText. De plus, le browser est informé qu'il doit initialiser la taille de l'applet à 400*75 pixels et aligner l'applet au centre de la ligne. Le browser devra aussi paramétrer l'attribut "text" à la valeur "Ceci est l'Applet Viewer".
Si la page est visualisée par un browser qui ne peut exécuter les applets JAVA, ce dernier ignorera les balises APPLET et PARAM. Il affichera le texte compris entre les balises <hr> et </hr>. Les browsers dotés de l'interpréteur JAVA ignorent ce texte.