Académique Documents
Professionnel Documents
Culture Documents
ii
Yakov Fain
Traduit de langlais (amricain) par Vincent Lataye et Maxime Daniel (vincent_lataye@xoteam.fr, maxime_daniel@xoteam.fr)
iii
Mai 2004 : Premire dition lectronique Juin 2005 : Premire dition lectronique en franais
Linformation contenue dans ce livre nest pas sujette garantie. Ni lauteur ni lditeur ne pourront tre tenus responsables des prjudices ou dommages de quelque nature que ce soit pouvant rsulter directement ou indirectement des instructions fournies dans ce livre ou de lutilisation des logiciels ou matriels informatiques qui y sont dcrits. Java et toutes les marques et logos drivs de Java sont des marques commerciales ou des marques dposes de Sun Microsystems, Inc. aux Etats-Unis et dans les autres pays. Windows 98, Windows NT, Windows 2000 et Windows XP sont des marques commerciales de Microsoft Corporation. Tous les autres noms de produits et de socits sont la proprit de leurs propritaires respectifs.
Lditeur met la version franaise de ce livre lectronique la disposition du public titre gracieux. Pour plus dinformation, crire books@smartdataprocessing.com. ISBN: 0-9718439-4-5
iv
Commentaires de programme..................................................................................................... 54 Prises de dcisions l'aide de la clause if ................................................................................. 55 Oprateurs logiques ..................................................................................................................... 57 Oprateur conditionnel................................................................................................................ 58 Utilisation de else if ............................................................................................................... 58 Prises de dcisions l'aide de la clause switch ....................................................................... 60 Quelle est la dure de vie des variables ?.................................................................................... 61 Mthodes spciales : constructeurs............................................................................................. 62 Le mot-cl this ........................................................................................................................... 63 Tableaux........................................................................................................................................ 63 Rptition d'actions l'aide de boucles ...................................................................................... 65 Autres lectures .............................................................................................................................. 68 Exercices........................................................................................................................................ 68 Exercices pour les petits malins................................................................................................... 69
vi
vii
Autres lectures ............................................................................................................................ 141 Exercices...................................................................................................................................... 141 Exercices pour les petits malins................................................................................................. 141
viii
Autres lectures ............................................................................................................................ 203 Exercices...................................................................................................................................... 203 Exercices pour les petits malins................................................................................................. 204
INDEX.................................................................................................... 216
ix
Prface
Un jour, mon fils Davey entra dans mon bureau tel un ouragan, mon didacticiel Java pour adultes la main. Il me demanda de lui apprendre programmer pour pouvoir crer des jeux informatiques. A cette poque, javais dj crit une paire de livres sur Java et donn de nombreux cours de programmation, mais ctait pour les grandes personnes ! Une recherche sur Amazon na rien donn dautre que des livres "pour les nuls", mais Davey nest pas un "nul" ! Aprs avoir pass des heures sur Google, je ne trouvai que de pauvres tentatives de cours de Java pour les enfants ou des livres trs superficiels. Sais-tu ce que jai fait ? Jai dcid den crire un. Pour maider comprendre la mentalit des plus jeunes, je dcidai de demander Davey de devenir mon premier tudiant enfant. Ce livre sera utile aux personnes suivantes :
Les jeunes de 11 18 ans. Les enseignants en informatique. Les parents souhaitant apprendre programmer leurs enfants. Tous ceux qui dbutent en programmation (lge na pas dimportance).
Mme si jemploie un langage simple pour expliquer la programmation, je mengage traiter mes lecteurs avec respect je ne vais pas crire quelque chose comme "Cher ami ! Tu es sur le point de commencer un nouveau et passionnant voyage". Bon, daccord ! Venons-en aux faits. Les premiers chapitres de ce livre aboutiront des programmes de jeu simples, avec les instructions dtailles pour les faire fonctionner. Nous allons aussi crer une calculatrice qui ressemble celle que tu as dans ton ordinateur. Dans la seconde partie du livre, nous crerons ensemble les programmes de jeu Morpion et Ping-Pong. Tu devras thabituer largot des programmeurs professionnels ; les mots importants sont crits dans cette police. Les programmes et les lments du langage Java sont crits dans une autre police, par exemple String. Ce livre ne couvre pas tous les lments du langage Java, sinon il serait trop gros et ennuyeux. Mais la fin de chaque chapitre, il y a une section Autres lectures avec des liens vers des sites web contenant des explications plus dtailles sur le sujet.
Tu trouveras aussi des devoirs la fin de chaque chapitre. Chaque lecteur doit faire les exercices de la section Exercices. Si ceux-ci sont trop faciles pour toi, je te mets au dfi de faire ceux de la section Exercices pour les petits malins. En fait, si tu lis ce livre, tu es une personne intelligente et tu devrais essayer de faire tous les exercices. Pour retirer le maximum de ce livre, lis-le du dbut la fin. Ne change pas de chapitre avant davoir compris celui que tu es en train de lire. Les ados, les parents et les grands-parents devraient pouvoir matriser ce livre sans aide extrieure, mais les enfants plus jeunes devraient lire ce livre avec laide dun adulte.
xi
Remerciements
Merci tous les architectes et dveloppeurs qui ont travaill gratuitement sur Eclipse lun des meilleurs environnements de dveloppement intgrs disponibles pour Java. Remerciements particuliers aux chauffeurs de bus de la socit New Jersey Transit pour la souplesse de leur conduite la moiti de ce livre a t crite dans le bus n 139, que je prenais pour aller au travail. Merci cette dame adorable, ma femme, Natasha, pour avoir fait tourner avec succs cette affaire quon appelle famille. Remerciements particuliers Yuri Goncharov un dveloppeur Java expert de Toronto, au Canada. Il a relu le livre, test chaque exemple de code et fourni un retour prcieux afin damliorer un peu ce livre.
langues. De la mme faon, on peut crire des programmes informatiques, tels que des jeux, calculatrices ou diteurs de texte, laide de diffrents langages de programmation. Sans programmes, ton ordinateur serait inutile et son cran serait toujours noir. Les lments de lordinateur constituent le matriel (hardware) 1 et les programmes le logiciel (software). Les langages informatiques les plus populaires sont Visual Basic, C++ et Java. Quest-ce qui fait de Java un langage diffrent de beaucoup dautres ? Premirement, le mme programme Java peut tourner (fonctionner) sur diffrents ordinateurs, tels que PC, Apple et autres, sans modification. En fait, les programmes Java ne savent mme pas o ils sexcutent, car ils le font lintrieur dune enveloppe logicielle spciale appele Machine Virtuelle Java, ou plus simplement Java. Si, par exemple, ton programme Java a besoin dimprimer des messages, il demande Java de le faire et Java sait comment se dbrouiller avec ton imprimante. Deuximement, Java permet de traduire facilement tes programmes (crans, menus et messages) en diffrentes langues. Troisimement, Java te permet de crer des composants logiciels (classes) 2 qui reprsentent les objets du monde rel. Par exemple, tu peux crer une classe Java nomme Voiture et lui donner des attributs tels que portes ou roues similaires ceux dune vraie voiture. Ensuite, partir de cette classe, tu peux crer une autre classe, par
NDT : Langlais constituant la langue de rfrence dans le monde de linformatique en gnral et de la programmation en particulier, nous avons pris le parti de rappeler, entre parenthses, lquivalent anglais des principaux termes techniques lors de leur premire apparition dans le texte. 2 NDT : En franais : une classe, des classes. En anglais : a class, classes.
1
13
exemple Ford, qui aura toutes les caractristiques de la classe Voiture et dautres que seules les Ford possdent. Quatrimement, Java est plus puissant que beaucoup dautres langages. Cinquimement, Java est gratuit ! Tu peux trouver sur Internet tout ce quil faut pour crer tes programmes Java sans dbourser un euro !
Une fois le tlchargement termin, lance linstallation double-clique simplement sur le fichier que tu as tlcharg pour installer J2SDK sur ton disque. Par exemple, sur une machine Windows, le programme dinstallation crera un rpertoire comme celui-ci :
14
Si tu nas pas assez de place sur ton disque c:, choisis-en un autre, sinon, contente-toi dappuyer sur les boutons Next, Install et Finish dans les fentres qui saffichent lcran. Linstallation de Java sur ton ordinateur ne prendra que quelques minutes. A ltape suivante de linstallation, tu dois dfinir deux variables systme. Dans Windows, par exemple, clique sur le bouton dmarrer et ouvre le Panneau de configuration (il peut tre cach derrire le menu Paramtres), puis double-clique sur licne Systme. Slectionne longlet Avanc et clique sur le bouton Variables denvironnement.
15
La fentre suivante prsente toutes les variables systme qui existent dj dans ton systme.
16
Clique sur le bouton Nouveau en bas de la fentre et dclare la variable Path qui permettra Windows (ou Unix) de trouver J2SDK sur ta machine. Vrifie bien le nom du rpertoire o tu as install Java. Si la variable Path existe dj, clique sur le bouton Modifier et ajoute le nom complet du rpertoire Java suivi dun point-virgule au tout dbut de la bote Valeur de la variable :
De mme, dclare la variable CLASSPATH en entrant comme valeur un point suivi dun point-virgule. Cette variable systme permettra Java de trouver tes programmes. Le point signifie que Java doit chercher tes programmes partir du rpertoire courant. Le point-virgule nest quun sparateur :
17
Linstallation de J2SDK est maintenant termine ! Si tu as un vieil ordinateur Windows 98, tu dois positionner les variables PATH et CLASSPATH dune autre manire. Trouve le fichier autoexec.bat sur ton disque c: et utilise le Bloc-notes ou un autre diteur de texte pour entrer les bonnes valeurs de ces variables la fin du fichier, comme ceci : SET CLASSPATH=.; SET PATH=c:\j2sdk1.5.0_03\bin;%PATH% Aprs avoir effectu cette modification, il faut redmarrer ton ordinateur.
principales
de
la
Pour crer un programme Java qui marche, tu dois passer par les tapes suivantes : Ecrire le programme en Java et lenregistrer sur un disque. Compiler le programme pour le traduire en un code binaire spcial comprhensible par Java. Excuter le programme.
18
Tout dabord, tu dois taper le programme et lenregistrer dans un fichier texte dont le nom se termine par .java. Par exemple, si tu veux crire un programme appel BonjourMonde, entre son texte (on appelle a le code source) dans le Bloc-notes et enregistre-le dans un fichier que tu nommeras BonjourMonde.java. Ne mets pas de blancs dans les noms de fichiers Java. Voici le programme qui affiche les mots "Bonjour Monde" lcran :
public class BonjourMonde { public static void main(String[] args) { System.out.println("Bonjour Monde"); } }
Jexpliquerai comment fonctionne ce programme un peu plus tard dans ce chapitre, mais pour linstant fais-moi confiance ce programme affichera les mots "Bonjour Monde" ltape 3.
19
20
un message derreur. Il te faudra alors corriger lerreur et recompiler le programme. Sil y a plusieurs erreurs, tu peux avoir besoin de rpter ces actions plusieurs reprises avant dobtenir le fichier BonjourMonde.class.
Noublie jamais que Java fait la diffrence entre les lettres minuscules et majuscules. Par exemple, si tu as nomm le programme BonjourMonde, avec un B majuscule et un M majuscule, nessaie pas de lancer le programme bonjourmonde ou bonjourMonde Java se plaindrait. Maintenant amusons-nous un peu essaie de deviner comment modifier ce programme. Je texpliquerai comment fonctionne ce programme dans le prochain chapitre, mais tout de mme, essaie de deviner comment le modifier pour quil dise bonjour ton animal familier, ton ami ou quil affiche ton adresse. Suis les trois tapes pour voir si le programme fonctionne toujours aprs tes modifications . Dans le prochain chapitre, je vais te montrer comment crire, compiler et excuter tes programmes dans un environnement plus sympa quun diteur de texte et une fentre de commande.
21
Autres lectures
Pour crer ta premire application : http://java.sun.com/docs/books/tutorial/getStarted/c upojava/win32.html Instructions dinstallation de Java pour Windows : http://java.sun.com/j2se/1.5.0/install-windows.html
22
appelle un Environnement de dveloppement intgr (Integrated Development Environment ou IDE). On peut y crire, compiler et excuter les programmes. Un IDE fournit aussi un utilitaire dAide qui dcrit tous les lments du langage et te permet de trouver et de corriger plus facilement les erreurs dans tes programmes. Alors que la plupart des IDE sont trs chers, il en existe un excellent, gratuit : Eclipse. Tu peux le tlcharger depuis le site web www.eclipse.org. Dans ce chapitre, je vais taider tlcharger et installer lenvironnement de dveloppement Eclipse sur ton ordinateur, puis y crer le projet Bonjour Monde. Ensuite, nous crerons tous nos programmes dans cet environnement. Familiarise-toi avec Eclipse cest un outil excellent, utilis par beaucoup de programmeurs Java.
Installation dEclipse
Ouvre la page web www.eclipse.org et clique sur le menu Download gauche. Slectionne ensuite la version dEclipse que tu souhaites tlcharger. Il y a gnralement la version officielle la plus rcente (latest release) et plusieurs versions intermdiaires stables (stable builds). Ces dernires peuvent avoir plus de fonctionnalits, mais elles peuvent encore avoir quelques dfauts mineurs. A lheure o jcris ces lignes, la dernire version officielle est la 3.0.2. Slectionne-la 3 pour obtenir la fentre suivante :
NDT : Attention : moins de prfrer travailler dans un environnement en anglais, il est prfrable dutiliser une version officielle, plutt quune version intermdiaire plus rcente qui peut ne pas encore tre supporte en franais. Lis aussi la note dinstallation au bas de la page 24.
23
Clique sur le lien de tlchargement correspondant ton systme et enregistre le fichier avec ce nom si long termin par .zip dans le rpertoire de ton choix sur ton disque. Tu nas plus qu dcompresser ce fichier sur ton disque. Si le programme WinZip est dj install sur ton ordinateur, clique sur le fichier avec le bouton droit de la souris et slectionne WinZip dans le menu contextuel, puis loption Extraire vers. Si tu as de la place sur ton disque c:, appuie sur le bouton Extraire, sinon slectionne un autre disque avec plus despace disponible.
Les fichiers avec lextension .zip sont des archives contenant de nombreux fichiers compresss. Dcompresser le fichier signifie extraire le contenu de cette archive sur le disque. Le programme darchivage le plus populaire est WinZip. Tu peux en tlcharger une version dvaluation ladresse suivante :
http://www.winzip.com/french.htm
24
Linstallation dEclipse est termine 4 ! Pour que ce soit plus pratique pour toi, cre un raccourci vers Eclipse. Clique avec le bouton droit de la souris sur le bureau, puis clique sur Nouveau, Raccourci, Parcourir et slectionne le fichier eclipse.exe dans le rpertoire c:\eclipse. Pour lancer le programme, double-clique sur licne bleue dEclipse, et tu verras le premier cran de bienvenue (cet cran peut changer lgrement selon les versions dEclipse) :
NDT : La version de base dEclipse est en anglais. Pour que ton environnement (menus, aide en ligne, messages) soit en franais, il te faut installer quelques fichiers complmentaires. Sur la page web www.eclipse.org, clique sur le menu Download puis sur le lien Platform downloads de la rubrique Eclipse Project, puis sur Language Pack Translations. Dans la section SDK Language Pack, tlcharge le fichier .zip correspondant ton systme. Ensuite, dcompresse ce fichier lendroit o tu as dcompress Eclipse (par exemple c:\). Attention : cette extension nest pas forcment compatible avec les versions intermdiaires dEclipse.
25
Complte le nom du plan de travail dans la rubrique Espace de travail. Par exemple, c:\eclipse\plan de travail. Clique sur le bouton OK.
Clique sur la flche en haut droite pour afficher ton plan de travail, qui doit ressembler lcran suivant :
26
27
Regarde la bote grise nomme Rpertoire. Elle tindique o seront enregistrs les fichiers de ce projet. Eclipse utilise un rpertoire spcial appel plan de travail (workspace), o seront stocks tous les fichiers de tes projets. Plus tard, tu creras des projets distincts pour une calculatrice, un jeu de morpion et dautres programmes. Il y aura plusieurs projets dans le plan de travail avant la fin de ce livre. Un plan de travail Eclipse contient plusieurs aires plus petites, appeles perspectives, qui constituent diffrentes vues de tes projets. Si Eclipse te le demande, accepte de passer en perspective Java.
28
Si tu cliques sur le petit signe plus devant Mon Premier Projet, tu verras plus de dtails. Pour linstant, il doit y avoir la ligne Bibliothque systme JRE (jdk1.5.0_03), qui constitue une partie du projet. Si ce nest pas le cas, clique sur les menus Fentre, Prfrences, Java, JRE installs, Ajouter, puis, laide du bouton Parcourir, trouve le rpertoire o tu as install Java, par exemple c:\Program Files\java\j2sdk1.5.0_03.
29
Clique sur le bouton Fin et tu verras que Eclipse a cr pour toi la classe BonjourMonde. Des commentaires de programme (le texte entre /* et */) ont t gnrs et placs en haut - tu devrais les modifier pour dcrire ta classe. A la suite des commentaires, tu trouveras le code de la classe BonjourMonde avec une mthode (method) main() vide. Le mot mthode signifie action. Pour excuter une classe Java comme un programme, cette classe doit possder une mthode nomme main().
public class BonjourMonde { public static void main(String[] args) { } }
Pour terminer notre programme, place le curseur aprs laccolade de la ligne qui contient main, appuie sur la touche Entre et tape la ligne suivante :
30
System.out.println("Bonjour Monde");
Pour enregistrer le programme sur le disque et le compiler, appuie simultanment sur deux touches de ton clavier : Ctrl-S. Si tu nas pas fait derreur de syntaxe, tu ne verras aucun message le programme est compil. Mais faisons une erreur volontairement pour voir ce qui va arriver. Supprime la dernire accolade et appuie nouveau sur Ctrl-S. Eclipse affiche alors Erreur de syntaxe dans la vue des Erreurs et affiche une marque rouge au dbut de la ligne qui pose problme. Lorsque tes projets sont plus importants, ils contiennent plusieurs fichiers et le compilateur peut gnrer plus dune erreur. Tu peux rapidement trouver (mais pas corriger) les lignes problmatiques en double-cliquant sur le message derreur dans la vue des erreurs. Remettons laccolade et appuyons nouveau sur Ctrl-S voil, le message derreur a disparu !
31
Appuie maintenant sur le bouton Excuter pour lancer le programme. Les mots "Bonjour Monde" seront affichs dans la vue Console comme ils ltaient au chapitre 1. Tu peux dsormais excuter ce projet en passant par les menus Excuter, Excuter le dernier lancement ou en appuyant sur les touches Ctrl-F11 du clavier.
32
Cette signature nous donne les informations suivantes : Qui a accs la mthode - public. Le mot-cl public signifie que la mthode main() peut tre utilise par nimporte quelle autre classe Java ou par Java lui-mme. Comment utiliser la mthode - static. Le mot-cl static signifie quil nest pas ncessaire de crer une instance (une copie) de lobjet BonjourMonde en mmoire pour pouvoir utiliser cette mthode. Nous reviendrons sur les instances de classe dans le prochain chapitre. La mthode retourne-t-elle des donnes ? Le mot-cl void signifie que la mthode main() ne retourne aucune donne au programme appelant, qui en loccurrence est Eclipse. Mais si on prenait lexemple dune mthode effectuant des calculs, celle-ci pourrait retourner un rsultat son appelant. Le nom de la mthode est main. La liste des arguments des donnes qui peuvent tre fournies la mthode String[] args. Dans la mthode main(), String[] args signifie que la mthode peut recevoir un tableau (array) de chanes de caractres (String) qui reprsentent du texte. Les valeurs qui sont passes la mthode sont appeles arguments. Comme je lai dj dit, un programme peut tre constitu de plusieurs classes, mais lune dentre elles possde la mthode main(). Les classes Java ont en gnral plusieurs mthodes. Par exemple, une classe Jeu pourrait avoir les mthodes dmarrerJeu(), arrterJeu(), lireScore() et ainsi de suite. Le corps de notre mthode main()ne contient quune ligne :
System.out.println("Bonjour Monde");
Chaque instruction ou appel de mthode doit se terminer par un pointvirgule ;. La mthode println()sait comment afficher des donnes sur la console systme (fentre de commande). Les noms de mthodes Java sont toujours suivis par des parenthses. Sil ny a rien entre les parenthses, cela signifie que la mthode ne prend pas darguments. Lexpression System.out signifie que la variable out est dfinie lintrieur de la classe System fournie avec Java. Comment es-tu sens savoir quil existe quelque chose nomm out dans la classe System ?
33
Eclipse va ty aider. Ds que tu as tap le mot System suivi dun point, Eclipse te propose automatiquement tout ce qui est disponible dans cette classe. Et tout moment tu peux placer le curseur aprs le point et appuyer sur Ctrl-Espace pour afficher une fentre daide de ce genre :
Lexpression out.println() indique que la variable out reprsente un objet et que ce "quelque chose nomm out" possde une mthode nomme println(). Le point entre la classe et le nom de la mthode signifie que la mthode existe lintrieur de la classe. Mettons que tu aies une classe JeuPingPong qui possde la mthode sauverScore(). Voil comment tu peux appeler cette mthode pour Dave qui a gagn trois parties : Encore une fois, les donnes entre les parenthses sont appeles arguments, ou paramtres. Ces paramtres sont fournis une mthode pour tre utiliss dans un traitement, par exemple pour enregistrer des donnes sur le disque. La mthode sauverScore() a deux arguments la chane de caractres "Dave" et le nombre 3. Eclipse rend amusante lcriture des programmes Java. Lannexe B prsente quelques trucs et astuces utiles pour booster ta programmation Java dans cet excellent environnement de dveloppement.
JeuPingPong.sauverScore("Dave", 3);
34
Autres lectures
Site web Eclipse :
http://www.eclipse.org
Exercices
Modifie la classe BonjourMonde pour quelle affiche ton adresse, en utilisant plusieurs appels la mthode println().
35
reprsentent des objets du monde rel. Mme si chaque personne crit des programmes sa faon, presque tout le monde est daccord pour reconnatre que la meilleure faon de le faire est demployer le style dit orient objet. Cela signifie que les bons programmeurs commencent par dcider quels objets doivent tre inclus dans le programme et quelles classes Java vont les reprsenter. Ce nest quune fois cette tape mene bien quils commencent crire du code Java.
es
programmes
Java
sont
constitus
de
classes
qui
Classes et Objets
Les classes Java peuvent possder des mthodes et des attributs. Les mthodes dfinissent les actions quune classe peut effectuer. Les attributs dcrivent la classe.
Crons et discutons une classe nomme JeuVido. Cette classe peut avoir plusieurs mthodes, qui reprsentent les actions que les objets de cette classe peuvent effectuer : dmarrer le jeu, larrter, enregistrer le score, etc. Cette classe peut aussi possder des attributs ou proprits : prix, couleur de lcran, nombre de tlcommandes et autres.
36
Notre classe JeuVido est sans doute similaire aux autres classes qui reprsentent des jeux vido ceux-ci ont tous des crans de taille et de couleur diffrentes, effectuent des actions similaires et cotent de largent. Nous pouvons tre plus spcifiques et crer une autre classe Java, nomme GameBoyAdvance. Elle appartient aussi la famille des jeux vido, mais possde certaines proprits spcifiques au modle GameBoy Advance, par exemple un type de cartouche.
class GameBoyAdvance { String typeCartouche; int largeurEcran; void dmarrerJeu() { } void arrterJeu() { } }
37
Dans cet exemple, la classe GameBoyAdvance dfinit deux attributs typeCartouche et largeurEcran et deux mthodes dmarrerJeu et arrterJeu. Mais, pour linstant, ces mthodes ne peuvent effectuer aucune action, parce quil ny a pas de code Java entre leurs accolades. Aprs le mot classe, tu dois maintenant thabituer la nouvelle signification du mot objet. La phrase "crer une instance dun objet" signifie crer une copie de cet objet dans la mmoire de lordinateur en respectant la dfinition de sa classe.
Un plan de fabrication de la GameBoy Advance correspond une console relle de la mme faon quune classe Java correspond lune de ses instances en mmoire. Le processus de fabrication des consoles relles daprs ce plan est similaire au processus de cration dinstances dobjets GameBoyAdvance en Java.
La plupart du temps, un programme ne pourra utiliser une classe Java quaprs quune instance en ait t cre. De mme, les fabricants
38
crent des milliers de copies dune console de jeu partir dune mme description. Bien que ces copies reprsentent la mme classe, leurs attributs peuvent avoir des valeurs diffrentes certaines sont bleues alors que dautres sont argentes, et ainsi de suite. En dautres termes, un programme peut crer de multiples instances dobjets GameBoyAdvance.
Types de donnes
Les variables Java peuvent reprsenter les attributs dune classe, les arguments dune mthode ou tre utilises lintrieur dune mthode pour stocker temporairement certaines donnes. Les variables doivent tre dclares avant de pouvoir tre utilises. Te souviens-tu dquations telles que y = x + 2 ? En Java, tu dois dclarer les variables x et y en prcisant quelles appartiennent un type de donnes numrique tel que int ou double :
int x; int y;
Les deux lignes suivantes montrent comment tu peux affecter une valeur ces variables. Si ton programme donne la valeur 5 la variable x, la variable y sera gale 7 :
x = 5; y = x + 2;
En Java, tu peux aussi changer la valeur dune variable dune faon assez inhabituelle. Les deux lignes suivantes modifient la valeur de la variable y, qui passe de 5 6 :
int y = 5; y++;
Bien quil y ait deux signes plus, Java va tout de mme incrmenter la valeur de la variable y de 1. Aprs le fragment de code suivant, la valeur de la variable monScore est aussi 6 :
int monScore = 5; monScore = monScore + 1;
On peut utiliser de la mme manire la multiplication, la division et la soustraction. Regarde lextrait de code suivant :
int monScore = 10; monScore--; monScore = monScore * 2;
Programmation Java pour les enfants, les parents et les grands-parents monScore = monScore / 3; System.out.println("Mon score est " + monScore);
39
Quimprime ce code ? Eclipse a une fonctionnalit bien pratique appele page de testeur de code, qui permet de tester rapidement nimporte quel bout de code (comme le prcdent) sans mme crer une classe. Slectionne le menu Fichier, Nouveau, Autre, puis Java, Excution/Dbogage Java, Page de testeur de code et entre le mot Test comme nom de ta page. Entre maintenant dans la page ces cinq lignes de code utilisant monScore, slectionne-les et clique sur la petite flche verte accompagne dun J dans la barre doutils.
Pour voir le rsultat des calculs, clique simplement sur longlet Console en bas de lcran :
Mon score est 6
Dans cet exemple, largument de la mthode println() a t fabriqu en accolant deux morceaux le texte "Mon score est " et la valeur de la variable monScore, cest--dire 6. On appelle concatnation la cration dune chane de caractres (String) partir de morceaux. Bien que monScore soit un nombre, Java est suffisamment malin pour convertir cette variable en String puis laccoler au texte "Mon score est ". Voyons dautres faons de modifier les valeurs des variables : monScore = monScore * 2; est quivalent monScore *= 2;
40
monScore = monScore + 2; est quivalent monScore += 2; monScore = monScore - 2; est quivalent monScore -= 2; monScore = monScore / 2; est quivalent monScore /= 2; Il y a huit types de donnes simples, ou primaires en Java, et tu dois dcider lequel utiliser en fonction du type et de la taille des donnes que tu as lintention de stocker dans chaque variable : Quatre types de donnes pour les valeurs entires byte, short, int et long. Deux types de donnes pour les valeurs dcimales float et double. Un type de donnes qui permet de stocker un caractre isol char. Un type de donnes logique nomm boolean qui autorise seulement deux valeurs : true (vrai) ou false (faux). On peut affecter une valeur initiale une variable lors de sa dclaration. On parle alors dinitialisation de la variable :
char niveau = 'E'; int chaises = 12; boolean sonActif = false; double revenuNational = 23863494965745.78; float prixJeu = 12.50f; long totalVoitures = 4637283648392l;
Dans les deux dernires lignes, f signifie float et l signifie long. Si tu ninitialises pas les variables, Java le fera pour toi en donnant la valeur 0 chaque variable numrique, la valeur false aux variables de type boolean et le code spcial \u0000 aux variables de type char. Il y a aussi le mot-cl spcial final ; sil est utilis dans la dclaration dune variable, on ne peut affecter de valeur cette variable quune fois, cette valeur ne pouvant plus tre modifie par la suite. Dans certains langages, les variables invariantes sont appeles constantes. En Java les noms des variables invariantes sont gnralement crits en lettres majuscules :
final String CAPITALE_ETAT = "Washington";
Outre les types de donnes primaires, on peut aussi utiliser les classes Java pour dclarer des variables. A chaque type de donnes primaire correspond une classe enveloppe, par exemple Integer, Double,
41
Boolean, etc. Ces classes possdent des mthodes utiles pour convertir les donnes dun type un autre. Alors que le type de donnes char est utilis pour stocker un caractre isol, Java a aussi une classe String permettant de manipuler un texte plus long, par exemple :
String nom = "Dupont";
En Java, les noms de variables ne peuvent pas commencer par un chiffre ni contenir despaces.
Un bit est le plus petit bout de donne que lon puisse stocker en mmoire. Il contient soit 1, soit 0. Un octet (byte) est compos de huit bits. En Java, un char occupe deux octets en mmoire. En Java, un int ou un float occupe quatre octets. Les variables de type long ou double utilisent huit octets. Les types de donnes numriques qui utilisent plus doctets peuvent stocker de plus grands nombres. 1 kilooctet (KO) correspond 1024 octets. 1 mgaoctet (MO) correspond 1024 kilooctets. 1 gigaoctet (GO) correspond 1024 mgaoctets.
42
Nous sommes maintenant prts dclarer les attributs et les mthodes de la classe AnimalFamilier. Le corps des mthodes et des classes Java est dlimit par des accolades. A chaque accolade ouvrante doit correspondre une accolade fermante :
class AnimalFamilier { }
Pour dclarer les variables constituant les attributs de la classe, nous devons choisir leur type. Prenons par exemple le type int pour lge, float pour la taille et le poids et String pour la couleur.
43
class AnimalFamilier { int ge; float poids; float taille; String couleur; }
Ltape suivante consiste ajouter des mthodes notre classe. Avant de dclarer une mthode, il faut dcider si elle prend des arguments et si elle retourne une valeur : La mthode dormir() ne fera quafficher le message "Bonne nuit, demain" elle na pas besoin darguments et ne retourne aucune valeur. Il en est de mme pour la mthode manger(). Elle ne fera quafficher le message "Jai si faim Donne-moi un biscuit !". La mthode dire() affichera aussi un message, mais lanimal pourra "dire" (afficher) le mot ou la phrase que nous lui fournirons. Nous passerons ce mot la mthode dire() comme un argument de mthode. La mthode construira une phrase en utilisant cet argument et la retournera au programme appelant. La nouvelle version de la classe AnimalFamilier ressemble ceci :
public class AnimalFamilier { int ge; float poids; float taille; String couleur; public void dormir() { System.out.println("Bonne nuit, demain"); } public void manger() { System.out.println( "Jai si faim Donne-moi un biscuit !"); } public String dire(String unMot) { String rponseAnimal = "OK !! OK !! " + unMot; return rponseAnimal; } }
44
Elle nous indique que cette mthode peut tre appele depuis nimporte quelle autre classe Java (public) et quelle ne retourne aucune donne (void). Les parenthses vides signifient que cette mthode ne prend pas dargument, parce quelle na besoin daucune donne du monde extrieur elle affiche toujours le mme texte. La signature de la mthode dire() est celle-ci :
public String dire(String unMot)
Cette mthode peut aussi tre appele depuis nimporte quelle autre classe Java, mais elle doit retourner un texte, ce quindique le mot-cl String devant le nom de la mthode. Par ailleurs, elle attend une donne textuelle de lextrieur, do largument String unMot.
45
Comment dcider si une mthode doit retourner une valeur ou pas ? Si une mthode manipule des donnes et doit fournir le rsultat de ces manipulations une classe appelante, elle doit retourner une valeur. Tu vas me dire que notre classe AnimalFamilier na aucune classe appelante ! Cest exact, alors crons-en une, que nous appellerons MatreAnimal. Cette classe aura une mthode main() contenant le code ncessaire pour communiquer avec la classe AnimalFamilier. Cre simplement une autre classe nomme MatreAnimal, mais cette fois slectionne dans Eclipse loption qui cre la mthode main(). Rappelle-toi, sans cette mthode il est impossible dexcuter cette classe en tant que programme. Modifie le code gnr par Eclipse pour obtenir ceci :
public class MatreAnimal { public static void main(String[] args) { String ractionAnimal; AnimalFamilier monAnimal = new AnimalFamilier(); monAnimal.manger(); ractionAnimal = monAnimal.dire("Cui !! Cui !!"); System.out.println(ractionAnimal); monAnimal.dormir(); } }
Noublie pas dappuyer sur Ctrl-S pour enregistrer et compiler cette classe ! Pour excuter la classe MatreAnimal, slectionne le menu Eclipse Excuter, Excuter, Crer et tape le nom de la classe principale : MatreAnimal. Appuie sur le bouton Excuter et le programme affichera le texte suivant :
Jai si faim Donne-moi un biscuit ! OK !! OK !! Cui !! Cui !! Bonne nuit, demain
La classe MatreAnimal est la classe appelante ; elle commence par crer une instance de lobjet AnimalFamilier. Elle dclare une variable monAnimal et utilise loprateur Java new :
AnimalFamilier monAnimal = new AnimalFamilier();
Cette ligne dclare une variable du type AnimalFamilier (cest exact, tu peux considrer chaque classe que tu cres comme un nouveau type Java). Maintenant, la variable monAnimal sait o a t cre linstance dAnimalFamilier dans la mmoire de lordinateur,
46
et tu peux utiliser cette variable pour appeler nimporte laquelle des mthodes de la classe AnimalFamilier, par exemple :
monAnimal.dormir();
Si une mthode retourne une valeur, tu dois lappeler dune autre faon. Dclare une variable du mme type que la valeur retourne par la mthode. Tu peux maintenant appeler cette mthode :
String ractionAnimal; ractionAnimal = monAnimal.dire("Cui !! Cui !!");
A ce stade, la valeur retourne est stocke dans la variable ractionAnimal et si tu veux voir ce quelle contient, ne te gne pas :
System.out.println(ractionAnimal);
47
Hritage un AnimalFamilier
Poisson
est
aussi
un
Notre classe AnimalFamilier va nous aider dcouvrir un autre concept important de Java, appel hritage. Dans la vie relle, chaque personne hrite des caractristiques de lun ou lautre de ses parents. De la mme faon, dans le monde Java, tu peux, partir dune classe, en crer une nouvelle. La classe AnimalFamilier possde un comportement et des attributs partags par de nombreux animaux familiers ils mangent, dorment, certains dentre eux mettent des bruits, leurs peaux peuvent tre de diffrentes couleurs, etc. Dun autre ct, les animaux familiers sont diffrents les uns des autres les chiens aboient, les poissons nagent et sont silencieux, les perroquets parlent mieux que les chiens. Mais tous mangent, dorment, ont un poids et une taille. Cest pourquoi il est plus facile de crer une classe Poisson qui hritera certains comportements et attributs communs de la classe AnimalFamilier, que de crer Chien, Perroquet ou Poisson partir de rien chaque fois. Le mot-cl spcial extends est l pour a :
On peut dire que notre Poisson est une sous-classe (subclass) de la classe AnimalFamilier et que la classe AnimalFamilier est une superclasse (superclass) de la classe Poisson. Autrement dit, on utilise la classe AnimalFamilier comme un modle pour crer la classe Poisson. Mme si tu te contentes de laisser la classe Poisson telle quelle est maintenant, tu peux toujours utiliser chacun des attributs et mthodes hrits de la classe AnimalFamilier. Regarde :
Poisson monPetitPoisson = new Poisson(); monPetitPoisson.dormir();
Mme si nous navons pas encore dclar de mthode dans la classe Poisson, nous avons le droit dappeler la mthode dormir() de sa superclasse !
48
Dans Eclipse, la cration de sous-classes est une partie de plaisir ! Slectionne le menu Fichier, Nouveau, Classe et tape Poisson comme nom de la classe. Remplace la valeur java.lang.Object par le mot AnimalFamilier dans le champ Superclasse.
Noublions pas cependant que nous sommes en train de crer une sousclasse dAnimalFamilier pour ajouter certaines proprits que seuls les poissons possdent et rutiliser une partie du code que nous avons crit pour un animal familier en gnral.
Il est temps de te rvler un secret toutes les classes Java hritent de la super superclasse Object, que tu utilises le mot extends ou pas. Mais une classe Java ne peut pas avoir deux parents distincts. Si ctait la mme chose avec les gens, les enfants ne seraient pas des sous-classes de leurs parents, mais tous les garons seraient des descendants dAdam et toutes les filles des descendantes dEve .
49
Tous les animaux ne sont pas capables de plonger, mais il est certain que les poissons le peuvent. Ajoutons maintenant une nouvelle mthode plonger() la classe Poisson.
public class Poisson extends AnimalFamilier { int profondeurCourante = 0; public int plonger(int combienDePlus){ profondeurCourante = profondeurCourante + combienDePlus; System.out.println("Plonge de " + combienDePlus + " mtres"); System.out.println("Je suis " + profondeurCourante + " mtres sous le niveau de la mer"); return profondeurCourante; }
La mthode plonger() a un argument combienDePlus qui indique au poisson de combien il doit plonger. Nous avons aussi dclar la variable de classe profondeurCourante qui enregistrera la nouvelle profondeur courante chaque fois que tu appelleras la mthode plonger(). Cette mthode renvoie la valeur courante de la variable profondeurCourante la classe appelante. Cre maintenant une autre classe nomme MatrePoisson qui ressemble ceci :
public class MatrePoisson { public static void main(String[] args) { Poisson monPoisson = new Poisson(); monPoisson.plonger(2); monPoisson.plonger(3); monPoisson.dormir(); } }
La mthode main() instancie lobjet Poisson et appelle sa mthode plonger() deux fois, avec des arguments diffrents. Ensuite, elle appelle la mthode dormir(). Quand tu excutes le programme MatrePoisson, il affiche les messages suivants :
Plonge Je suis Plonge Je suis de 2 mtres 2 mtres sous le niveau de la mer de 3 mtres 5 mtres sous le niveau de la mer
Programmation Java pour les enfants, les parents et les grands-parents Bonne nuit, demain
50
As-tu not que, outre la mthode dfinie dans la classe Poisson, le MatrePoisson appelle aussi des mthodes de sa superclasse AnimalFamilier ? Cest tout lintrt de lhritage tu nas pas besoin de copier et coller le code de la classe AnimalFamilier il suffit dutiliser le mot extends et la classe Poisson peut utiliser les mthodes dAnimalFamilier !
Encore une chose : bien que la mthode plonger() renvoie la valeur de profondeurCourante, notre MatrePoisson ne lutilise pas. Trs bien, notre MatrePoisson na pas besoin de cette valeur ; mais peuttre y a-t-il dautres classes qui utilisent Poisson, qui pourraient trouver cette valeur utile. Par exemple, imagine une classe ContrleurTraficPoissons qui doit connatre les positions des autres poissons dans la mer avant dautoriser un poisson plonger, pour viter les accidents .
Programmation Java pour les enfants, les parents et les grands-parents monPoisson.dire("Un poisson qui parle !");
51
Eh bien, notre poisson a commenc parler Pour viter que cela se produise, il faut que la classe Poisson surcharge (override) la mthode dire() de la classe AnimalFamilier. Voil comment a marche : si tu dclares une mthode avec exactement la mme signature dans la sous-classe que dans la superclasse, la mthode de la sous-classe sera utilise la place de celle de la superclasse. Ajoutons la mthode dire() la classe Poisson.
public String dire(String unMot) { return "Ne sais-tu pas que les poissons ne parlent pas ?"; }
Cela prouve que la mthode dire() de la classe AnimalFamilier a t surcharge, ou, autrement dit, supprime.
Si la signature dune mthode inclut le mot-cl final, elle ne peut pas tre surcharge. Par exemple:
final public void dormir(){}
Waouh ! Nous en avons appris, des choses, dans ce chapitre. Que dirais-tu dune petite pause ?
52
Autres lectures
1. Types de donnes Java :
http://java.sun.com/docs/books/tutorial/java/nutsandb olts/datatypes.html
2. Hritage :
http://java.sun.com/docs/books/tutorial/java/concepts/i nheritance.html
Exercices
1. Cre une nouvelle classe Voiture possdant les mthodes suivantes :
public void dmarrer() public void arrter() public int rouler(int dure)
La mthode rouler() doit renvoyer la distance totale parcourue par la voiture pendant un temps donn. Utilise la formule suivante pour calculer la distance :
distance = dure * 60;
2. Ecris une autre classe, PropritaireVoiture, qui cre une instance de lobjet Voiture et appelle ses mthodes. Le rsultat de chaque appel de mthode doit tre affich laide de System.out.println().
53
54
programme pour expliquer quoi servent une ligne, une mthode ou une classe particulire. Tout d'abord, il arrive qu'on oublie pourquoi on a crit un programme de cette faon. Ensuite, les commentaires aident les autres programmeurs comprendre ton code.
Commentaires de programme
Il y a trois types de commentaires diffrents : Si tes commentaires tiennent sur une ligne, commence-les par deux barres obliques (slashs) :
// Cette mthode calcule la distance
Les commentaires s'tendant sur plusieurs lignes doivent tre entours par les symboles /* et */, par exemple :
/* les 3 lignes suivantes enregistrent la position courante du Poisson. */
Java est fourni avec un programme spcial, javadoc, qui peut extraire certains des commentaires de tes programmes dans un fichier d'aide spar. Ce fichier peut tre utilis comme documentation technique de tes programmes. Ces commentaires sont entours par les symboles /** et */. Seuls les commentaires les plus importants, comme la description d'une classe ou d'une mthode, devraient tre reprs ainsi.
/** Cette mthode calcule la remise en fonction du prix. Si le prix est suprieur 100 , la remise est de 20%, sinon, elle est seulement de 10%. */
A partir de maintenant, j'ajouterai des commentaires aux exemples de code pour que tu comprennes mieux comment et o les utiliser.
55
56
Modifions la mthode plonger() de la classe Poisson pour que notre poisson ne puisse pas plonger plus profond que 100 mtres :
public class Poisson extends AnimalFamilier { int profondeurCourante = 0; public int plonger(int combienDePlus) { profondeurCourante = profondeurCourante + combienDePlus; if (profondeurCourante > 100) { System.out.println("Je suis un petit " + " poisson et je ne peux pas plonger" + " plus profond que 100 mtres"); profondeurCourante = profondeurCourante - combienDePlus; } else { System.out.println("Plonge de " + combienDePlus + " mtres"); System.out.println("Je suis " + profondeurCourante + " mtres sous le niveau de la mer"); } return profondeurCourante; } public String dire(String unMot) { return "Ne sais-tu pas que les poissons ne" + " parlent pas ?"; }
Effectuons ensuite une petite modification de MatrePoisson laissons-le essayer de faire plonger notre poisson trs profond :
public class MatrePoisson { public static void main(String[] args) { Poisson monPoisson = new Poisson(); // Essayons de plonger plus profond que 100 mtres monPoisson.plonger(2); monPoisson.plonger(97); monPoisson.plonger(3); monPoisson.dormir(); } }
57
Oprateurs logiques
Parfois, pour prendre une dcision, il peut tre ncessaire de vrifier plus d'une expression conditionnelle. Par exemple, si le nom d'un tat est "Texas" ou "Californie", ajouter la taxe d'tat au prix de chaque article du magasin. C'est un cas d'emploi du ou logique (logical or ) soit "Texas" soit "Californie". En Java, un ou logique est reprsent par une ou deux barres verticales. Ca fonctionne comme ceci : si l'une quelconque des conditions est vraie, le rsultat de l'expression dans son ensemble vaut true. Dans les exemples suivants, j'utilise une variable de type String. Cette classe Java possde une mthode equals() que j'utilise pour comparer la valeur de la variable tat avec "Texas" ou "Californie" :
if (tat.equals("Texas") | tat.equals("Californie"))
La diffrence entre les deux est que, si tu utilises deux barres et que la premire expression est vraie, la seconde expression ne sera mme pas value. Si tu ne mets qu'une seule barre, Java value les deux expressions. Le et logique (logical and) est reprsent par un ou deux "et commercial" (&&) et l'expression dans son ensemble vaut true si chacune de ses parties vaut true. Par exemple, imputer les taxes commerciales uniquement dans le cas o l'tat est "New York" et o le prix est suprieur 110. Les deux conditions doivent tre vraies en mme temps :
if (tat.equals("New York") && prix > 110)
ou
if (tat.equals("New York") & prix > 110)
Si tu utilises un double "et commercial" et que la premire expression vaut false, la seconde ne sera mme pas value, car l'expression entire vaudra false de toutes faons. Avec un simple "et commercial", les deux expressions seront values. Le non logique (logical not) est reprsent par le point d'exclamation et donne l'expression le sens oppos. Par exemple, si tu veux effectuer certaines actions uniquement si l'tat n'est pas "New York", utilise cette syntaxe :
Programmation Java pour les enfants, les parents et les grands-parents if (!tat.equals("New York"))
58
Voici un autre exemple les deux expressions suivantes produiront le mme rsultat :
if (prix < 50) if (!(prix >= 50))
Oprateur conditionnel
Il existe une autre forme de la clause if : l'oprateur conditionnel. On l'utilise pour affecter une valeur une variable en fonction d'une expression termine par un point d'interrogation. Si l'expression est vraie, la valeur suivant le point d'interrogation est utilise ; sinon, la valeur suivant les deux points est affecte la variable situe gauche du signe gal :
remise = prix > 50 ? 10 : 5;
Si le prix est suprieur 50, la variable remise prend la valeur 10 ; sinon, elle vaut 5. C'est juste un raccourci pour exprimer une clause if normale :
if (prix > 50) { remise = 10; } else { remise = 5; }
Utilisation de else if
Tu peux construire des clauses if plus complexes avec plusieurs blocs else if. Nous allons maintenant crer la classe BulletinApprciation. Cette classe doit avoir la mthode main() ainsi qu'une mthode acceptant un argument la note du devoir. En fonction du nombre, cette mthode affichera ton niveau sous la forme I (Insuffisant), P (Passable), A (Assez bien), B (Bien), T (Trs bien) ou E (Excellent). Nous la nommerons convertirNiveaux().
59
public class BulletinApprciation { /** Cette mthode attend un argument entier la note du devoir - et retourne une mention, I, P, A, B, T ou E, en fonction de sa valeur. */ public char convertirNiveaux(int noteDevoir) { char niveau; if (noteDevoir >= 18) { niveau = 'E'; } else if (noteDevoir >= 16 niveau = 'T'; } else if (noteDevoir >= 14 niveau = 'B'; } else if (noteDevoir >= 12 niveau = 'A'; } else if (noteDevoir >= 10 niveau = 'P'; } else { niveau = 'I'; } return niveau; } public static void main(String[] args) { BulletinApprciation convertisseur = new BulletinApprciation(); char tonNiveau = convertisseur.convertirNiveaux(17); System.out.println("Ton premier niveau est " + tonNiveau); tonNiveau = convertisseur.convertirNiveaux(15); System.out.println("Ton second niveau est " + tonNiveau);
&& noteDevoir < 18) { && noteDevoir < 16) { && noteDevoir < 14) { && noteDevoir < 12) {
Outre l'utilisation de la condition else if, cet exemple te montre aussi comment utiliser des variables de type char. Tu peux aussi voir que tu peux utiliser l'oprateur && pour vrifier si un nombre appartient une plage de valeurs donne. Tu ne peux pas crire simplement if rsultatTest entre 16 et 18, mais en Java nous crivons que rsultatTest doit tre la fois suprieur ou gal 16 et infrieur 18 :
rsultatTest >= 16 && rsultatTest < 18
60
Rflchis la raison pour laquelle nous ne pouvons pas utiliser l'oprateur || ici.
N'oublie pas le mot-cl break la fin de chaque cas il faut que le code saute hors de la clause switch. Sans les instructions break, ce code imprimerait, par exemple, les quatre dernires lignes si la variable tonNiveau avait la valeur 'B'. La clause switch Java a une limitation l'expression valuer doit tre de l'un de ces types : char int byte short
61
Voici un autre exemple : il y a en Java une classe Math qui contient plusieurs douzaines de mthodes mathmatiques telles que sqrt() (racine carre), sin(), abs() et autres. Toutes ces mthodes sont statiques et tu n'as pas besoin de crer une instance de la classe Math pour les appeler. Par exemple :
Programmation Java pour les enfants, les parents et les grands-parents double racineCarre = Math.sqrt(4.0);
62
Les parenthses aprs le mot Poisson signifient que cette classe a une mthode nomme Poisson(). Oui, il y a des mthodes spciales appeles constructeurs (constructors), qui ont les caractristiques suivantes :
Les constructeurs ne sont appels qu'une fois au cours de la construction d'un objet en mmoire. Ils doivent avoir le mme nom que la classe elle-mme. Ils ne retournent pas de valeur ; il n'est mme pas ncessaire d'utiliser le mot-cl void dans la signature d'un constructeur.
Toute classe peut avoir plusieurs constructeurs. Si tu ne cres pas de constructeur pour une classe, Java cre automatiquement, lors de la compilation, un constructeur sans argument par dfaut. C'est pour cela que le compilateur Java n'a jamais rclam une dclaration permettant d'crire new Poisson(), alors que la classe Poisson ne dfinit aucun constructeur. En gnral, les constructeurs sont utiliss pour affecter des valeurs initiales aux variables membres d'une classe. Par exemple, la version suivante de la classe Poisson a un constructeur mono-argument qui se contente d'affecter la valeur de l'argument la variable d'instance profondeurCourante pour une utilisation ultrieure.
public class Poisson extends AnimalFamilier { int profondeurCourante; Poisson(int positionDpart) { profondeurCourante = positionDpart; }
Maintenant, la classe MatrePoisson peut crer une instance de Poisson et affecter la position initiale du poisson. L'exemple suivant cre une instance de Poisson "submerge" sous 20 mtres d'eau :
Poisson monPoisson = new Poisson(20);
63
Si un constructeur avec arguments est dfini dans une classe, il n'est plus possible d'utiliser le constructeur sans argument par dfaut. Si tu souhaites avoir un constructeur sans argument, cris-en un.
Le mot-cl this
Le mot-cl this est utile lorsque tu as besoin de te rfrer l'instance de l'objet dans laquelle tu te trouves. Regarde cet exemple :
class Poisson { int profondeurCourante ; Poisson(int profondeurCourante) { this.profondeurCourante = profondeurCourante; } }
Le mot-cl this permet d'viter les conflits de nom. Par exemple, this.profondeurCourante fait rfrence la variable membre profondeurCourante, alors que profondeurCourante fait rfrence la valeur de l'argument. En d'autres termes, l'instance de l'objet Poisson pointe sur ellemme. Tu verras un autre exemple important de l'utilisation du mot-cl this au Chapitre 6, dans la section Comment passer des donnes entre classes.
Tableaux
Disons que ton programme doit stocker les noms de quatre joueurs. Au lieu de dclarer quatre variables de type String, tu peux dclarer un tableau (array) qui a quatre lments de type String. Les tableaux sont reprs par des crochets, placs soit aprs le nom de la variable, soit aprs le type de donnes :
String [] joueurs;
ou
Programmation Java pour les enfants, les parents et les grands-parents String joueurs[];
64
Ces lignes indiquent juste au compilateur Java que tu as l'intention de stocker plusieurs chanes de caractres dans le tableau joueurs. Chaque lment possde son propre indice partant de zro. L'exemple suivant cre en fait une instance de tableau qui peut stocker quatre lments de type String puis leur affecte des valeurs :
joueurs = new String [4]; joueurs[0] joueurs[1] joueurs[2] joueurs[3] = = = = "David"; "Daniel"; "Anna"; "Gregory";
Tu dois connatre la taille du tableau avant d'affecter des valeurs ses lments. Si tu ne sais pas l'avance combien d'lments tu vas avoir, tu ne peux pas utiliser de tableaux ; tu devrais examiner d'autres classes Java, par exemple Vector (vecteur). Mais concentrons-nous pour l'instant sur nos tableaux. Tous les tableaux ont un attribut nomm length (longueur) qui se "rappelle" le nombre d'lments de ce tableau. Tu peux donc toujours savoir combien d'lments il y a :
int nombreJoueurs = joueurs.length;
Si tu connais toutes les valeurs qui seront stockes dans le tableau au moment o tu le dclares, Java te permet de dclarer et d'initialiser le tableau d'un seul coup :
String [] joueurs = {"David", "Daniel", "Anna", "Gregory"};
Imagine que le second joueur soit un gagnant et que tu souhaites lui faire part de tes flicitations. Si le nom des joueurs est stock dans un tableau, nous avons besoin de son deuxime lment :
65
Sais-tu pourquoi le deuxime lment a l'indice [1] ? Bien sr que tu le sais : l'indice du premier lment est toujours [0]. Le tableau de joueurs de notre exemple est unidimensionnel, car nous les stockons en quelque sorte en ligne. Si nous voulons stocker les valeurs sous forme de matrice, nous pouvons crer un tableau bidimensionnel. Java permet la cration de tableaux multidimensionnels. Tu peux stocker n'importe quel objet dans un tableau ; je te montrerai comment au Chapitre 10.
Java excute chaque ligne entre les accolades puis retourne la premire ligne de la boucle, pour incrmenter le compteur et valuer l'expression conditionnelle. Ce code signifie ceci : Affiche la valeur de l'lment du tableau dont l'indice est identique la valeur courante du compteur. Commence de l'lment 0 (compteur = 0) et incrmente de 1 la valeur du compteur (compteur++). Continue faire ainsi tant que le compteur est infrieur nombreJoueurs (compteur < nombreJoueurs). Il y a un autre mot-cl permettant d'crire des boucles - while (pendant). Avec ces boucles, il n'est pas ncessaire de savoir exactement combien de fois l'action doit tre rpte, mais il faut tout de mme savoir quel moment terminer la boucle. Voyons comment
66
nous pouvons fliciter les joueurs en utilisant une boucle while qui se terminera lorsque la valeur de la variable compteur sera gale la valeur de nombreJoueurs :
int nombreJoueurs = joueurs.length; int compteur = 0; while (compteur < nombreJoueurs) { String leJoueur = joueurs[compteur]; System.out.println("Flicitations, " + leJoueur + " !"); compteur++; }
Au Chapitre 9, tu apprendras comment enregistrer les donnes sur les disques et comment les recharger dans la mmoire de l'ordinateur. Si tu charges les scores du jeu partir d'un fichier sur le disque, tu ne sais pas l'avance combien de scores y ont t enregistrs. Il est fort probable que tu chargeras les scores l'aide d'une boucle while. Tu peux aussi utiliser deux mots-cls importants dans les boucles : break et continue. Le mot-cl break est utilis pour sortir de la boucle quand une condition particulire est vraie. Disons que nous ne voulons pas afficher plus de 3 flicitations, indpendamment du nombre de joueurs que nous avons. Dans l'exemple suivant, aprs avoir affich les lments 0, 1 et 2 du tableau, le break fera sortir le code de la boucle et le programme continuera partir de la ligne suivant l'accolade fermante. Dans cet exemple de code, il y a un double signe gale dans la clause if. Cela signifie que tu compares la valeur de la variable compteur avec le nombre 3. Un seul signe gale cet endroit signifierait qu'on affecte la valeur 3 la variable compteur. Remplacer == par = dans une instruction if est un pige trs subtil, qui peut mener des erreurs du programme imprvisibles et difficiles trouver.
67
int compteur = 0; while (compteur < nombreJoueurs) { if (compteur == 3) { break; // Sortie de la boucle } String leJoueur = joueurs[compteur]; System.out.println("Flicitations, " + leJoueur + " !"); compteur++; }
Le mot-cl continue permet au code de sauter des lignes et de revenir au dbut de la boucle. Imagine que tu veuilles fliciter tout le monde sauf David le mot-cl continue fait revenir le programme au dbut de la boucle :
while (compteur < nombreJoueurs) { compteur++; String leJoueur = joueurs[compteur]; if (leJoueur.equals("David")) { continue; } System.out.println("Flicitations, " + leJoueur + " !");
Il y a encore une autre forme de la boucle while, qui commence par le mot-cl do :
do { // Place ton code cet endroit } while (compteur < nombreJoueurs);
Une telle boucle value l'expression aprs avoir excut le code entre les accolades, ce qui signifie que le code l'intrieur de la boucle est excut au moins une fois. Les boucles qui commencent par le mot-cl while peuvent ne pas tre excutes du tout si l'expression conditionnelle est fausse ds le dbut.
68
Autres lectures
1. jGuru: Language Essentials. Short Course:5
http://java.sun.com/developer/onlineTraining/JavaIntro/conten ts.html
Exercices
1. Cre une nouvelle classe nomme ConvertisseurTempratures dont une mthode a la signature suivante :
public String convertirTemprature (int temprature, char convertirEn)
Si la valeur de l'argument convertirEn est F, la temprature doit tre convertie en degrs Fahrenheit ; si c'est C, en degrs Celsius. Quand tu appelles cette mthode, mets la valeur de l'argument de type char entre apostrophes. 2. Essaie de dclarer la mthode convertirNiveaux() de la classe BulletinApprciation comme static et supprime de la mthode main() la ligne qui instancie cette classe.
NDT : Ce document propose, en anglais, une prsentation des bases du langage et un cours d'introduction.
69
70
ava est fourni avec un tas de classes dont tu vas te servir pour
crer des applications graphiques. Il y a deux groupes principaux de classes (librairies) utilises pour crer des fentres en Java : AWT et Swing.
AWT et Swing
Lorsque Java fut cr, seule la librairie AWT tait disponible pour travailler avec du graphique. Cette librairie est un simple ensemble de classes telles que Button (bouton), TextField (champ textuel), Label (libell) et autres. Peu aprs, une autre librairie, plus volue, apparut : Swing. Elle inclut aussi les boutons, les champs textuels et d'autres contrles. Le nom des composants Swing commence par la lettre J, par exemple JButton, JTextField, JLabel, etc. Tout est un peu mieux, plus rapide et plus simple d'utilisation avec Swing, mais dans certains cas, nos programmes sont excuts sur des ordinateurs avec d'anciennes versions de Java qui peuvent ne pas supporter les classes Swing. Tu verras des exemples d'utilisation de AWT plus tard, au Chapitre 7, mais dans le prsent chapitre nous allons crer une calculatrice utilisant Swing. Il existe un autre ensemble de classes graphiques, une partie de la plate-forme Eclipse appele Standard Widget Toolkit (SWT), mais nous ne l'utiliserons pas dans ce livre.
71
responsables du dessin, d'autres des classes permettant de travailler avec Internet et ainsi de suite. Par exemple, la classe String fait partie du paquetage java.lang et le nom complet de la classe String est java.lang.String. Le compilateur Java sait o trouver les classes de java.lang, mais il y a beaucoup d'autres paquetages contenant des classes utiles et c'est toi de dire au compilateur o se trouvent les classes de ton programme. Par exemple, la plupart des classes Swing se trouvent dans l'un de ces deux paquetages :
javax.swing javax.swing.event
Ce serait ennuyeux de devoir crire le nom complet d'une classe chaque fois qu'on l'utilise. Pour viter cela, on peut effectuer une bonne fois des dclarations import (importer) avant la ligne de dclaration de la classe. Par exemple :
import javax.swing.JFrame; import javax.swing.JButton; class Calculatrice { JButton monBouton = new JButton(); JFrame monCadre = new JFrame(); }
Ces dclarations import permettent d'utiliser ensuite les noms courts des classes, comme JFrame ou JButton. Le compilateur Java saura o chercher ces classes. Si tu as besoin de plusieurs classes d'un mme paquetage, tu n'as pas besoin d'en crire la liste dans la dclaration import. Utilise simplement le caractre joker (wildcard). Dans l'exemple suivant, l'toile (astrisque) rend toutes les classes du paquetage javax.swing visibles de ton programme :
import javax.swing.*;
Cependant, il est prfrable d'utiliser des dclarations d'importation distinctes, afin de voir quelle classe exacte est importe de chaque paquetage. Nous en reparlerons plus avant au Chapitre 10.
72
Une fentre ou un cadre (frame) qui peut tre cr en utilisant la classe JFrame. Un panneau (panel) ou un carreau (pane) contenant tous les boutons, champs textuels, libells et autres composants. Les panneaux sont crs l'aide de la classe JPanel. Les contrles graphiques tels que les boutons (JButton), les champs textuels (JTextField), les listes (JList)... Les gestionnaires de disposition (layout managers) qui aident organiser tous ces boutons et champs dans un panneau.
Habituellement, un programme cre une instance de JPanel et lui affecte un gestionnaire de disposition. Ensuite, il peut crer des contrles graphiques et les ajouter au panneau. Enfin, il ajoute le panneau au cadre, fixe les dimensions du cadre et le rend visible.
Mais l'affichage du cadre n'est qu'une partie du travail, parce que les contrles graphiques doivent savoir comment rpondre divers vnements (events), tels qu'un clic sur un bouton. Dans ce chapitre, nous allons apprendre afficher des fentres agrables voir. Dans le chapitre suivant, nous verrons comment crire le code qui traite les vnements qui peuvent concerner les lments de cette fentre. Notre prochain objectif est la cration d'une calculatrice simple capable d'ajouter deux nombres et d'afficher le rsultat. Cre dans Eclipse le
73
import javax.swing.*; import java.awt.FlowLayout; public class CalculatriceSimple { public static void main(String[] args) { // Cre un panneau JPanel contenuFentre = new JPanel(); // Affecte un gestionnaire de disposition ce panneau FlowLayout disposition = new FlowLayout(); contenuFentre.setLayout(disposition); // Cre les contrles en mmoire JLabel label1 = new JLabel("Nombre 1 :"); JTextField entre1 = new JTextField(10); JLabel label2 = new JLabel("Nombre 2 :"); JTextField entre2 = new JTextField(10); JLabel label3 = new JLabel("Somme :"); JTextField rsultat = new JTextField(10); JButton lancer = new JButton("Ajouter"); // Ajoute les contrles au panneau contenuFentre.add(label1); contenuFentre.add(entre1); contenuFentre.add(label2); contenuFentre.add(entre2); contenuFentre.add(label3); contenuFentre.add(rsultat); contenuFentre.add(lancer); // Cre le cadre et y ajoute le panneau JFrame cadre = new JFrame("Ma premire calculatrice"); cadre.setContentPane(contenuFentre); // Positionne les dimensions et rend la fentre visible cadre.setSize(400,100); cadre.setVisible(true); } }
Ce n'est peut-tre pas la calculatrice la plus jolie, mais elle nous permettra d'apprendre comment ajouter des composants et afficher une fentre. Dans la section suivante, nous tcherons d'amliorer son apparence l'aide des gestionnaires de disposition.
74
Gestionnaires de disposition
Certains langages de programmation vieillots t'obligent rgler les coordonnes et tailles exactes de chaque composant de la fentre. Ca marche trs bien si tu connais les rglages de l'cran (sa rsolution) de chacune des personnes qui utiliseront ton programme. A propos, on appelle les personnes qui utilisent nos programmes des utilisateurs. Il y a dans Java des gestionnaires de disposition qui t'aident arranger les composants sur l'cran sans avoir affecter des positions prcises aux contrles graphiques. Les gestionnaires de disposition assurent que l'cran aura une bonne tte quelles que soient les dimensions de la fentre. Swing propose les gestionnaires de disposition suivants :
FlowLayout (prsentation en file) GridLayout (prsentation en grille) BoxLayout (prsentation en lignes ou colonnes) BorderLayout (prsentation avec bordures) CardLayout (prsentation en pile) GridBagLayout (prsentation en grille composite) SpringLayout (prsentation avec ressorts)
Pour utiliser un gestionnaire de disposition, un programme doit l'instancier puis affecter cet objet un conteneur (container), par exemple un panneau, comme dans la classe CalculatriceSimple.
FlowLayout
Dans cette prsentation, les composants sont disposs dans la fentre ligne par ligne. Par exemple, les libells, les champs textuels et les boutons sont ajouts la premire ligne imaginaire tant qu'il y reste de la place. Quand la ligne courante est pleine, on passe la ligne suivante. Si un utilisateur retaille la fentre, il risque de dsorganiser son apparence. Essaie simplement de retailler la fentre de notre calculatrice en tirant sur l'un de ses coins. Regarde comment le gestionnaire java.awt.FlowLayout rorganise les contrles lorsque les dimensions de la fentre varient.
75
Dans l'exemple de code suivant, le mot-cl this reprsente une instance de l'objet CalculatriceSimple.
FlowLayout disposition = new FlowLayout(); this.setLayoutManager(disposition);
Eh bien, FlowLayout n'est pas le meilleur choix pour notre calculatrice. Essayons quelque chose d'autre.
GridLayout
La classe java.awt.GridLayout te permet d'organiser les composants en lignes et en colonnes dans une grille. Tu vas ajouter les composants des cellules imaginaires de cette grille. Si les dimensions de l'cran sont modifies, les cellules de la grille peuvent changer de taille, mais les positions relatives des composants de la fentre ne changent pas. Notre calculatrice a sept composants trois libells, trois champs textuels et un bouton. Nous pouvons les organiser selon une grille de quatre lignes sur deux colonnes (il reste une cellule vide) :
GridLayout disposition = new GridLayout(4,2);
Tu peux aussi fixer un espace, horizontal ou vertical, entre les cellules, par exemple cinq pixels (les images sur l'cran de l'ordinateur sont constitues de minuscules points appels pixels).
GridLayout disposition = new GridLayout(4,2,5,5);
Aprs quelques modifications mineures (en surbrillance ci-dessous), notre calculatrice a une bien meilleure allure. Cre et compile la classe GrilleCalculatriceSimple dans le projet Ma Calculatrice.
Programmation Java pour les enfants, les parents et les grands-parents import javax.swing.*; import java.awt.GridLayout; public class GrilleCalculatriceSimple { public static void main(String[] args) { // Cre un panneau JPanel contenuFentre = new JPanel();
76
// Affecte un gestionnaire de prsentation ce panneau GridLayout disposition = new GridLayout(4,2); contenuFentre.setLayout(disposition); // Cre les contrles en mmoire JLabel label1 = new JLabel("Nombre 1 :"); JTextField entre1 = new JTextField(10); JLabel label2 = new JLabel("Nombre 2 :"); JTextField entre2 = new JTextField(10); JLabel label3 = new JLabel("Somme :"); JTextField rsultat = new JTextField(10); JButton lancer = new JButton("Ajouter"); // Ajoute les contrles au panneau contenuFentre.add(label1); contenuFentre.add(entre1); contenuFentre.add(label2); contenuFentre.add(entre2); contenuFentre.add(label3); contenuFentre.add(rsultat); contenuFentre.add(lancer); // Cre le cadre et y ajoute le panneau JFrame cadre = new JFrame("Ma premire calculatrice"); cadre.setContentPane(contenuFentre); // Affecte ses dimensions la fentre et la rend visible cadre.setSize(400,100); cadre.setVisible(true); } }
Essaie de retailler cette fentre les contrles grandissent avec la fentre, mais leurs positions relatives ne changent pas :
77
Il y a encore une chose retenir propos de la disposition en grille toutes les cellules de la grille ont la mme largeur et la mme hauteur.
BorderLayout
La classe java.awt.BorderLayout partage la fentre en cinq zones : South (sud), West (ouest), North (nord), East (est) et Center (centre). La rgion North est toujours en haut de la fentre, la rgion South en bas ; la rgion West est gauche et la rgion East droite. Par exemple, dans la calculatrice de la page suivante, le champ textuel qui affiche les nombres est situ dans la zone North. Voici comment crer une disposition BorderLayout et y placer un champ textuel :
BorderLayout disposition = new BorderLayout(); this.setLayoutManager(disposition); JTextField affichageTexte = new JTextField(20); this.add("North", affichageTexte);
Tu n'es pas oblig de mettre des contrles graphiques dans chacune des cinq zones. Si tu n'as besoin que des rgions North, Center, et South, la rgion Center sera plus large, car tu ne vas pas utiliser les rgions East et West. J'utiliserai un gestionnaire BorderLayout un peu plus tard dans la version suivante de notre calculatrice, Calculatrice.java.
78
Champ texte
Malheureusement, non, parce que les cellules de cette calculatrice sont de tailles diffrentes le champ textuel est plus large que les boutons, par exemple. Mais tu peux combiner les gestionnaires de disposition en utilisant des panneaux qui ont chacun leur propre gestionnaire de disposition. Pour combiner les gestionnaires de disposition dans notre nouvelle calculatrice, procdons comme suit : Affecte une disposition BorderLayout au panneau de contenu. Ajoute un JTextField la rgion North de l'cran pour afficher les nombres. Cre un panneau p1 avec la prsentation GridLayout, ajoute-lui 20 boutons et ajoute p1 la rgion Center du panneau de contenu. Cre un panneau p2 avec la prsentation GridLayout, ajoute-lui 4 boutons et ajoute p2 la rgion West du panneau de contenu. Commenons avec une version un peu plus simple de la calculatrice qui ressemblera ceci :
79
Cre la classe Calculatrice et excute le programme. Lis les commentaires dans l'exemple de code suivant pour comprendre comment a marche.
import javax.swing.*; import java.awt.GridLayout; import java.awt.BorderLayout; public class Calculatrice { // Dclaration de tous les composants de la calculatrice. JPanel contenuFentre; JTextField champAffichage; JButton bouton0; JButton bouton1; JButton bouton2; JButton bouton3; JButton bouton4; JButton bouton5; JButton bouton6; JButton bouton7; JButton bouton8; JButton bouton9; JButton boutonVirgule; JButton boutonEgale; JPanel panneauChiffres; // Le constructeur cre les composants en mmoire // et les ajoute au cadre en utilisant une combinaison // de Borderlayout et Gridlayout Calculatrice() { contenuFentre = new JPanel(); // Affecte un gestionnaire de prsentation ce panneau BorderLayout dispositionl = new BorderLayout(); contenuFentre.setLayout(dispositionl); // Cre le champ d'affichage et le positionne dans // la zone nord de la fentre champAffichage = new JTextField(30); contenuFentre.add("North", champAffichage); // Cre les boutons en utilisant le constructeur de // la classe JButton qui prend en paramtre le libell // du bouton bouton0 = new JButton("0"); bouton1 = new JButton("1"); bouton2 = new JButton("2"); bouton3 = new JButton("3"); bouton4 = new JButton("4"); bouton5 = new JButton("5"); bouton6 = new JButton("6"); bouton7 = new JButton("7"); bouton8 = new JButton("8"); bouton9 = new JButton("9"); boutonVirgule = new JButton(","); boutonEgale = new JButton("=");
80
// Cre le panneau avec le quadrillage qui contient // les 12 boutons les 10 boutons numriques et ceux // reprsentant la virgule et le signe gale panneauChiffres = new JPanel(); GridLayout disposition2 = new GridLayout(4, 3); panneauChiffres.setLayout(disposition2); // Ajoute les contrles au panneau panneauChiffres panneauChiffres.add(bouton1); panneauChiffres.add(bouton2); panneauChiffres.add(bouton3); panneauChiffres.add(bouton4); panneauChiffres.add(bouton5); panneauChiffres.add(bouton6); panneauChiffres.add(bouton7); panneauChiffres.add(bouton8); panneauChiffres.add(bouton9); panneauChiffres.add(bouton0); panneauChiffres.add(boutonVirgule); panneauChiffres.add(boutonEgale); // Ajoute panneauChiffres la zone centrale de la // fentre contenuFentre.add("Center", panneauChiffres); // Cre le cadre et lui affecte son contenu JFrame frame = new JFrame("Calculatrice"); frame.setContentPane(contenuFentre); // Affecte la fentre des dimensions suffisantes pour // prendre en compte tous les contrles frame.pack(); // Enfin, affiche la fentre frame.setVisible(true); } public static void main(String[] args) { Calculatrice calc = new Calculatrice(); }
BoxLayout
La classe javax.swing.BoxLayout permet de disposer de multiples composants soit horizontalement (selon l'axe des X) ou verticalement (selon l'axe des Y). Contrairement au gestionnaire FlowLayout, les contrles ne changent pas de ligne quand la fentre est retaille. Avec BoxLayout, les contrles peuvent avoir des tailles diffrentes (ce qui n'est pas possible avec GridLayout). Les deux lignes de code suivantes mettent en place une prsentation de type BoxLayout avec un alignement vertical dans un JPanel.
81
Pour rendre ce code plus compact, je ne dclare pas de variable pour stocker une rfrence l'objet BoxLayout ; je cre plutt une instance de cet objet et la passe immdiatement en argument la mthode setLayout().
GridBagLayout
Dans cette section, je vais encore te montrer un autre moyen de crer la fentre de la calculatrice en utilisant le gestionnaire java.awt.GridBagLayout au lieu de combiner des dispositions et des panneaux. Notre calculatrice a des lignes et des colonnes, mais dans une prsentation en grille tous les composants doivent avoir les mmes dimensions. Ca ne marche pas pour notre calculatrice cause du champ textuel, en haut, qui est aussi large que trois boutons numriques. La disposition GridBagLayout est une grille volue, qui permet d'avoir des cellules de tailles diffrentes. La classe GridBagLayout fonctionne en collaboration avec la classe GridBagConstraints (contraintes de la grille). Les contraintes ne sont rien d'autre que des attributs de la cellule, que tu dois positionner pour chaque cellule sparment. Toutes les contraintes d'une cellule doivent tre positionnes avant de placer un composant dans la cellule. Par exemple, l'un des attributs de contrainte est appel gridwidth. Il permet de rendre une cellule aussi large que plusieurs autres. Quand tu travailles avec une prsentation en grille composite, tu dois d'abord crer une instance de l'objet contrainte puis donner une valeur ses proprits. Une fois ceci fait, tu peux ajouter le composant la cellule dans ton conteneur.
82
x=0 y=2
L'exemple de code suivant est largement comment pour t'aider comprendre comment utiliser GridBagLayout.
83
// Positionne le GridBagLayout pour le contenu de la fentre GridBagLayout disposition = new GridBagLayout(); contenuFentre.setLayout(disposition); // Tu dois rpter ces lignes pour chaque composant // que tu souhaites ajouter au quadrillage // Cre une instance de GridBagConstraints GridBagConstraints contr = new GridBagConstraints(); // Affecte les contraintes du champ Affichage // coordonne contr.gridx = // coordonne contr.gridy = x dans le quadrillage 0; y dans le quadrillage 0;
// cette cellule a la mme hauteur que les autres contr.gridheight = 1; // cette cellule est 6 fois plus large que les autres contr.gridwidth = 6; // remplit tout l'espace dans la cellule contr.fill = GridBagConstraints.BOTH; // proportion d'espace horizontal occupe par ce composant contr.weightx = 1.0; // proportion d'espace vertical occupe par ce composant contr.weighty = 1.0; // position du composant dans la cellule contr.anchor = GridBagConstraints.CENTER; // Cre le champ textuel champAffichage = new JTextField(); // Affecte les contraintes ce champ disposition.setConstraints(champAffichage, contr); // Ajoute le champ la fentre contenuFentre.add(champAffichage);
CardLayout
Imagine une pile de cartes poses les unes sur les autres, de telle sorte qu'on ne puisse voir compltement que la carte du dessus. Le gestionnaire java.awt.CardLayout permet de crer un composant qui ressemble un classeur onglets.
84
Quand tu cliques sur un onglet, le contenu de l'cran change. En fait, tous les panneaux ncessaires cet cran dont dj prchargs et se trouvent les uns au-dessus des autres. Quand l'utilisateur clique sur un onglet, le programme se contente de "mettre cette carte" au-dessus et rend les autres cartes invisibles. Il y a peu de chances que tu utilises cette disposition car la librairie Swing comporte un meilleur composant pour les fentres onglet. Il s'agit du composant JTabbedPane.
SpringLayout
Le gestionnaire de disposition ressorts est inspir de vritables ressorts et tringles. Imagine que tu aies un paquet de crochets, ressorts et tringles et que tu doives fixer nos boutons et champs textuels aux bordures de la fentre. Les composants attachs par des tringles ne peuvent pas bouger et changeront de taille si tu agrandis la fentre, mais ceux attachs par des ressorts pourront s'carter du bord. Les carts entre composants sont dfinis par les proprits des ressorts (minimum, maximum, taille prfre et taille relle). Ces paramtres sont spcifis dans l'instance de SpringLayout.Constraints associe chaque composant. C'est un peu comme pour le GridBagLayout. Au contraire du GridLayout, le SpringLayout te permet de grer la disposition de composants de tailles diffrentes, tout en maintenant leurs positions relatives. Tu peux en lire davantage sur ce gestionnaire de disposition dans un article en ligne de Joe Winchester : "SpringLayout: A Powerful and Extensible Layout Manager" (http://jdj.sys-con.com/read/37300.htm).
Programmation Java pour les enfants, les parents et les grands-parents contenuFentre.setLayout(null);
85
Mais si tu fais ceci, ton code doit affecter les coordonnes du coin suprieur gauche, la largeur et la hauteur de chaque composant de la fentre. Cet exemple montre comment tu peux donner un bouton une largeur de 40 pixels, une hauteur de 20 pixels et le placer 100 pixels droite et 200 pixels au-dessous du coin suprieur gauche de la fentre :
JButton monBouton = new JButton("Nouvelle partie"); monBouton.setBounds(100, 200, 40, 20);
Tu peux aussi crer des menus (JMenu et JPopupMenu), des fentres la demande (popup), des cadres imbriqus dans d'autres cadres (JInternalFrame) et utiliser les fentres standard de manipulation d'informations : JFileChooser (choix de fichier), JColorChooser (choix de couleur) et JOptionPane (choix d'option).
86
Java est accompagn d'une excellente application de dmonstration qui prsente tous les composants Swing disponibles en action. Elle se trouve dans le rpertoire demo\jfc\SwingSet2 du rpertoire d'installation de J2SDK. Ouvre simplement le fichier SwingSet2.html, et tu verras un cran similaire celui-ci :
Clique sur une image de la barre d'outils pour voir comment le composant Swing correspondant fonctionne. Tu peux aussi consulter le code utilis pour crer chaque fentre en slectionnant l'onglet Source Code. Par exemple, si tu cliques sur la quatrime icne partir de la gauche (nomme combobox), tu obtiendras une fentre comme celle-ci :
87
Il y a tant de diffrents composants Swing permettant de rendre tes fentres agrables voir ! Dans ce chapitre, nous avons cr des composants Swing simplement en tapant le code, sans utiliser d'outils particuliers. Mais il existe des outils permettant de slectionner un composant depuis une barre d'outils et de le dposer sur la fentre. Ces outils gnrent automatiquement le bon code Java pour les composants Swing. L'un des ces outils gratuits de conception d'interface utilisateur graphique (Graphic User Interface ou GUI), permettant de crer facilement des composants Swing et SWT, est jigloo, dit par CloudGarden. Tu trouveras la rfrence de la page web de ce produit dans la section Autres lectures. Dans le chapitre suivant, tu apprendras comment une fentre peut ragir aux actions de l'utilisateur.
88
Autres lectures
1.Didacticiel Swing :
http://java.sun.com/docs/books/tutorial/uiswing/
2. Classe JFormattedTextField :
http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JFormatte dTextField.html
Exercices
1. Modifie la classe Calculatrice.java en lui ajoutant les boutons +, -, / et *. Ajoute ces boutons au panneau panneauOprations et place celui-ci dans la rgion est du panneau contenu de la fentre. 2. Va lire sur le web les informations concernant JFormattedTextField et modifie le code de la calculatrice en utilisant cette classe la place de JTextField. L'objectif est de crer un champ align droite comme dans les vraies calculatrices.
89
par une boucle qui cre les boutons et les stocke dans le tableau. Suggestion : jette un il au code du jeu de morpion au Chapitre 7.
90
divers vnements : un utilisateur clique sur un bouton dans une fentre, le navigateur web dcide de repeindre la fentre, etc. Je suis sr que tu as essay de cliquer sur les boutons de notre calculatrice du Chapitre 5, mais ces boutons n'taient pas encore prts ragir tes actions. Chaque composant d'une fentre peut traiter un certain nombre d'vnements ou, comme on dit, tre l'coute (listen) de ces vnements, et, son tour, mettre des vnements, possiblement diffrents de ceux qu'il a reu. Pour ragir aux actions de l'utilisateur, ton programme doit s'enregistrer auprs des composants de la fentre au moyen de classes Java appeles rcepteurs (listeners). Il vaut mieux que ton programme ne reoive que les vnements qui l'intressent. Par exemple, quand une personne dplace le pointeur de la souris audessus d'un bouton de la calculatrice : peu importe l'endroit exact o se trouve la souris quand la personne appuie sur le bouton ; ce qui compte, c'est que c'est l'intrieur de la surface du bouton, et que ton programme sache que le bouton a t cliqu. C'est pourquoi tu n'as pas besoin d'enregistrer ton programme auprs du bouton en tant que MouseMotionListener, qui est le rcepteur traitant les dplacements de la souris. Par contre, ce rcepteur est bien utile pour toutes sortes de programmes de dessin. Ton programme devrait s'enregistrer auprs des boutons de la calculatrice en tant que rcepteur ActionListener, qui peut traiter les clics sur un bouton. Tous les rcepteurs sont des classes Java spciales appeles interfaces.
91
Interfaces
La plupart des classes dfinissent des mthodes qui effectuent diverses actions, par exemple ragir aux clics sur les boutons, ragir aux mouvements de la souris, etc. La combinaison de telles actions est appele le comportement de la classe (class behavior). Les interfaces sont des classes spciales qui donnent juste des noms un ensemble d'actions particulires sans crire le code rel qui implanterait ces actions. Par exemple :
interface MouseMotionListener { void mouseDragged(MouseEvent vnement); void mouseMoved(MouseEvent vnement); }
Comme tu vois, les mthodes mouseDragged() et mouseMoved() ne contiennent pas de code elles sont juste dclares dans l'interface MouseMotionListener. Mais si ta classe a besoin de ragir quand la souris est dplace ou qu'elle fait glisser un objet, elle doit implanter6 (to implement) cette interface. Le terme implanter signifie que cette classe va inclure pour de bon les mthodes dclares dans l'interface, par exemple :
NDT on rencontre frquemment aussi le terme implmenter, mais implanter est la recommandation officielle.
92
import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; class monBlocADessin implements MouseMotionListener { // Insre ici ton code capable de dessiner public void mouseDragged(MouseEvent vnement) { // Insre ici le code excuter quand un "glisser" // est effectu avec la souris } public void mouseMoved(MouseEvent vnement) { // Insre ici le code excuter quand la souris est // dplace } }
Tu te demandes peut-tre quoi bon prendre la peine de crer des interfaces sans mme y crire le code ? C'est pour la bonne raison que, une fois que cette interface est cre, elle peut tre rutilise par de nombreuses classes. Par exemple, quand d'autres classes (ou Java luimme) voient que la classe monBlocADessin implante l'interface MouseMotionListener, elles sont certaines que cette classe dfinit les mthodes mouseDragged() et mouseMoved(). Chaque fois qu'un utilisateur dplace la souris, Java appelle la mthode mouseMoved()et excute le code que tu y a crit. Imagine ce qui se passerait si un programmeur John dcidait de nommer une telle mthode mouseMoved(), mais que Marie la nommait mouvementSouris() et Pierre prfrait sourisDplace() ? Java serait embrouill et ne saurait pas quelle mthode de ta classe appeler pour lui signaler le dplacement de la souris. Une classe Java peut implanter plusieurs interfaces. Par exemple, elle peut avoir besoin de traiter les dplacements de la souris et le clic sur un bouton :
class MonProgrammeDeDessin implements MouseMotionListener, ActionListener { // Tu dois crire ici le code de toutes les mthodes // dfinies par les deux interfaces }
Une fois l'aise avec les interfaces fournies avec Java, tu seras mme de crer tes propres interfaces, mais il s'agit d'un sujet avanc. N'en parlons mme pas pour l'instant.
93
Rcepteur d'vnements
Revenons notre calculatrice. Si tu as fait tes devoirs du prcdent chapitre, la partie visuelle est termine. Nous allons maintenant crer une autre classe, un rcepteur qui effectuera certaines actions quand l'utilisateur cliquera sur l'un des boutons. En ralit, nous aurions pu ajouter le code traitant les vnements clic la classe Calculatrice.java, mais les bons programmeurs mettent toujours les parties affichage et traitement dans des classes distinctes. Nous allons appeler la deuxime classe MoteurCalcul. Elle doit implanter l'interface java.awt.ActionListener qui ne dclare qu'une mthode - actionPerformed(ActionEvent). Java appelle cette mthode de la classe qui implmente l'interface chaque fois qu'une personne clique sur un bouton. Cre s'il te plat cette classe simple :
import java.awt.event.ActionListener; public class MoteurCalcul implements ActionListener { }
Si tu essaies de compiler cette classe (ou simplement de l'enregistrer dans Eclipse), tu obtiens un message d'erreur disant que cette classe doit implanter la mthode actionPerformed(ActionEvent vnement). Corrigeons cette erreur :
import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class MoteurCalcul implements ActionListener { public void actionPerformed(ActionEvent vnement) { // On peut laisser ici une mthode vide, mme s'il // ne se produira rien quand Java l'appellera }
La version suivante de cette classe affiche une bote de message (message box) depuis la mthode actionPerformed(). Tu peux afficher n'importe quel message en utilisant la classe JOptionPane et sa mthode showConfirmDialog(). Par exemple, la classe MoteurCalcul affiche cette bote de message :
94
Il y a diffrentes version de la mthode showConfirmDialog(). Nous allons utiliser celle qui prend quatre arguments. Dans le code cidessous, le mot-cl null signifie que cette bote de message n'a pas de fentre mre, le deuxime argument contient le message, le troisime le titre de la bote de message et le quatrime te permet de choisir le(s) bouton(s) inclure dans la bote (PLAIN_MESSAGE signifie que seul un bouton OK est affich).
public void actionPerformed(ActionEvent vnement) { JOptionPane.showConfirmDialog(null, "Quelque chose s'est produit...", "Juste un test", JOptionPane.PLAIN_MESSAGE); }
Dans la prochaine section, je t'expliquerai comment compiler et excuter une nouvelle version de notre calculatrice, qui affichera la bote de message "Quelque chose s'est produit".
Dsormais, chaque fois qu'un utilisateur cliquera sur bouton0, Java appellera la mthode actionPerformed() de l'objet MoteurCalcul.
95
Maintenant, compile et excute la classe Calculatrice. Clique sur le bouton zro ton programme affiche la bote de message "Quelque chose s'est produit" ! Les autres boutons restent inactifs car ils ne connaissent pas encore notre rcepteur d'actions. Continue ajouter des lignes semblables pour donner vie tous les boutons :
bouton1.addActionListener(moteurCalcul); bouton2.addActionListener(moteurCalcul); bouton3.addActionListener(moteurCalcul); bouton4.addActionListener(moteurCalcul);
Nous dclarons une variable de type JButton la gauche du signe gale et, bien que la mthode getSource() retourne des donnes du type Object, nous disons Java : Ne t'inquite pas, je suis certain d'obtenir une instance de JButton.
96
C'est seulement aprs avoir effectu la conversion d'Object en JButton que nous avons le droit d'appeler la mthode getText() dfinie par la classe JButton.
import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JOptionPane; import javax.swing.JButton; public class MoteurCalcul implements ActionListener { public void actionPerformed(ActionEvent vnement) { // Retrouve la source de l'action JButton boutonCliqu = (JButton) vnement.getSource(); // Retrouve le libell du bouton String libellBoutonCliqu = boutonCliqu.getText(); // Concatne le libell du bouton au texte // de la bote de message JOptionPane.showConfirmDialog(null, "Tu as appuy sur " + libellBoutonCliqu, "Juste un test", JOptionPane.PLAIN_MESSAGE); } }
Maintenant, si tu appuies par exemple sur le bouton cinq, tu obtiendras la bote de message suivante :
Mais que faire si les vnements d'une fentre proviennent non seulement des boutons, mais aussi d'autres composants ? Nous ne
97
voulons pas convertir n'importe quel objet en JButton ! Pour traiter ces cas, tu dois utiliser l'oprateur Java spcial instanceof pour effectuer la conversion de type approprie. L'exemple suivant vrifie d'abord quel type d'objet est l'origine de l'vnement, puis effectue une conversion de type, soit en JButton soit en JTextField :
public void actionPerformed(ActionEvent vnement) { JTextField monChampAffichage = null; JButton boutonCliqu = null; Object sourceEvnement = vnement.getSource(); if (sourceEvnement instanceof JButton) { boutonCliqu = (JButton) sourceEvnement; } else if (sourceEvnement instanceof JTextField) { monChampAffichage = (JTextField) sourceEvnement; }
Notre calculatrice doit excuter diffrentes portions de code pour les diffrents boutons. Le fragment de code suivant montre comment faire.
public void actionPerformed(ActionEvent vnement) { Object source = vnement.getSource(); if (source == boutonPlus) { // Insre ici le code qui ajoute deux nombres } else if (source == boutonMoins) { // Insre ici le code qui soustrait deux nombres } else if (source == boutonDiviser) { // Insre ici le code qui divise deux nombres } else if (source == boutonMultiplier) { // Insre ici le code qui multiplie deux nombres } }
98
Nous allons dclarer un constructeur dans la prochaine version de la classe MoteurCalcul. Ce constructeur a un argument de type Calculatrice. Ne sois pas tonn, les types des arguments de mthodes peuvent tre des classes que tu as toi-mme cres ! Java excute le constructeur de l'instance de MoteurCalcul au cours de sa cration en mmoire. La classe Calculatrice instancie le MoteurCalcul et passe au constructeur du moteur une rfrence elle-mme :
MoteurCalcul moteurCalcul = new MoteurCalcul(this);
Cette rfrence contient l'adresse de la calculatrice en mmoire. Le constructeur du moteur stocke cette valeur dans la variable membre parent et enfin l'utilise dans la mthode actionPerformed() pour accder au champ textuel de la calculatrice.
parent.champAffichage.getText();
parent.champAffichage.setText(textChampAffichage + libellBoutonCliqu);
99
Quand tu dclares une variable pour stocker une rfrence l'instance d'une classe particulire, cette variable doit tre du type de cette classe ou de l'une de ses superclasses. En Java, chaque classe hrite de la classe Object. Si la classe Poisson est une sous-classe de AnimalFamilier, toutes ces lignes sont correctes : Poisson monPoisson = new Poisson(); AnimalFamilier monPoisson = new Poisson(); Object monPoisson = new Poisson();
Fin de la calculatrice
Intressons-nous quelques rgles (un algorithme) concernant la faon dont notre calculatrice doit fonctionner : 1. L'utilisateur entre tous les chiffres du premier nombre. 2. Si l'utilisateur tape l'un des boutons d'action +, -, / ou *, alors stocker le premier nombre et l'action slectionne dans des variables membres, puis effacer le nombre du champ textuel. 3. L'utilisateur entre un deuxime nombre et appuie sur le bouton gale. 4. Convertir la valeur de type String du champ textuel dans le type numrique double pour pouvoir stocker de grands nombres dcimaux. Excuter l'action slectionne en utilisant cette valeur et le nombre stock dans la variable l'tape 2. 5. Afficher le rsultat de l'tape 4 dans le champ textuel et stocker cette valeur dans la variable utilise l'tape 2. Nous allons programmer toutes ces actions dans la classe MoteurCalcul. En lisant le code ci-dessous, rappelle-toi que la mthode actionPerformed() est appele aprs chaque clic sur un bouton et qu'entre ces appels de mthode les donnes sont stockes dans les variables actionSlectionne et rsultatCourant.
100
import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.text.NumberFormat; import java.text.ParsePosition; import javax.swing.JButton; public class MoteurCalcul implements ActionListener { Calculatrice parent; // une rfrence la Calculatrice char actionSlectionne = ' '; // +, -, /, ou * double rsultatCourant = 0; NumberFormat formatNombres = NumberFormat.getInstance(); // un objet capable de lire et prsenter les nombres // Le constructeur stocke la rfrence la fentre // Calculatrice dans la variable membre parent MoteurCalcul(Calculatrice parent) { this.parent = parent; } public void actionPerformed(ActionEvent vnement) { // Retrouve la source de l'action JButton boutonCliqu = (JButton) vnement.getSource(); String texteChampAffichage = parent.champAffichage.getText(); double valeurAffiche = 0; // Retrouve le nombre prsent dans le champ texte // s'il n'est pas vide if (!"".equals(texteChampAffichage)) { valeurAffiche = // analyse la chane de caractres formatNombres.parse( texteChampAffichage, new ParsePosition(0) /* ne sert pas */). // puis donne sa valeur en tant que double doubleValue(); } Object sourceEvnement = vnement.getSource(); // // // // Pour chaque bouton d'action, mmorise l'action slectionne, +, -, /, ou *, stocke la valeur courante dans la variable rsultatCourant et vide le champ Affichage avant l'entre du nombre suivant
101
if (sourceEvnement == parent.boutonPlus) { actionSlectionne = '+'; rsultatCourant = valeurAffiche; parent.champAffichage.setText(""); } else if (sourceEvnement == parent.boutonMoins) { actionSlectionne = '-'; rsultatCourant = valeurAffiche; parent.champAffichage.setText(""); } else if (sourceEvnement == parent.boutonDiviser) { actionSlectionne = '/'; rsultatCourant = valeurAffiche; parent.champAffichage.setText(""); } else if (sourceEvnement == parent.boutonMultiplier) { actionSlectionne = '*'; rsultatCourant = valeurAffiche; parent.champAffichage.setText(""); } else if (sourceEvnement == parent.boutonEgale) { // Effectue les calculs en fonction de actionSlectionne // Modifie la valeur de la variable rsultatCourant // et affiche le rsultat if (actionSlectionne == '+') { rsultatCourant += valeurAffiche; // Convertit le rsultat en le transformant en String // l'aide de formatNombres parent.champAffichage.setText( formatNombres.format(rsultatCourant)); } else if (actionSlectionne == '-') { rsultatCourant -= valeurAffiche; parent.champAffichage.setText( formatNombres.format(rsultatCourant)); } else if (actionSlectionne == '/') { rsultatCourant /= valeurAffiche; parent.champAffichage.setText( formatNombres.format(rsultatCourant)); } else if (actionSlectionne == '*') { rsultatCourant *= valeurAffiche; parent.champAffichage.setText( formatNombres.format(rsultatCourant)); } } else { // Pour tous les boutons numriques, ajoute le libell // du bouton au champ texte String libellBoutonCliqu = boutonCliqu.getText(); parent.champAffichage.setText(texteChampAffichage + libellBoutonCliqu); }
102
La classe Calculatrice effectue les tapes suivantes : 1. 2. 3. 4. Crer et afficher tous les composants de la fentre. Crer une instance du rcepteur d'vnements MoteurCalcul. Passer au moteur une rfrence elle-mme. Enregistrer le moteur en tant que rcepteur auprs de tous les composants qui peuvent gnrer des vnements.
103
JButton boutonDiviser = new JButton("/"); JButton boutonMultiplier = new JButton("*"); JPanel contenuFentre = new JPanel(); JTextField champAffichage = new JTextField(30); // Constructeur Calculatrice() { // Affecte le gestionnaire de disposition pour ce panneau BorderLayout disposition = new BorderLayout(); contenuFentre.setLayout(disposition); // Ajoute le champ d'affichage en haut de la fentre contenuFentre.add("North", champAffichage); // Cre le panneau avec le quadrillage qui contient // 12 boutons les 10 boutons numriques et ceux // reprsentant la virgule et le signe gale JPanel panneauChiffres = new JPanel(); GridLayout dispositionChiffres = new GridLayout(4, 3); panneauChiffres.setLayout(dispositionChiffres); panneauChiffres.add(bouton1); panneauChiffres.add(bouton2); panneauChiffres.add(bouton3); panneauChiffres.add(bouton4); panneauChiffres.add(bouton5); panneauChiffres.add(bouton6); panneauChiffres.add(bouton7); panneauChiffres.add(bouton8); panneauChiffres.add(bouton9); panneauChiffres.add(bouton0); panneauChiffres.add(boutonVirgule); panneauChiffres.add(boutonEgale); // Ajoute le panneau des chiffres la zone centrale // de la fentre contenuFentre.add("Center", panneauChiffres); // Cre le panneau avec le quadrillage qui contient 4 // boutons d'opration Plus, Moins, Diviser, Multiplier JPanel panneauOprations = new JPanel(); GridLayout dispositionOprations = new GridLayout(4, 1); panneauOprations.setLayout(dispositionOprations); panneauOprations.add(boutonPlus); panneauOprations.add(boutonMoins); panneauOprations.add(boutonMultiplier); panneauOprations.add(boutonDiviser);
104
// Ajoute le panneau des oprations la zone est // de la fentre contenuFentre.add("East", panneauOprations); // Cre le cadre et lui affecte son contenu JFrame frame = new JFrame("Calculatrice"); frame.setContentPane(contenuFentre); // Affecte la fentre des dimensions suffisantes pour // prendre en compte tous les contrles frame.pack(); // Affiche la fentre frame.setVisible(true); // Instancie le rcepteur d'vnements et l'enregistre // auprs de chaque bouton MoteurCalcul moteurCalcul = new MoteurCalcul(this); bouton0.addActionListener(moteurCalcul); bouton1.addActionListener(moteurCalcul); bouton2.addActionListener(moteurCalcul); bouton3.addActionListener(moteurCalcul); bouton4.addActionListener(moteurCalcul); bouton5.addActionListener(moteurCalcul); bouton6.addActionListener(moteurCalcul); bouton7.addActionListener(moteurCalcul); bouton8.addActionListener(moteurCalcul); bouton9.addActionListener(moteurCalcul); boutonVirgule.addActionListener(moteurCalcul); boutonPlus.addActionListener(moteurCalcul); boutonMoins.addActionListener(moteurCalcul); boutonDiviser.addActionListener(moteurCalcul); boutonMultiplier.addActionListener(moteurCalcul); boutonEgale.addActionListener(moteurCalcul); } public static void main(String[] args) { // Instancie la classe Calculatrice Calculatrice calc = new Calculatrice(); }
Classe Calculatrice (partie 3 de 3) Maintenant, compile le projet et excute la classe Calculatrice. Elle marche presque comme les calculatrices du monde rel. Flicitations ! C'est ton premier programme utilisable par plein d'autres personnes fais-en cadeau tes amis. Pour mieux comprendre comment fonctionne ce programme, je te recommande de te familiariser avec le dboguage (debugging) de
105
Mthodes implanter
focusGained(FocusEvent) focusLost(FocusEvent) itemStateChanged(ItemEvent) keyPressed(KeyEvent) keyReleased(KeyEvent) keyTyped(KeyEvent) mouseClicked(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mousePressed(MouseEvent) mouseReleased(MouseEvent) mouseDragged(MouseEvent) mouseMoved(MouseEvent) windowActivated(WindowEvent) windowClosed(WindowEvent) windowClosing(WindowEvent) windowDeactivated (WindowEvent)
MouseListener
MouseMotionListener WindowListener
Programmation Java pour les enfants, les parents et les grands-parents windowDeiconified(WindowEvent) windowIconified(WindowEvent) windowOpened(WindowEvent)
106
Par exemple, l'interface FocusListener dclare deux mthodes : focusGained() et focusLost(). Cela implique que, mme si ta classe n'est intresse que par le traitement des vnements correspondant l'activation d'un champ particulier et n'a donc besoin d'implanter que focusGained(), tu dois aussi inclure la mthode vide focusLost(). Cela peut tre pnible, mais Java fournit des classes adapteurs (adapter classes) spciales pour chaque rcepteur afin de faciliter le traitement des vnements.
import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; class MonProcesseurEvnements extends WindowAdapter { public void windowClosing(WindowEvent vnement) { // Insre ici le code qui enregistre // les donnes sur disque } }
Le reste est facile enregistre simplement cette classe comme rcepteur d'vnements dans la classe de la fentre :
MonProcesseurEvnements monRcepteur = new MonProcesseurEvnements(); addWindowListener(monRcepteur);
On peut obtenir le mme rsultat en utilisant ce qu'on appelle des classes internes anonymes (anonymous inner classes), mais c'est un sujet un peu trop compliqu pour ce livre.
107
Autres lectures
Ecriture de rcepteurs d'vnements :
http://java.sun.com/docs/books/tutorial/uiswing/events/
Exercices
Essaie de diviser un nombre par zro l'aide de notre calculatrice le champ textuel affiche un signe qui veut dire "infini". Modifie la classe MoteurCalcul pour afficher le message "Impossible de diviser par zro" si l'utilisateur tente une division par zro.
108
pour que certains des jeux et autres programmes qui te sont proposs soient crits en Java l'aide de ce qu'on appelle des applets ou, parfois, des appliquettes. Ces applications spciales existent et s'excutent dans la fentre du navigateur web. Les navigateurs web comprennent un langage simple appel HTML, qui te permet d'insrer des marques spciales, ou balises (tags), dans les fichiers texte, afin de leur donner une apparence agrable lorsqu'ils sont affichs par les navigateurs. En plus du texte, tu peux inclure dans un fichier HTML la balise <applet>, qui indique au navigateur o trouver une applet Java et comment l'afficher. Les applets Java sont tlcharges sur ton ordinateur depuis Internet en tant que parties d'une page web. Le navigateur est suffisamment malin pour lancer son propre Java afin de les excuter.
Dans ce chapitre, tu vas apprendre comment crer des applets sur ton ordinateur. L'annexe C explique comment publier tes pages web sur Internet pour que d'autres personnes puissent les utiliser. Les gens naviguent sur Internet sans savoir si les pages web contiennent des applets Java ou pas, mais veulent tre certains que leurs ordinateurs sont l'abri des dgts que pourraient causer des personnes malintentionnes en incorporant une page une applet
109
nuisible. C'est pourquoi les applets ont t conues avec les limitations suivantes :
Les applets ne peuvent pas accder aux fichiers de ton disque dur, moins que tu n'aies sur ton disque un fichier spcial, appel certificat, qui leur en donne l'autorisation. Les applets ne peuvent se connecter qu' l'ordinateur duquel elles ont t tlcharges. Les applets ne peuvent dmarrer aucun des programmes situs sur ton disque dur.
Pour excuter une applet, il te faut une classe Java crite d'une certaine manire, un fichier texte HTML contenant la balise <applet> pointant sur cette classe et un navigateur web qui supporte Java. Tu peux aussi tester les applets dans Eclipse ou l'aide d'un programme spcial appel visualisateur d'applet (appletviewer). Mais avant d'apprendre crer des applets, prenons 15 minutes pour nous familiariser avec quelques balises HTML.
110
premire page web" et l'intrieur de la page sont affichs les mots "Mon jeu de morpion va bientt arriver" :
Modifie maintenant ce fichier en ajoutant la balise pour l'applet Morpion : <HTML> <Head> <Title>Ma premire page web</Title> </Head> <BODY> Voici mon jeu de morpion : <p><APPLET code = "Morpion.class" width=300 height=250> </APPLET> </BODY> </HTML>
111
Evidemment, puisque le navigateur web ne peut pas trouver Morpion.class, il affiche simplement un rectangle vide. Nous crerons cette classe un peu plus loin dans ce chapitre. Les balises HTML sont entoures par des signes infrieur (<) et suprieur (>). Certaines balises peuvent avoir des attributs supplmentaires. La balise <APPLET> de notre exemple utilise les attributs suivants :
code : nom de la classe Java de l'applet. width : largeur en pixels de la surface rectangulaire de l'cran qui sera occupe par l'applet. height : hauteur de la surface occupe par l'applet.
Si une applet Java est constitue de plusieurs classes, rassemble-les dans un fichier archive l'aide du programme jar fourni avec J2SDK. Dans ce cas, l'attribut archive doit prciser le nom de cette archive. L'annexe A propose des lectures relatives aux jars.
112
113
Contrairement aux applications Java, les applets n'ont pas besoin de mthode main() car le navigateur web les tlcharge et les excute ds qu'il rencontre la balise <applet> dans une page web. Le navigateur envoie aussi des signaux aux applets quand des vnements importants se produisent, par exemple quand l'applet est lance, est repeinte, etc. Pour tre sr que l'applet ragisse ces vnements, tu dois programmer des mthodes de rappel (callback methods) spciales : init() (initialiser), start() (dmarrer), paint() (peindre), stop() (arrter) et destroy() (dtruire). Le Java du navigateur appelle ces mthodes dans les cas suivants :
init() est appele quand l'applet est charge par le navigateur. Elle n'est appele qu'une fois : elle joue donc un rle similaire celui des constructeurs des classes Java normales. start() est appele juste aprs init(). Elle est aussi appele si l'utilisateur revient une page web aprs avoir visit une autre page. paint() est appele quand la fentre de l'applet a besoin d'tre affiche ou rafrachie aprs une activit quelconque sur l'cran. Par exemple, l'applet a t recouverte par une autre fentre et le navigateur a besoin de la repeindre. stop() est appele quand l'utilisateur quitte la page web contenant l'applet. destroy() est appele quand le navigateur dtruit l'applet. Tu n'as besoin d'crire du code pour cette mthode que si l'applet utilise d'autres ressources, par exemple quand elle maintient une connexion avec l'ordinateur duquel elle a t tlcharge.
Mme s'il n'est pas ncessaire de programmer toutes ces mthodes, chaque applet doit dfinir au moins init() et paint(). Voici le code d'une applet qui affiche les mots "Bonjour Monde !". Cette applet ne contient que la mthode paint(), qui reoit une instance de l'objet Graphics du Java du navigateur. Cet objet dispose d'un tas de
114
mthodes graphiques. L'exemple suivant utilise la mthode drawString() (dessiner une chane de caractres) pour dessiner le texte "Bonjour Monde !".
public class AppletBonjour extends java.applet.Applet { public void paint(java.awt.Graphics contexteGraphique) { contexteGraphique.drawString("Bonjour Monde !", 70, 40); } }
Cre cette classe dans Eclipse. Ensuite, dans la fentre Excuter, slectionne Applet Java dans le coin suprieur gauche, appuie sur le bouton Crer et entre AppletBonjour dans le champ Applet. Pour tester cette applet dans le navigateur web, cre le fichier Bonjour.html dans le dossier o est enregistre ton applet.
<HTML> <BODY> Voici ma premire applet :<P> <APPLET code = AppletBonjour.class width = 200 height = 100> </APPLET> </BODY> </HTML>
Ouvre maintenant le fichier Bonjour.html l'aide des menus Fichier et Ouvrir de ton navigateur.
115
Crois-tu qu'aprs ce simple exemple nous soyons prts pour crire un programme de jeu ? Tu m'tonnes ! Boucle juste ta ceinture
Stratgie
Tous les jeux utilisent un algorithme un ensemble de rgles ou une stratgie appliquer en fonction des actions du joueur. Pour un mme jeu, il peut y avoir des algorithmes simples ou trs compliqus. Quand on dit que le champion du monde d'checs Gary Kasparov joue contre un ordinateur, il joue en fait contre un programme. Des quipes
116
d'experts essaient d'inventer des algorithmes sophistiqus pour le battre. Le jeu de morpion peut aussi tre programm selon diffrentes stratgies ; nous allons en utiliser la plus simple : 1. Nous utilisons un plateau 3 x 3. 2. L'utilisateur joue avec le symbole X et l'ordinateur avec le O. 3. Pour gagner, il faut avoir complt une ligne, une colonne ou une diagonale avec le mme symbole. 4. Aprs chaque coup, le programme vrifie s'il y a un gagnant. 5. S'il y a un gagnant, la combinaison gagnante est mise en surbrillance et la partie se termine. 6. La partie se termine aussi s'il n'y a plus de cases libres. 7. Pour faire une nouvelle partie, le joueur appuie sur le bouton Nouvelle partie. 8. Quand l'ordinateur dcide o placer le prochain O, il essaie de trouver une ligne, une colonne ou une diagonale o se trouvent dj deux O pour la complter. 9. S'il n'y pas deux O aligns, l'ordinateur essaie de trouver deux X aligns afin de parer un coup gagnant du joueur en plaant un O. 10. Si aucun coup gagnant ou bloquant n'a t trouv, l'ordinateur essaie d'occuper la case centrale, ou choisit la prochaine case vide au hasard.
Code
Je vais juste te donner ici une brve description du programme car le code de l'applet contient de nombreux commentaires qui t'aideront comprendre comment il fonctionne. L'applet utilise un gestionnaire de disposition BorderLayout. La zone nord de la fentre contient le bouton Nouvelle partie. La zone centrale affiche neuf boutons reprsentant les cases et la zone sud affiche les messages :
117
Tous les composants de la fentre sont crs par la mthode init() de l'applet. Tous les vnements sont traits par le rcepteur ActionListener dans la mthode actionPerformed(). La mthode chercherUnGagnant() est appele aprs chaque coup pour vrifier si la partie est termine. Les rgles 8, 9 et 10 de notre stratgie sont codes dans la mthode coupOrdinateur(), qui peut avoir besoin de gnrer un nombre alatoire (random number). On utilise pour cela la classe Java Math et sa mthode random(). Tu rencontreras aussi une syntaxe assez inhabituelle o plusieurs appels de mthodes sont effectus en une seule expression, comme dans cet exemple :
if(cases[0].getLabel().equals(cases[1].getLabel())){}
Cette ligne raccourcit le code car elle effectue en fait les mmes actions que l'ensemble des lignes suivantes :
String label0 = cases[0].getLabel(); String label1 = cases[1].getLabel(); if(label0.equals(label1)){}
Dans les expressions complexes, Java value le code entre parenthses avant d'effectuer d'autres calculs. La version courte de ce code cherche d'abord le rsultat de l'expression entre parenthses, puis l'utilise comme argument de la mthode equals(), qui est applique au rsultat du premier appel getLabel(). Mme si le code du jeu occupe plusieurs pages, il n'est pas trs difficile comprendre. Lis simplement tous les commentaires qui s'y trouvent.
118
/** * Un jeu de morpion sur un plateau 3x3 */ import java.awt.*; import java.awt.event.*; import java.applet.Applet; public class Morpion extends Applet implements ActionListener { Button cases[]; Button boutonNouvellePartie; Label score; int casesLibresRestantes = 9; /** * La mthode init est comme un constructeur pour l'applet */ public void init() { // Affecte le gestionnaire de disposition et la couleur // de l'applet this.setLayout(new BorderLayout()); this.setBackground(Color.CYAN); // Passe la police de l'applet en style gras et taille 20 Font policeApplet = new Font("Monospaced", Font.BOLD, 20); this.setFont(policeApplet); // Cre le bouton Nouvelle partie et enregistre // le rcepteur d'actions auprs de lui boutonNouvellePartie = new Button("Nouvelle partie"); boutonNouvellePartie.addActionListener(this); // Cre deux panneaux et un label et les agence en // utilisant le border layout Panel panneauSuprieur = new Panel(); panneauSuprieur.add(boutonNouvellePartie);
119
this.add(panneauSuprieur, "North"); Panel panneauCentral = new Panel(); panneauCentral.setLayout(new GridLayout(3, 3)); this.add(panneauCentral, "Center"); score = new Label("A vous de jouer !"); this.add(score, "South"); // Cre un tableau pour stocker les rfrences des // 9 boutons cases = new Button[9]; // Instancie les boutons, stocke leurs rfrences dans le // tableau, enregistre le rcepteur auprs d'eux, peint // les boutons en orange et les ajoute au panneau central for(int i = 0; i < 9; i++) { cases[i]= new Button(); cases[i].addActionListener(this); cases[i].setBackground(Color.ORANGE); panneauCentral.add(cases[i]); }
} /** * Cette mthode traite tous les vnements d'action * @param vnement l'vnement traiter */ public void actionPerformed(ActionEvent vnement) { Button leBouton = (Button) vnement.getSource(); // S'agit-il du bouton Nouvelle partie ? if (leBouton == boutonNouvellePartie) { for(int i = 0; i < 9; i++) { cases[i].setEnabled(true); cases[i].setLabel(""); cases[i].setBackground(Color.ORANGE); } casesLibresRestantes = 9; score.setText("A vous de jouer !"); boutonNouvellePartie.setEnabled(false); return; // Sort de la mthode } String gagnant = "";
120
// S'agit-il de l'une des cases ? for (int i = 0; i < 9; i++) { if (leBouton == cases[i]) { cases[i].setLabel("X"); gagnant = chercherUnGagnant(); if(!"".equals(gagnant)) { terminerLaPartie(); } else { coupOrdinateur(); gagnant = chercherUnGagnant(); if (!"".equals(gagnant)) { terminerLaPartie(); } } break; } } // Fin de la boucle for if (gagnant.equals("X")) { score.setText("Vous avez gagn !"); } else if (gagnant.equals("O")) { score.setText("Vous avez perdu !"); } else if (gagnant.equals("T")) { score.setText("Partie nulle !"); } } // Fin de actionPerformed /** * Cette mthode est appele aprs chaque coup jou pour * voir s'il y a un gagnant. Elle vrifie pour chaque ligne, * colonne et diagonale, s'il y a trois symboles identiques * @return "X", "O", "T" (termin, partie nulle) ou "" (pas * fini) */ String chercherUnGagnant() { String leGagnant = ""; casesLibresRestantes--;
121
// Vrifie la ligne 1 - lments 0, 1 et 2 du tableau if (!cases[0].getLabel().equals("") && cases[0].getLabel().equals(cases[1].getLabel()) && cases[0].getLabel().equals(cases[2].getLabel())) { leGagnant = cases[0].getLabel(); montrerGagnant(0, 1, 2); // Vrifie la ligne 2 - lments 3, 4 et 5 du tableau } else if (!cases[3].getLabel().equals("") && cases[3].getLabel().equals(cases[4].getLabel()) && cases[3].getLabel().equals(cases[5].getLabel())) { leGagnant = cases[3].getLabel(); montrerGagnant(3, 4, 5); // Vrifie la ligne 3 - lments 6, 7 et 8 du tableau } else if (!cases[6].getLabel().equals("") && cases[6].getLabel().equals(cases[7].getLabel()) && cases[6].getLabel().equals(cases[8].getLabel())) { leGagnant = cases[6].getLabel(); montrerGagnant(6, 7, 8); // Vrifie la colonne 1 - lments 0, 3 et 6 du tableau } else if (!cases[0].getLabel().equals("") && cases[0].getLabel().equals(cases[3].getLabel()) && cases[0].getLabel().equals(cases[6].getLabel())) { leGagnant = cases[0].getLabel(); montrerGagnant(0, 3, 6); // Vrifie la colonne 2 - lments 1, 4 et 7 du tableau } else if (!cases[1].getLabel().equals("") && cases[1].getLabel().equals(cases[4].getLabel()) && cases[1].getLabel().equals(cases[7].getLabel())) { leGagnant = cases[1].getLabel(); montrerGagnant(1, 4, 7); // Vrifie la colonne 3 - lments 2, 5 et 8 du tableau } else if (!cases[2].getLabel().equals("") && cases[2].getLabel().equals(cases[5].getLabel()) && cases[2].getLabel().equals(cases[8].getLabel())) { leGagnant = cases[2].getLabel(); montrerGagnant(2, 5, 8);
122
// Vrifie la premire diagonale - lments 0, 4 et 8 } else if (!cases[0].getLabel().equals("") && cases[0].getLabel().equals(cases[4].getLabel()) && cases[0].getLabel().equals(cases[8].getLabel())) { leGagnant = cases[0].getLabel(); montrerGagnant(0, 4, 8); // Vrifie la seconde diagonale - lments 2, 4 et 6 } else if (!cases[2].getLabel().equals("") && cases[2].getLabel().equals(cases[4].getLabel()) && cases[2].getLabel().equals(cases[6].getLabel())) { leGagnant = cases[2].getLabel(); montrerGagnant(2, 4, 6); } else if (casesLibresRestantes == 0) { return "T"; // Partie nulle } return leGagnant; } /** * Cette mthode applique un ensemble de rgles afin de * trouver le meilleur coup pour l'ordinateur. Si un bon * coup ne peut tre trouv, elle choisit une case au * hasard. */ void coupOrdinateur() { int caseSlectionne; // L'ordinateur essaie d'abord de trouver une case // vide prs de deux case marques "O" pour gagner caseSlectionne = trouverCaseVide("O"); // S'il n'y a pas deux "O" aligns, essaie au moins // d'empcher l'adversaire d'aligner trois "X" en // plaant un "O" prs de deux "X" if (caseSlectionne == -1) { caseSlectionne = trouverCaseVide("X"); } // Si caseSlectionne vaut toujours -1, essaie d'occuper // la case centrale if ((caseSlectionne == -1) && (cases[4].getLabel().equals(""))) { caseSlectionne = 4; } // Pas de chance avec la case centrale non plus... // Choisit une case au hasard if (caseSlectionne == -1) { caseSlectionne = choisirCaseAuHasard(); } cases[caseSlectionne].setLabel("O"); }
123
/** * Cette mthode examine chaque ligne, colonne et diagonale * pour voir si elle contient deux cases avec le mme label * et une case vide. * @param joueur "X" pour l'utilisateur ou "O" pour * l'ordinateur * @return numro de la case vide utiliser ou le nombre * ngatif -1 si la recherche est infructueuse */ int trouverCaseVide(String joueur) { int poids[] = new int[9]; for (int i = 0; i < 9; i++ ) { if (cases[i].getLabel().equals("O")) poids[i] = -1; else if (cases[i].getLabel().equals("X")) poids[i] = 1; else poids[i] = 0; } int deuxPoids = joueur.equals("O") ? -2 : 2; // Regarde si la ligne 1 a 2 cases if (poids[0] + poids[1] + poids[2] if (poids[0] == 0) return 0; else if (poids[1] == 0) return 1; else return 2; } // Regarde si la ligne 2 a 2 cases if (poids[3] + poids[4] + poids[5] if (poids[3] == 0) return 3; else if (poids[4] == 0) return 4; else return 5; } identiques et une vide == deuxPoids) {
124
// Regarde si la ligne 3 a 2 cases identiques et une vide if (poids[6] + poids[7] + poids[8] == deuxPoids) { if (poids[6] == 0) return 6; else if (poids[7] == 0) return 7; else return 8; } // Regarde si la colonne 1 a 2 cases identiques et une vide if (poids[0] + poids[3] + poids[6] == deuxPoids) { if (poids[0] == 0) return 0; else if (poids[3] == 0) return 3; else return 6; } // Regarde si la colonne 2 a 2 cases identiques et une vide if (poids[1] + poids[4] + poids[7] == deuxPoids) { if (poids[1] == 0) return 1; else if (poids[4] == 0) return 4; else return 7; } // Regarde si la colonne 3 a 2 cases identiques et une vide if (poids[2] + poids[5] + poids[8] == deuxPoids) { if (poids[2] == 0) return 2; else if (poids[5] == 0) return 5; else return 8; } // Regarde si la diagonale 1 a 2 cases identiques et une // vide if (poids[0] + poids[4] + poids[8] == deuxPoids) { if (poids[0] == 0) return 0; else if (poids[4] == 0) return 4; else return 8; }
125
// Regarde si la diagonale 2 a 2 cases identiques et une // vide if (poids[2] + poids[4] + poids[6] == deuxPoids) { if (poids[2] == 0) return 2; else if (poids[4] == 0) return 4; else return 6; } // Il n'y a pas de cases alignes identiques return -1; } // Fin de trouverCaseVide() /** * Cette mthode slectionne une case vide quelconque. * @return un numro de case choisi au hasard */ int choisirCaseAuHasard() { boolean caseVideTrouve = false; int caseSlectionne = -1; do { caseSlectionne = (int) (Math.random() * 9); if (cases[caseSlectionne].getLabel().equals("")) { caseVideTrouve = true; // Pour terminer la boucle } } while (!caseVideTrouve); return caseSlectionne; } // Fin de choisirCaseAuHasard() /** * Cette mthode affiche la ligne gagnante en surbrillance. * @param gagnante1 premire case montrer. * @param gagnante2 deuxime case montrer. * @param gagnante3 troisime case montrer. */ void montrerGagnant(int gagnante1, int gagnante2, int gagnante3) { cases[gagnante1].setBackground(Color.CYAN); cases[gagnante2].setBackground(Color.CYAN); cases[gagnante3].setBackground(Color.CYAN); } // Dsactive les cases et active le bouton Nouvelle partie void terminerLaPartie() { boutonNouvellePartie.setEnabled(true); for (int i = 0; i < 9; i++) { cases[i].setEnabled(false); } } } // Fin de la classe
126
Flicitations ! Tu as termin ton premier jeu en Java. Tu peux excuter cette applet directement depuis Eclipse ou en ouvrant le fichier Morpion.html que nous avons cr au dbut de ce chapitre (copie simplement les fichiers Morpion.html et Morpion.class dans le mme rpertoire). Notre classe Morpion a un petit bogue (bug) - tu pourrais mme ne pas t'en apercevoir, mais je suis sr qu'il sera corrig lorsque tu auras termin le deuxime exercice ci-dessous. Notre classe Morpion utilise une stratgie simple parce que notre objectif est juste d'apprendre programmer. Mais si tu souhaites amliorer ce jeu, applique l'algorithme appel minimax qui te permet de choisir le meilleur coup pour l'ordinateur. La description de cette stratgie n'est pas du ressort de ce livre, mais tu peux facilement la trouver sur le web.
127
Autres lectures
Applets Java :
http://java.sun.com/docs/books/tutorial/applet/
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Math.html
Exercices
1. Ajoute au panneau suprieur de la classe Morpion deux champs affichant les nombres de victoires et de dfaites. Pour ce faire, dclare deux variables de classe que tu incrmenteras chaque victoire ou dfaite. Le score doit tre rafrachi juste aprs que le programme ait affich le message "Vous avez gagn" ou "Vous avez perdu". 2. Notre programme permet de cliquer sur une case qui est dj marque d'un X ou d'un O. C'est un bogue ! Le programme continue comme si on avait jou un coup valide. Modifie le code pour ignorer les clics sur des cases dj marques. 3. Ajoute la mthode main() la classe Morpion pour qu'on puisse lancer le jeu non seulement comme une applet, mais aussi comme une application Java.
128
129
Java. Il se produirait une erreur de compilation, que tu pourrais corriger facilement. Mais il se produit aussi ce qu'on appelle des erreurs d'excution (run-time errors), lorsque ton programme cesse tout coup de fonctionner correctement. Par exemple, une classe Java lit un fichier contenant les scores du jeu. Que se passe-t-il si quelqu'un a supprim ce fichier ? Le programme s'croule-t-il en affichant un message d'erreur droutant, ou reste-t-il en vie en affichant un message comprhensible comme : "Cher ami, pour une raison inconnue il m'est impossible de lire le fichier scores.txt. Merci de vrifier que ce fichier existe." ? Il est prfrable de crer des programmes capables de grer les situations inhabituelles. Dans beaucoup de langages de programmation, le traitement des erreurs dpend de la bonne volont du programmeur. Mais Java rend obligatoire l'inclusion de code de gestion des erreurs. A dfaut, les programmes ne peuvent mme pas tre compils. En Java, les erreurs d'excution sont appeles des exceptions et le traitement des erreurs est appel gestion des exceptions (exception handling). Tu dois placer le code susceptible de produire des erreurs dans des blocs try/catch (essayer/capturer). C'est comme si tu disais ceci Java : Essaie de lire le fichier contenant les scores. Si quelque chose d'anormal se produit, capture l'erreur et excute le code qui doit la grer.
try { fichierScores.read(); } catch (IOException exception) { System.out.println( "Cher ami, je ne peux pas lire le fichier scores.txt"); }
maginons que tu aies oubli une accolade fermante dans ton code
Nous apprendrons comment travailler avec des fichiers au Chapitre 9, mais pour l'instant familiarise-toi avec l'expression I/O ou input/output (entre/sortie). Les oprations de lecture et d'criture (sur disque ou sur d'autres priphriques) sont appeles I/O ; ainsi,
130
IOException est une classe qui contient des informations relatives aux erreurs d'entre/sortie. Une mthode lve une exception en cas d'erreur. Diffrentes exceptions sont leves pour diffrents types d'erreurs. Si le bloc catch existe dans le programme pour un type particulier d'erreur, l'erreur est capture et le programme se dbranche sur le bloc catch pour excuter le code qui s'y trouve. Le programme reste vivant et cette exception est considre comme prise en charge. L'instruction qui affiche le message dans le code ci-dessus n'est excute que dans le cas d'une erreur de lecture de fichier.
1 class TestTracePile { 2 TestTracePile() 3 { 4 diviserParZro(); 5 } 6 7 int diviserParZro() 8 { 9 return 25 / 0; 10 } 11 12 public static void main(String[] args) 13 { 14 new TestTracePile(); 15 } 16 }
La sortie de ce programme montre la squence des appels de mthodes effectus jusqu'au moment o l'erreur d'excution s'est produite. Lis cette sortie en remontant partir de la dernire ligne.
Exception in thread "main" java.lang.ArithmeticException: / by zero at TestTracePile.diviserParZro(TestTracePile.java:9) at TestTracePile.<init>(TestTracePile.java:4) at TestTracePile.main(TestTracePile.java:14)
131
Ceci signifie que le programme a commenc par la mthode main(), puis est entr dans init(), qui est un constructeur, et a ensuite appel la mthode diviserParZro(). Les nombres 14, 4 et 9 indiquent dans quelles lignes du programme ont eu lieu ces appels de mthodes. Enfin, une exception ArithmeticException a t leve : la ligne numro 9 a essay d'effectuer une division par 0.
Les sous-classes de la classe Exception sont appeles exceptions contrles (checked exceptions) et tu dois les traiter dans ton code.
132
Les sous-classes de la classe Error sont des erreurs fatales et le programme en cours d'excution ne peut en gnral pas les grer. TropDeVlosException est un exemple d'exception cre par un dveloppeur. Comment un dveloppeur est-il sens savoir l'avance si une mthode Java peut lever une exception et qu'un bloc try/catch est ncessaire ? Pas de soucis ; si tu appelles une mthode qui peut lever une exception, le compilateur Java affiche un message d'erreur comme celui-ci :
"LecteurDeScore.java": unreported exception: java.io.IOException; must be caught or declared to be thrown at line 57
Bien sr, tu es libre de lire la documentation Java qui dcrit les exceptions qui peuvent tre leves par une mthode donne. La suite de ce chapitre explique comment grer ces exceptions.
Bloc try/catch
Il y a cinq mot-cls Java qui peuvent tre utiliss dans le traitement des erreurs : try, catch, finally, throw et throws. Aprs un bloc try, tu peux mettre plusieurs blocs catch, si tu penses que diffrentes erreurs sont susceptibles de se produire. Par exemple, quand un programme essaie de lire un fichier, le fichier peut ne pas tre l, ce qui gnre l'exception FileNotFoundException, ou le fichier peut tre l mais le code continuer le lire aprs avoir atteint la fin du fichier, ce qui gnre l'exception EOFException. L'extrait de code suivant affiche des messages en bon franais si le programme ne trouve pas le fichier contenant les scores ou atteint prmaturment la fin du fichier. Pour toute autre erreur, il affiche le message "Problme de lecture de fichier" et une description technique de l'erreur.
public void chargerScores() { try { fichierScores.read(); System.out.println("Scores chargs avec succs"); } catch(FileNotFoundException e) { System.out.println("Fichier Scores introuvable"); } catch(EOFException e1) { System.out.println("Fin de fichier atteinte"); } catch(IOException e2) { System.out.println("Problme de lecture de fichier" + e2.getMessage()); } }
133
Si la mthode read() (lire) choue, le programme saute la ligne println() et essaie de trouver le bloc catch qui correspond l'erreur. S'il le trouve, l'instruction println() approprie est excute ; s'il n'y a pas de bloc catch correspondant l'erreur, la mthode chargerScores() remonte l'exception la mthode qui l'a appele. Si tu cris plusieurs blocs catch, tu dois faire attention l'ordre dans lequel tu les cris si les exceptions que tu traites hritent les unes des autres. Par exemple, puisque EOFException est une sous-classe de IOException, tu dois placer le bloc catch de EOFException, la sousclasse, en premier. Si tu traitais IOException en premier, le programme n'atteindrait jamais les exceptions FileNotFound ou EOFException, car elles seraient interceptes par le premier catch. Les fainants pourraient programmer la mthode chargerScores() comme ceci :
public void chargerScores() { try { fichierScores.read(); } catch(Exception e) { System.out.println("Problme de lecture du fichier " + e.getMessage()); } }
C'est un exemple de mauvais style de code Java. Quand tu cris un programme, n'oublie jamais que quelqu'un d'autre pourrait le lire ; et tu ne veux pas avoir honte de ton code. Les blocs catch reoivent une instance de l'objet Exception contenant une courte explication du problme. La mthode getMessage() retourne cette information. Parfois, lorsque la description d'une erreur n'est pas claire, tu peux essayer la mthode toString() la place :
catch(Exception exception) { System.out.println("Problme de lecture du fichier " + exception.toString()); }
Si tu as besoin d'informations plus dtailles propos de l'exception, utilise la mthode printStackTrace(). Elle affiche la squence d'appels de mthodes qui a abouti l'exception, de la mme faon que dans l'exemple de la section Lecture de la trace de la pile.
134
Essayons de "tuer" le programme de calculatrice du Chapitre 6. Excute la classe Calculatrice et entre au clavier les caractres abc. Appuie sur n'importe lequel des boutons d'oprations ; la console affiche quelque chose de ce genre :
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at MoteurCalcul.actionPerformed(MoteurCalcul.java:43) at javax.swing.AbstractButton.fireActionPerformed(AbstractB utton.java:1849) at javax.swing.AbstractButton$Handler.actionPerformed(Abstr actButton.java:2169) at javax.swing.DefaultButtonModel.fireActionPerformed(Defau ltButtonModel.java:420)
C'est un exemple d'exception non gre. Dans la mthode actionPerformed() de la classe MoteurCalcul, il y a ces lignes :
valeurAffiche = // analyse la chane de caractres formatNombres.parse( texteChampAffichage, new ParsePosition(0) /* ne sert pas */). // puis donne sa valeur en tant que double doubleValue();
Si la variable texteChampAffichage ne reprsente pas une valeur numrique, la mthode parse() est incapable de la convertir dans un nombre et rend null. Du coup l'appel de la mthode doubleValue() lve une exception NullPointerException. Grons cette exception et affichons un message d'erreur qui explique le problme l'utilisateur. Les lignes qui commencent par valeurAffiche doivent tre places dans un bloc try/catch ; Eclipse va t'y aider. Slectionne tout le texte depuis valeurAffiche jusqu'au point-virgule aprs doubleValue()et clique sur le bouton droit de la souris. Dans le menu popup, slectionne les sous-menus Source et Entourer d'un bloc try/catch. Rponds Oui la question que te pose Eclipse et voil ! Le code est modifi :
try { valeurAffiche = // analyse la chane de caractres formatNombres.parse( texteChampAffichage, new ParsePosition(0) /* ne sert pas */). // puis donne sa valeur en tant que double doubleValue(); } catch (RuntimeException e) { // TODO Bloc catch auto-gnr e.printStackTrace(); }
135
Nous nous sommes dbarrasss des messages d'erreur droutants de la trace de la pile, pour afficher la place le message facile comprendre "Merci d'entrer un nombre" :
Le mot-cl throws
Dans certains cas, il est plus appropri de traiter l'exception non pas dans la mthode o elle se produit, mais dans la mthode appelante. Dans de tels cas, la signature de la mthode doit dclarer (avertir) qu'elle peut lever une exception particulire. On utilise pour cela le mot-cl spcial throws. Reprenons notre exemple de lecture de fichier. Puisque la mthode read() peut dclencher une exception IOException, tu dois la grer ou la dclarer. Dans l'exemple suivant, nous dclarons que la mthode chargerTousLesScores() peut mettre une IOException :
Programmation Java pour les enfants, les parents et les grands-parents class MonSuperJeu { void chargerTousLesScores() throws IOException { // // N'utilise pas try/catch si tu ne gres pas // d'exceptions dans cette mthode fichier.read(); } public static void main(String[] args) { MonSuperJeu jeu = new MonSuperJeu(); System.out.println("Liste des scores");
136
try { // Puisque la mthode chargerTousLesScores() dclare // une exception, nous la grons ici jeu.chargerTousLesScores(); } catch(IOException e) { System.out.println( "Dsol, la liste des scores n'est pas disponible"); } } }
Comme nous n'essayons mme pas de capturer d'exception dans la mthode chargerTousLesScores(), l'exception IOException est propage sa mthode appelante, main(). Celle-ci doit maintenant grer cette exception.
Le mot-cl finally
Le code inclus dans un bloc try/catch peut se terminer de trois faons :
Le code l'intrieur du bloc try est excut avec succs et le programme se poursuit. Le code l'intrieur du bloc try rencontre une instruction return et le programme sort de la mthode. Le code l'intrieur du bloc try lve une exception et le contrle passe au bloc catch correspondant. Soit celui-ci gre l'erreur et l'excution de la mthode se poursuit ; soit il rmet l'exception destination de la mthode appelante.
Si un morceau de code doit tre excut quoi qu'il arrive, il faut le placer dans un bloc finally :
Programmation Java pour les enfants, les parents et les grands-parents try { fichier.read(); } catch(Exception e) { e.printStackTrace(); } finally { // Le code qui doit toujours tre excut, // par exemple file.close(), est plac ici. }
137
Le code ci-dessus doit fermer le fichier indpendamment du succs ou de l'chec de l'opration de lecture. En gnral, on trouve dans le bloc finally le code qui libre des ressources de l'ordinateur, par exemple la dconnexion d'un rseau ou la fermeture d'un fichier. Si tu n'as pas l'intention de traiter les exceptions dans la mthode courante, elles sont propages l'appelant. Dans ce cas, tu peux utiliser finally mme si tu n'as pas de bloc catch :
void maMthode() throws IOException { try { // Place ici le code qui lit le fichier. } finally { // Place ici le code qui ferme le fichier. } }
Le mot-cl throw
Si une exception se produit dans une mthode, mais que tu penses que c'est l'appelant de la traiter, il suffit de la rmettre vers celui-ci. Parfois, tu peux vouloir capturer une exception mais en lever une autre avec une description diffrente de l'erreur, comme dans le bout de code ci-dessous. L'instruction throw est utilise pour lever des exceptions en lanant des objets Java. L'objet lanc par un programme doit tre missible (throwable). C'est--dire que tu ne peux lancer que les objets qui sont des sous-classes directes ou indirectes de la classe Throwable - ce que sont toutes les exceptions Java.
138
Le fragment de code suivant montre comment la mthode chargerTousLesScores() capture une IOException, cre un nouvel objet Exception avec une description plus sympathique de l'erreur, et le lance vers la mthode main(). Du coup, pour que la mthode main() puisse tre compile, il faut ajouter une ligne qui appelle chargerTousLesScores() dans le bloc try/catch, car cette mthode peut mettre un objet Exception qui doit tre trait ou rmis. La mthode main() ne devant lever aucune exception, elle doit traiter celle-ci.
class ListeDesScores { // Ce code doit tre complt pour pouvoir le compiler static void chargerTousLesScores() throws Exception { try { fichier.read(); // Cette ligne peut lever // une exception } catch (IOException e) { throw new Exception( "Cher ami, le fichier des scores a un problme."); } } public static void main(String[] args) { System.out.println("Scores"); try { chargerTousLesScores(); } catch(Exception e1) { System.out.println(e1.getMessage()); } } }
139
Si une erreur fichier se produit, la mthode main() la prend en charge et l'appel e1.getMessage() renvoie le message "Cher ami "
Cette classe a juste un constructeur qui prend le message dcrivant l'erreur et le passe sa superclasse pour qu'elle le stocke. Quand un bloc catch reoit cette exception, il peut savoir ce qu'il se passe exactement en appelant la mthode getMessage(). Imagine qu'un utilisateur slectionne plusieurs bicyclettes d'un certain modle dans la fentre EcranCommande et appuie sur le bouton Commander. Comme tu le sais depuis le Chapitre 6, cette action aboutit l'appel de la mthode actionPerformed(), laquelle vrifie
140
si la commande peut tre livre. L'exemple de code suivant montre comment la mthode vrifierCommande() dclare qu'elle est susceptible de lever l'exception TropDeVlosException. Si la commande ne rentre pas dans la camionnette, la mthode lve l'exception, le bloc catch l'intercepte et affiche un message d'erreur dans le champ textuel de la fentre.
class EcranCommande implements ActionListener { // Place ici le code pour crer les composants de la fentre. public void actionPerformed(ActionEvent evt) { // L'utilisateur a cliqu sur le bouton Commander String modleChoisi = champTexteModle.getText(); String quantitChoisie = champTexteQuantit.getText(); int quantit = Integer.parseInt(quantitChoisie); try { commandeVlos.vrifierCommande(modleChoisi, quantitChoisie); // Cette ligne sera saute en cas d'exception champTexteConfirmationCommande.setText( "Votre commande est prte."); } catch(TropDeVlosException e) { champTexteConfirmationCommande.setText(e.getMessage()); } } void vrifierCommande(String modleVlo, int quantit) throws TropDeVlosException { // Ecris le code qui vrifie que la quantit demande // du modle slectionn entre bien dans la camionnette. // Si a n'entre pas, faire ce qui suit : throw new TropDeVlosException ("Impossible de livrer " + quantit + " vlos du modle " + modleVlo + " en une fois."); } }
Dans un monde parfait, tous les programmes fonctionneraient parfaitement, mais il faut tre raliste et tre prt ragir aux situations inattendues. Java nous aide vraiment en nous forant crire un code adapt ces situations.
141
Autres lectures
Gestion des erreurs l'aide des exceptions :
http://java.sun.com/docs/books/tutorial/essential/exceptions/
Exercices
Cre une application Swing pour grer des commandes de vlos. Elle doit contenir les deux champs textuels Modle de vlo et Quantit, le bouton Commander et le libell pour la confirmation des commandes. Utilise le code des exemples EcranCommande et TropDeVlosException. Prvois plusieurs combinaisons de modles et de quantits qui dclenchent une exception.
142
mmoire. Cela signifie que toutes les classes, mthodes et variables disparaissent jusqu' ce que tu excutes nouveau ce programme. Si tu souhaites sauvegarder certains rsultats de l'excution du programme, il faut les enregistrer dans des fichiers sur un disque, une cassette, une carte mmoire ou un autre priphrique capable de stocker des donnes pendant une longue priode. Dans ce chapitre, tu vas apprendre comment enregistrer des donnes sur disque l'aide des flux (streams) Java. Fondamentalement, tu ouvres un flux entre ton programme et un fichier sur disque. Si tu veux lire des donnes sur le disque, il te faut un flux d'entre (input stream) ; si tu cris des donnes sur le disque, ouvre un flux de sortie (output stream). Par exemple, si un joueur gagne une partie et que tu veux sauvegarder son score, tu peux l'enregistrer dans le fichier scores.txt en utilisant un flux de sortie. Un programme lit ou crit les donnes dans un flux en srie octet aprs octet, caractre aprs caractre, etc. Comme ton programme utilise diffrents types de donnes tels que String, int, double et autres, tu dois utiliser un flux Java appropri, par exemple un flux d'octets (byte stream), un flux de caractres (character stream) ou un flux de donnes (data stream). Les classes qui fonctionnent avec des flux de fichiers sont situes dans les paquetages java.io. et java.nio. Quel que soit le type de flux que tu vas utiliser, tu dois respecter les trois tapes suivantes dans ton programme :
Ouvrir un flux qui pointe sur un fichier. Lire ou crire des donnes dans ce flux. Fermer le flux.
143
Flux d'octets
Si tu cres un programme qui lit un fichier puis affiche son contenu sur l'cran, tu dois savoir quel type de donnes contient le fichier. Par contre, un programme qui se contente de copier des fichiers d'un endroit un autre n'a mme pas besoin de savoir s'il s'agit d'images, de texte ou de musique. De tels programmes chargent le fichier original en mmoire sous la forme d'un ensemble d'octets, puis les crivent dans le fichier de destination, octet aprs octet, l'aide des classes Java FileInputStream et FileOutputStream. L'exemple suivant montre comment utiliser la classe FileInputStream pour lire un fichier graphique nomm abc.gif, situ dans le rpertoire c:\exercices. Si tu utilises un ordinateur sous Microsoft Windows, pour viter la confusion avec les caractres spciaux Java qui commencent par une barre oblique inverse, utilise des barres doubles dans ton code pour sparer les noms de rpertoires et de fichier : "c:\\exercices". Ce petit programme n'affiche pas l'image, mais des nombres qui correspondent la faon dont l'image est stocke sur un disque. Chaque octet a une valeur entire positive comprise entre 0 et 255, que la classe LecteurOctets affiche en la dlimitant par des espaces. Je te prie de noter que la classe LecteurOctets ferme le flux dans le bloc finally. N'appelle jamais la mthode close() l'intrieur du bloc try/catch juste aprs avoir fini de lire le fichier, mais fais-le dans le bloc finally. Sinon, en cas d'exception, le programme sauterait par-dessus l'instruction close() barre et le flux ne serait pas ferm ! La lecture se termine quand la mthode FileInputStream.read() retourne la valeur ngative -1.
144
import java.io.FileInputStream; import java.io.IOException; public class LecteurOctets { public static void main(String[] args) { FileInputStream monFichier = null; try { // Ouvre un flux pointant sur le fichier monFichier = new FileInputStream("c:\\exercices\\abc.gif"); while (true) { int valeurEntireOctet = monFichier.read(); System.out.print(" " + valeurEntireOctet); if (valeurEntireOctet == -1) { // Nous avons atteint la fin du fichier // Sortons de la boucle break; } } // Fin de la boucle while // monFichier.close(); pas cet endroit } catch (IOException exception) { System.out.println("Impossible de lire le fichier : " + exception.toString()); } finally { try { monFichier.close(); } catch (Exception exception1){ exception1.printStackTrace() ; } System.out.println("Lecture du fichier termine."); }
L'extrait de code suivant crit plusieurs octets, reprsents par des nombres entiers, dans le fichier xyz.dat, l'aide de la classe FileOutputStream :
145
int donnes[] = {56, 230, 123, 43, 11, 37}; FileOutputStream monFichier = null; try { // Ouvre le fichier xyz.dat et y enregistre // les donnes du tableau monFichier = new FileOutputStream("xyz.dat"); for (int i = 0; i < donnes.length; i++) { monFichier.write(donnes[i]); } } catch (IOException exception) { System.out.println("Impossible d'crire dans le fichier :" + exception.toString()); } finally{ try{ monFichier.close(); } catch (Exception exception1) { exception1.printStackTrace(); } }
Flux tampon
Jusqu'ici nous avons lu et crit les donnes un octet la fois, ce qui implique que le programme LecteurOctets devra accder 1000 fois au disque pour lire un fichier de 1000 octets. Mais l'accs aux donnes sur le disque est bien plus lent que la manipulation de donnes en mmoire. Pour minimiser le nombre de tentatives d'accs au disque, Java fournit ce qu'on appelle des tampons (buffers), qui sont des sortes de "rservoirs de donnes". La classe BufferedInputStream permet de remplir rapidement la mmoire tampon avec des donnes de FileInputStream. Un flux tampon charge d'un seul coup dans un tampon en mmoire un gros paquet d'octets depuis un fichier. Ensuite, la mthode read() lit chaque octet dans le tampon beaucoup plus rapidement qu'elle ne le ferait sur le disque.
146
Ton programme peut connecter des flux comme un plombier connecte deux tuyaux. Modifions l'exemple qui lit un fichier. Les donnes sont d'abord dverses du FileInputStream dans le BufferedInputStream, puis passes la mthode read() :
FileInputStream monFichier = null; BufferedInputStream tampon = null; try { monFichier = new FileInputStream("c:\\exercices\\abc.gif"); // Connecte les flux tampon = new BufferedInputStream(monFichier); while (true) { int valeurOctet = tampon.read(); System.out.print(valeurOctet + " "); if (valeurOctet == -1) break; } } catch (IOException exception) { exception.printStackTrace(); } finally { try { tampon.close(); monFichier.close(); } catch(IOException exception1) { exception1.printStackTrace(); } }
Quelle est la taille de ce tampon ? Cela dpend du Java, mais tu peux rgler sa taille et voir si cela rend la lecture de fichier un peu plus rapide. Par exemple, pour affecter au tampon une taille de 5000 octets, utilise le constructeur deux arguments :
BufferedInputStream tampon = new BufferedInputStream(monFichier, 5000);
Les flux tampon ne modifient pas le type de lecture ; ils la rendent seulement plus rapide.
147
Pour t'assurer que tous les octets du tampon sont envoys au fichier, appelle la mthode flush() (vider) lorsque l'criture dans le BufferedOutputStream est termine.
Programmation Java pour les enfants, les parents et les grands-parents public static void main(String[] arguments)
148
Effectivement, c'est un tableau de String que Java passe la mthode main(). Si tu lances un programme sans aucun argument sur la ligne de commande, ce tableau est vide. Dans le cas contraire, le nombre d'lments de ce tableau est exactement le mme que celui des arguments passs au programme sur la ligne de commande. Voyons comment utiliser ces arguments de ligne de commande dans une classe trs simple qui ne fait que les afficher :
public class TestArguments { public static void main(String[] arguments) { // Combien d'arguments m'a-t-on fourni ? int nombreArguments = arguments.length; for (int i = 0; i < nombreArguments; i++) { System.out.println("On m'a fourni " + arguments[i]); } } }
La capture d'cran suivante montre ce qu'il se passe si on excute ce programme avec deux arguments xyz.gif et 250. La valeur xyz.gif est place par Java dans l'lment arguments[0] et la seconde dans arguments[1].
Les arguments de la ligne de commande sont toujours passs un programme comme des Strings. Il est de la responsabilit du programme de convertir les donnes dans le type de donnes appropri. Par exemple :
int monScore = Integer.parseInt(arguments[1]);
C'est toujours une bonne chose de vrifier si la ligne de commande contient le bon nombre d'arguments. Fais-le au tout dbut de la mthode main(). Si le programme ne reoit pas les arguments attendus, il doit le signaler en affichant un message bref et s'arrter immdiatement en utilisant la mthode spciale System.exit():
149
public static void main(String[] arguments) { if (arguments.length != 2) { System.out.println( "Merci de fournir deux arguments, par exemple : "); System.out.println("java TestArguments xyz.gif 250"); // Sortie du programme System.exit(0);
A la fin de ce chapitre, tu devras crire un programme qui copie des fichiers. Pour que ce programme fonctionne avec n'importe quels fichiers, les noms des fichiers source et destination doivent tre passs au programme en tant qu'arguments de la ligne de commande. Tu peux tester tes programmes dans Eclipse, qui permet aussi de fournir des arguments de ligne de commande tes programmes. Dans la fentre Excuter, slectionne l'onglet (x)=Arguments et entre les valeurs requises dans la bote Arguments de programme.
150
La bote Arguments VM est utilise pour passer des paramtres Java. Ces paramtres permettent de demander plus de mmoire pour ton programme, rgler finement la performance de Java Tu trouveras dans la section Autres lectures la rfrence d'un site web qui dcrit ces paramtres en dtail.
cre
le
fichier
Excute le programme LecteurScores ci-dessous et il affichera le contenu de ce fichier. Ajoute d'autres lignes au fichier de scores et excute nouveau le programme pour vrifier que les nouvelles lignes sont aussi affiches.
Programmation Java pour les enfants, les parents et les grands-parents import java.io.FileReader; import java.io.BufferedReader; import java.io.IOException; public class LecteurScores { public static void main(String[] arguments) { FileReader monFichier = null; BufferedReader tampon = null; try { monFichier = new FileReader("c:\\scores.txt"); tampon = new BufferedReader(monFichier); while (true) { // Lit une ligne de scores.txt String ligne = tampon.readLine(); // Vrifie la fin de fichier if (ligne == null) break; System.out.println(ligne); } // Fin du while } catch (IOException exception) { exception.printStackTrace(); } finally { try { tampon.close(); monFichier.close(); } catch(IOException exception1) { exception1.printStackTrace(); } } } // Fin de main }
151
Si ton programme doit crire un fichier texte sur un disque, utilise l'une des mthodes write() surcharges de la classe FileWriter. Ces mthodes permettent d'crire un caractre, un String ou un tableau entier de caractres. FileWriter possde plusieurs constructeurs surchargs. Si tu ouvres un fichier en criture en ne fournissant que son nom, ce fichier sera remplac par un nouveau chaque fois que tu excuteras le programme :
FileWriter fichierSortie = new FileWriter("c:\\scores.txt");
Si tu souhaites ajouter des donnes la fin d'un fichier existant, utilise le constructeur deux arguments (true signifie ici mode ajout) :
FileWriter fichierSortie = new FileWriter("c:\\scores.txt", true);
152
La classe EnregistreurScores crit trois lignes dans le fichier c:\scores.txt partir du tableau scores.
import java.io.FileWriter; import java.io.BufferedWriter; import java.io.IOException; public class EnregistreurScores { public static void main(String[] arguments) { FileWriter monFichier = null; BufferedWriter tampon = null; String[] scores = new String[3]; // Entre des scores dans le tableau scores[0] = "M. Dupont 240"; scores[1] = "M. Durand 300"; scores[2] = "M. Pemieufer 190"; try { monFichier = new FileWriter("c:\\scores.txt"); tampon = new BufferedWriter(monFichier); for (int i = 0; i < scores.length; i++) { // Ecrit le tableau de chanes dans scores.txt tampon.write(scores[i]); System.out.println("Ecriture de : " + scores[i]); } System.out.println("Ecriture du fichier termine."); } catch (IOException exception) { exception.printStackTrace(); } finally { try { tampon.flush(); tampon.close(); monFichier.close(); } catch (IOException e1) { e1.printStackTrace(); } } } // Fin de main
153
vrifier si le fichier existe, etc. Mettons que ton programme enregistre des donnes dans un fichier et qu'il ait besoin d'afficher un message pour avertir l'utilisateur si ce fichier existe dj. Pour ce faire, tu dois crer une instance de l'objet File en lui donnant le nom du fichier, puis appeler la mthode exists(). Si cette mthode retourne true, le fichier a t trouv et tu dois afficher un message d'avertissement. Sinon, c'est que ce fichier n'existe pas.
File unFichier = new File("abc.txt"); if (unFichier.exists()) { // Affiche un message ou utilise un JOptionPane // pour afficher un avertissement. }
Le constructeur de la classe File ne cre pas rellement un fichier il cre juste en mmoire une instance de cet objet qui pointe sur le fichier rel. Si tu dois vraiment crer un fichier sur le disque, utilise la mthode createNewFile(). Voici quelques unes des mthodes utiles de la classe File. Nom de la mthode createNewFile() Fonctionnalit Cre un nouveau fichier, vide, du nom utilis pour l'instanciation de la classe File. Ne cre un nouveau fichier que s'il n'existe pas dj un fichier du mme nom. Supprime un fichier ou un rpertoire. Renomme un fichier. Retourne la longueur d'un fichier en octets. Retourne true si le fichier existe. Retourne un tableau de chanes contenant les noms des fichiers/rpertoires contenus dans un rpertoire donn. Retourne l'heure et la date de dernire modification du fichier. Cre un rpertoire.
lastModified() mkDir()
L'extrait de code ci-dessous renomme le fichier clients.txt en clients.txt.bak. Si le fichier .bak existe dj, il est remplac.
154
File fichier = new File("clients.txt"); File sauvegarde = new File("clients.txt.bak"); if (sauvegarde.exists()) { sauvegarde.delete(); } fichier.renameTo(sauvegarde);
Mme si nous n'avons travaill dans ce chapitre que sur des fichiers situs sur le disque de ton ordinateur, Java te permet de crer des flux pointant vers des machines distantes sur un rseau d'ordinateurs. Ces ordinateurs peuvent tre situs assez loin les uns des autres. Par exemple, la NASA utilise Java pour contrler les robots de la mission Mars Rovers et je suis sr qu'ils se sont contents de pointer leurs flux sur Mars.
155
Autres lectures
1. Options de ligne de commande Java
http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/java.html
Exercices
Ecris le programme de copie de fichier FileCopy en combinant les fragments de code de la section sur les flux d'octets. Ouvre deux flux (entre et sortie) et appelle les mthodes read() et write() dans la mme boucle. Utilise les arguments de la ligne de commande pour passer au programme les noms des fichiers source et cible, par exemple :
java CopieFichier c:\temp\scores.txt c:\sauvegardes\scores2.txt
156
Quand l'utilisateur clique sur le bouton Copier, le code de la mthode actionPerformed() doit copier le fichier slectionn. Essaie de rutiliser le code de l'exercice prcdent sans effectuer de copier/coller.
157
diffrents dans les chapitres prcdents. Nous avons mme cr un jeu de morpion. Mais j'ai laiss de ct d'importants lments et techniques Java et il est temps de corriger ces omissions.
La sortie de ces lignes peut ressembler ceci7 : Nous sommes le 23 juin 2005 La classe SimpleDateFormat permet d'afficher les dates et les heures selon diffrents formats. D'abord, tu dois crer une instance de cette classe avec le format souhait. Ensuite, appelle sa mthode format() en lui passant un objet Date en argument. Le programme suivant formate et affiche la date courante sous diffrents formats.
7
NDT le code minimal est encore plus simple pour nos amis anglophones, qui n'ont pas besoin de faire appel SimpleDateFormat ; la ligne System.out.println("Date anglaise " + maintenant); imprimerait par exemple Date anglaise Thu Jun 23 11:48:55 CEST 2005.
158
import java.util.Date; import java.text.SimpleDateFormat; public class MonFormatDate { public static void main( String [] args ) { // Cre un objet Date // et l'affiche dans le format par dfaut Date maintenant = new Date(); System.out.println("Nous sommes le : " + SimpleDateFormat.getDateInstance().format(maintenant)); // Affiche la date comme ceci : 23-06-05 SimpleDateFormat formatDate = new SimpleDateFormat("dd-MM-yy"); String dateFormate = formatDate.format(maintenant); System.out.println("Nous sommes le (jj-MM-aa) : " + dateFormate); // Affiche la date comme ceci : 23-06-2005 formatDate = new SimpleDateFormat("dd/MM/yyyy"); dateFormate = formatDate.format(maintenant); System.out.println("Nous sommes le (jj/MM/aaaa) : " + dateFormate); // Affiche la date comme ceci : jeudi 23 juin 2005 formatDate = new SimpleDateFormat("EEEE d MMM yyyy"); dateFormate = formatDate.format(maintenant); System.out.println("Nous sommes le (JJJJ jj MMMM aaaa) : " + dateFormate); // Affiche l'heure comme ceci : 20h 30m 17s formatDate = new SimpleDateFormat("kk'h' mm'm' ss's'"); dateFormate = formatDate.format(maintenant); System.out.println("Il est (HHh MMm SSs) : " + dateFormate);
La documentation Java de la classe SimpleDateFormat dcrit d'autres formats. Tu peux aussi trouver d'autres mthodes de gestion des dates dans la classe java.util.Calendar.
159
Surcharge de mthode
Il peut y avoir, dans une mme classe, plusieurs mthodes de mme nom mais ayant des listes d'arguments diffrentes. C'est ce qu'on appelle la surcharge de mthode (method overloading). Par exemple, la mthode println() de la classe System peut tre appele avec diffrents types d'arguments : String, int, char, etc.
System.out.println("Bonjour"); System.out.println(250); System.out.println('A');
Mme s'il semble que l'on appelle trois fois la mme mthode println(), il s'agit en fait de trois mthodes diffrentes. Tu te demandes peut-tre pourquoi on ne cre pas des mthodes avec des noms diffrents, par exemple printString(), printInt() et printChar() ? Une raison en est qu'il est plus facile de mmoriser un nom de mthode d'affichage plutt que plusieurs. Il y a d'autres raisons justifiant l'utilisation de la surcharge de mthode, mais elles sont un peu compliques expliquer et sont abordes dans des livres d'un niveau plus avanc. Tu te rappelles notre classe Poisson du Chapitre 4 et sa mthode plonger(), qui attend un argument :
public int plonger(int combienDePlus)
Crons une autre version de cette mthode qui n'aura pas besoin d'argument. Cette mthode va forcer le poisson plonger de cinq mtres, sauf si la profondeur courante vient dpasser 100 mtres. La nouvelle version de la classe Poisson a une nouvelle variable invariante, PROFONDEUR_PLONGEE, dont la valeur est cinq. La classe Poisson a maintenant deux mthodes plonger() surcharges.
160
public class Poisson extends AnimalFamilier { int profondeurCourante = 0; final int PROFONDEUR_PLONGEE = 5; public int plonger() { profondeurCourante = profondeurCourante + PROFONDEUR_PLONGEE; if (profondeurCourante > 100) { System.out.println("Je suis un petit" + " poisson et je ne peux pas plonger" + " plus profond que 100 mtres"); profondeurCourante = profondeurCourante - PROFONDEUR_PLONGEE; } else { System.out.println("Plonge de " + PROFONDEUR_PLONGEE + " mtres"); System.out.println("Je suis " + profondeurCourante + " mtres sous le niveau de la mer"); } return profondeurCourante; } public int plonger(int combienDePlus) { profondeurCourante = profondeurCourante + combienDePlus; if (profondeurCourante > 100) { System.out.println("Je suis un petit" + " poisson et je ne peux pas plonger" + " plus profond que 100 mtres"); profondeurCourante = profondeurCourante - combienDePlus; } else { System.out.println("Plonge de " + combienDePlus + " mtres"); System.out.println("Je suis " + profondeurCourante + " mtres sous le niveau de la mer"); } return profondeurCourante; } public String dire(String unMot){ return "Ne sais-tu pas que les poissons ne" + " parlent pas ?"; } // Constructeur Poisson(int positionDpart) { profondeurCourante = positionDpart; } }
161
public class MatrePoisson { public static void main(String[] args) { Poisson monPoisson = new Poisson(20); monPoisson.plonger(2); monPoisson.plonger(); // nouvelle mthode surcharge
Les constructeurs peuvent aussi tre surchargs, mais l'un d'entre eux seulement est utilis lorsqu'un objet est cr. Java appelle le constructeur qui a la bonne liste d'arguments. Par exemple, si tu ajoutes un constructeur sans argument la classe Poisson, MatrePoisson peut en crer une instance par l'un des moyens suivants :
Poisson monPoisson = new Poisson(20);
ou
Poisson monPoisson = new Poisson();
162
l'utilisateur. Une fois que l'utilisateur a tap un ou plusieurs caractres et appuy sur la touche Entre, Java place ces caractres dans l'objet InputStream pour les passer au programme.
import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; public class MatrePoisson { public static void main(String[] args) { Poisson monPoisson = new Poisson(20); String chaneNombreDeMtres = ""; int entierNombreDeMtres; // Cre un lecteur de flux d'entre connect // System.in et le passe au lecteur tampon BufferedReader entreStandard = new BufferedReader (new InputStreamReader(System.in)); // Continue plonger tant que l'utilisateur // ne tape pas "Q" while (true) { System.out.println("Prt plonger. De combien ?"); try { chaneNombreDeMtres = entreStandard.readLine(); if (chaneNombreDeMtres.equals("Q")) { // Sort du programme System.out.println("Au revoir !"); System.exit(0); } else { // Convertit chaneNombreDeMtres en entier // et plonge de la valeur de entierNombreDeMtres entierNombreDeMtres = Integer.parseInt(chaneNombreDeMtres); monPoisson.plonger(entierNombreDeMtres); } } catch (IOException e) { e.printStackTrace(); } } // Fin du while } // Fin de main
163
En premier lieu, MatrePoisson cre un flux BufferedReader connect l'entre standard System.in. Il affiche ensuite le message "Prt plonger. De combien ?" et la mthode readLine() met le programme en attente jusqu' ce que l'utilisateur appuie sur Entre. La valeur saisie est passe au programme sous forme de String, que MatrePoisson convertit en entier avant d'appeler la mthode plonger() de la classe Poisson. Ces actions sont rptes en boucle jusqu' ce que l'utilisateur tape la lettre Q pour quitter le programme. La ligne chaneNombreDeMtres.equals("Q") compare la valeur de la variable de type String chaneNombreDeMtres avec la lettre Q. Nous avons utilis la mthode readLine() pour lire en une seule fois toute la ligne entre par l'utilisateur, mais il existe une autre mthode, System.in.read(), qui permet de traiter les entres de l'utilisateur caractre par caractre.
164
Appuie sur le bouton Fin et Eclipse gnre un code qui inclut une ligne contenant le nom du paquetage.
package crans; public class TablePingPong { public static void main(String[] args) { } }
A propos, si ta classe inclut une ligne avec le mot-cl package, tu n'as le droit d'crire que des commentaires au-dessus de cette ligne. Comme chaque paquetage est stock dans un rpertoire diffrent du disque, Eclipse cre le rpertoire crans et y place le fichier TablePingPong.java. Vrifie il doit y avoir sur ton disque un rpertoire c:\eclipse\plan de travail\Ping Pong\crans,
165
TablePingPong.java
et
Cre maintenant une autre classe, nomme MoteurPingPong, et indique moteur comme nom de paquetage. Le projet Ping Pong contient maintenant deux paquetages :
Puisque nos deux classes sont situes dans deux paquetages (et rpertoires) diffrents, la classe TablePingPong ne peut voir la classe MoteurPingPong que si tu ajoutes une instruction import.
Programmation Java pour les enfants, les parents et les grands-parents package crans; import moteur.MoteurPingPong; public class TablePingPong { public static void main(String[] args) { MoteurPingPong moteurJeu = new MoteurPingPong(); }
166
Non seulement les paquetages Java t'aident-ils mieux organiser tes classes, mais ils peuvent aussi tre utiliss pour limiter l'accs leurs classes par des "trangers" installs dans d'autres paquetages.
Niveaux d'accs
Les classes, mthodes et variables membres Java peuvent avoir les niveaux d'accs public, private, protected et package. Notre classe MoteurPingPong a le niveau d'accs public, ce qui signifie que n'importe quelle classe peut y accder. Faisons une petite exprience : tons le mot-cl public de la dclaration de la classe MoteurPngPong. La classe TablePingPong ne peut mme plus compiler ; le message d'erreur MoteurPingPong ne peut pas tre rsolu ou ne correspond pas un type signifie que la classe TablePingPong ne voit plus la classe MoteurPingPong. Si aucun niveau d'accs n'est spcifi, la classe a un niveau d'accs package, c'est--dire qu'elle n'est accessible qu'aux classes du mme paquetage.
De la mme faon, si tu oublies de donner un accs public aux mthodes de la classe MoteurPingPong, TablePingPong se plaindra en disant que ces mthodes ne sont pas visibles. Tu verras comment les niveaux d'accs sont utiliss dans le prochain chapitre, en crant le jeu de ping pong.
167
Le niveau d'accs private est utilis pour cacher les variables ou mthodes de la classe aux yeux du monde extrieur. Pense une voiture : la plupart des gens n'ont aucune ide de tout ce qui se cache sous le capot ou de ce qui se passe quand le conducteur appuie sur la pdale de frein. Examine l'exemple de code suivant - en Java, on peut dire que l'objet Voiture expose une seule mthode publique freiner(), qui en interne peut appeler plusieurs autres mthodes qu'un conducteur n'a pas besoin de connatre. Par exemple, si le conducteur appuie trop fort sur la pdale, l'ordinateur de bord peut mettre en action des freins spciaux anti-blocage. J'ai dj dit auparavant que des programmes Java contrlaient des robots aussi compliqus que ceux de la mission Mars Rovers, sans mme parler des simples voitures.
Programmation Java pour les enfants, les parents et les grands-parents public class Voiture { // Cette variable prive ne peut tre utilise // qu' l'intrieur de cette classe private String conditionFreins; // La mthode publique freiner() appelle des mthodes // prives pour dcider quels freins utiliser public void freiner(int pressionPdale) { boolean utiliserFreinsNormaux; utiliserFreinsNormaux = vrifierBesoinABS(pressionPdale); if (utiliserFreinsNormaux == true) { utiliserFreinsNormaux(); } else { utiliserFreinsAntiBlocage(); } } // Cette mthode prive ne peut tre appele // qu' l'intrieur de cette classe private boolean vrifierBesoinABS(int pression) { if (pression > 100) { return true; } else { return false; } } // Cette mthode prive ne peut tre appele // qu' l'intrieur de cette classe private void utiliserFreinsNormaux() { // Code qui envoie un signal aux freins normaux }
168
// Cette mthode prive ne peut tre appele // qu' l'intrieur de cette classe private void utiliserFreinsAntiBlocage() { // Code qui envoie un signal aux freins anti-blocage }
Le dernier mot-cl Java pour contrler le niveau d'accs est protected. Si tu utilises ce mot-cl dans la signature d'une mthode, celle-ci est visible l'intrieur de la classe, de ses sous-classes et des autres classes du mme paquetage. Mais elle n'est pas utilisable par les classes indpendantes situes dans d'autres paquetages. L'une des caractristiques principales des langages orients objet est appele encapsulation, c'est--dire la capacit cacher et protger les lments d'une classe.
169
Quand tu conois une classe, cache les mthodes et les variables membres qui ne doivent pas tre visibles de l'extrieur. Si les concepteurs de voitures ne masquaient pas une partie des contrles de la mcanique, le conducteur devrait grer des centaines de boutons, d'interrupteurs et de jauges.
Dans la section suivante, la classe Score masque ses attributs en les dclarant private.
170
au lieu de : Score.affecterScore(250); Essaie d'largir ton horizon. Imagine que, plus tard, nous dcidions que notre programme doive jouer un morceau de musique quand un joueur atteint le score de 500 ? Si la classe Score a une mthode affecterScore(), il suffit de modifier cette mthode en lui ajoutant le code qui vrifie le score et joue de la musique si ncessaire. La classe appelante appelle toujours de la mme faon la version musicale de la mthode affecterScore(). Si la classe appelante affectait directement la valeur, elle devrait elle-mme implanter les changements musicaux. Et si tu voulais rutiliser la classe Score dans deux programmes de jeu diffrents ? En utilisant la modification directe d'attributs, tu devrais implanter les changements dans deux classes appelantes, alors qu'une mthode d'affectation encapsule les changements qui sont immdiatement fonctionnels pour chaque classe appelante.
Programmation Java pour les enfants, les parents et les grands-parents import java.util.Date; import java.text.SimpleDateFormat; public class Score { private String prnom; private String nom; private int score; private Date dateDernirePartie;
171
public String lirePrnom() { return prnom; } public void affecterPrnom(String prnom) { this.prnom = prnom; } public String lireNom() { return nom; } public void affecterNom(String nom) { this.nom = nom; } public int lireScore() { return score; } public void affecterScore(int score) { this.score = score; } public Date lireDateDernirePartie() { return dateDernirePartie; } public void affecterDateDernirePartie(Date dateDernirePartie) { this.dateDernirePartie = dateDernirePartie; } // Concatne tous les attributs en une chane // et y ajoute un caractre fin de ligne. // Cette mthode est pratique, par exemple pour // afficher toutes les valeurs d'un coup, comme ceci : // System.out.println(myScore.toString()); // NDT : comme cette mthode surcharge Object.toString(), // tu es certain que la bonne reprsentation de Score // est utilise partout o Java en a besoin (c'est pour // cela que nous ne l'avons pas appele convertirEnString). public String toString() { String chaneScore = prnom + " " + nom + " " + score + " " + SimpleDateFormat. getDateInstance().format(dateDernirePartie) + System.getProperty("line.separator"); return chaneScore; }
Le programme EnregistreurScores2 cre des instances de l'objet Score et affecte des valeurs leurs attributs.
Programmation Java pour les enfants, les parents et les grands-parents import import import import java.io.FileWriter; java.io.BufferedWriter; java.io.IOException; java.util.Date;
172
public class EnregistreurScores2 { /** La mthode main excute les actions suivantes : 1. Cre une instance de tableau 2. Cre les objets Score et les stocke dans le tableau 3. Ecrit les donnes de scores dans un fichier */ public static void main(String[] args) { FileWriter monFichier = null; BufferedWriter tampon = null; Date ceJour = new Date(); Score scores[] = new Score[3]; // Joueur n1 scores[0]= new Score(); scores[0].affecterPrnom("Jean"); scores[0].affecterNom("Dupont"); scores[0].affecterScore(250); scores[0].affecterDateDernirePartie(ceJour); // Joueur n2 scores[1]= new Score(); scores[1].affecterPrnom("Anne"); scores[1].affecterNom("Durand"); scores[1].affecterScore(300); scores[1].affecterDateDernirePartie(ceJour); // Joueur n3 scores[2]= new Score(); scores[2].affecterPrnom("Eskil"); scores[2].affecterNom("Pemieufer"); scores[2].affecterScore(190); scores[2].affecterDateDernirePartie(ceJour);
173
try { monFichier = new FileWriter("c:\\scores2.txt"); tampon = new BufferedWriter(monFichier); for (int i = 0; i < scores.length; i++) { // Convertit chaque Score en String // et l'crit dans scores2.txt tampon.write(scores[i].toString()); System.out.println("Ecriture des donnes de " + scores[i].lireNom()); } System.out.println("Ecriture du fichier termine"); } catch (IOException e) { e.printStackTrace(); } finally { try { tampon.flush(); tampon.close(); monFichier.close(); } catch (IOException e1) { e1.printStackTrace(); } }
} }
Classe EnregistreurScores2 (partie 2 de 2) Si un programme essaie d'accder un lment du tableau dont l'indice est trop grand, par exemple ici scores[5].lireNom(), Java lve l'exception ArrayIndexOutOfBoundsException.
Classe ArrayList
Le paquetage java.util contient des classes plutt pratiques pour stocker plusieurs instances (des collections) d'objets en mmoire. Certaines des collections populaires de ce paquetage sont les classes ArrayList (liste stocke dans un tableau), Vector (vecteur), Hashtable et HashMap (deux sortes de tables de hachage) et List (liste). Je vais te montrer comment utiliser la classe java.util.ArrayList. L'inconvnient des tableaux normaux est que tu dois connatre l'avance le nombre d'lments du tableau. Rappelle-toi, pour crer une instance de tableau, tu dois mettre un nombre entre les crochets :
String[] mesAmis = new String[5];
174
La classe ArrayList n'a pas cette contrainte. Tu peux crer une instance de cette collection sans savoir combien d'objets il y aura : ajoute simplement de nouveaux lments quand tu en as besoin. Pourquoi utiliser des tableaux, alors, et ne pas utiliser systmatiquement des ArrayList ? Malheureusement, rien n'est gratuit et il faut payer le prix du confort : ArrayList est un peu plus lent qu'un tableau normal et on ne peut y stocker que des objets, pas des nombres de type int. Pour crer et remplir un objet ArrayList, il faut l'instancier, crer des instances des objets que tu souhaites y stocker, puis les ajouter l'ArrayList en appelant sa mthode add(). Le petit programme cidessous remplit un ArrayList avec des objets de type String puis affiche le contenu de cette collection.
import java.util.ArrayList; public class DmoArrayList { public static void main(String[] args) { // Cre et remplit un ArrayList ArrayList amis = new ArrayList(); amis.add("Marie"); amis.add("Anne"); amis.add("David"); amis.add("Rmi"); // Combien d'amis y a-t-il ? int nombreAmis = amis.size(); // Affiche le contenu de l'ArrayList for (int i = 0; i < nombreAmis; i++) { System.out.println("L'ami(e) n" + i + " est " + amis.get(i)); } } }
La mthode get() extrait d'un ArrayList l'lment situ une position donne. Puisqu'on peut stocker n'importe quel objet dans une collection, la mthode get() renvoie chaque lment comme un Object Java ; le programme a la responsabilit de convertir explicitement cet objet en un type de donnes appropri. Nous n'avons pas besoin de le faire dans l'exemple prcdent uniquement parce que
175
nous stockons des objets de type String dans la collection amis et que Java convertit automatiquement Object en String. Mais si tu stockes d'autres objets dans un ArrayList, par exemple des instances de la classe Poisson, le code correct pour ajouter et extraire un Poisson ressemble plutt celui du programme BocalAPoissons cidessous. Le programme cre une paire d'instances de la classe Poisson, affecte des valeurs leurs attributs couleur, poids et profondeurCourante, puis les stocke dans l'ArrayList bocalAPoissons. Le programme extrait ensuite les objets de cette collection, convertit chacun d'entre eux en Poisson et affiche les valeurs de ses attributs.
import java.util.ArrayList; public class BocalAPoissons { public static void main(String[] args) { ArrayList bocalAPoissons = new ArrayList(); Poisson lePoisson; Poisson unPoisson = new Poisson(20); unPoisson.couleur = "Rouge"; unPoisson.poids = 1; bocalAPoissons.add(unPoisson); unPoisson = new Poisson(10); unPoisson.couleur = "Vert"; unPoisson.poids = 2; bocalAPoissons.add(unPoisson); int nombrePoissons = bocalAPoissons.size(); for (int i = 0; i < nombrePoissons; i++) { lePoisson = (Poisson) bocalAPoissons.get(i); System.out.println("Attrap le poisson " + lePoisson.couleur + " qui pse " + lePoisson.poids + " livres. Profondeur : " + lePoisson.profondeurCourante); } } }
Maintenant que tu connais les niveaux d'accs Java, on peut modifier un peu les classes AnimalFamilier et Poisson. Des variables telles que age, couleur, poids et taille devraient tre dclares comme protected et la variable profondeurCourante devrait tre private. Tu dois ajouter de nouvelles mthodes publiques, telles que
176
lireAge() pour renvoyer la valeur de la variable affecterAge() pour affecter la valeur de cette variable.
age
et
Les programmeurs lgants ne permettent pas une classe de modifier directement les proprits d'une autre ; la classe doit fournir les mthodes qui modifient ses internes. C'est pourquoi la classe Score de la section prcdente est conue avec des variables private, qui peuvent tre modifies et lues avec les mthodes d'accs appropries. Dans ce chapitre, je t'ai prsent divers lments et techniques Java qui semblent sans relation les uns avec les autres. Mais tous ces lments sont frquemment utiliss par les programmeurs Java professionnels. Aprs avoir effectu les exercices pratiques de ce chapitre, tu devrais mieux comprendre comment tous ces lments fonctionnent ensemble.
177
Autres lectures
1. Collections Java :
http://java.sun.com/docs/books/tutorial/collections/intro/
2. Classe ArrayList:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.htm l
3. Classe Vector:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Vector.html
4. Classe Calendar:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Calendar.html
Exercices
1. Ajoute un constructeur surcharg sans argument la classe Poisson. Ce constructeur doit initialiser 10 mtres la profondeur de dpart. La classe MatrePoisson va crer une instance de l'objet Poisson comme ceci :
Poisson monPoisson = new Poisson();
2. Ajoute un constructeur quatre arguments la classe Score. Cre un programme EnregistreurScores3 qui gnre les instances des objets Score non pas en utilisant des mthodes d'affectation, mais plutt au moment de la cration des scores, comme ceci :
Score unScore = new Score("Jean", "Dupont", 250, ceJour);
178
composants AWT et Swing. Je vais maintenant te montrer comment dessiner et dplacer dans une fentre des objets tels que des ovales, des rectangles et des lignes. Nous verrons aussi comment traiter les vnements de la souris et du clavier. Pour rendre plus amusant ces sujets ennuyeux, nous allons explorer toutes ces choses en crant un jeu de ping-pong. Il y aura deux joueurs, que j'appelle l'enfant et l'ordinateur.
Stratgie
Commenons par les rgles du jeu : 1. La partie se poursuit jusqu' ce que l'un des joueurs (l'enfant ou l'ordinateur) atteigne le score de 21. 2. Les mouvements de la raquette de l'enfant sont contrls par la souris. 3. Le score est affich en bas de la fentre. 4. Une nouvelle partie commence quand un joueur appuie sur la touche N du clavier. Q met fin la partie. S effectue le service. 5. Seul l'enfant peut servir. 6. Pour gagner un point, la balle doit dpasser la ligne la verticale de la raquette (sans avoir t bloque par la raquette). 7. Quand l'ordinateur renvoie la balle, elle ne peut se dplacer qu'horizontalement vers la droite. 8. Si la balle rencontre la raquette de l'enfant dans la moiti suprieure de la table, elle doit se dplacer dans la direction haut-gauche. Si la balle se trouve dans la partie infrieure de la table, elle doit se dplacer dans la direction bas-gauche.
179
Tu dois penser que a va tre difficile programmer. L'astuce consiste dcouper une tche complexe en un ensemble de tches plus petites et plus simples, puis d'essayer de les rsoudre une par une. Cette mthode de travail est appele rflexion analytique (analytical thinking). Elle est utile non seulement en programmation, mais aussi dans la vie en gnral : ne sois pas frustr si tu ne peux pas atteindre un objectif important, mais dcoupe-le en un ensemble d'objectifs plus petits que tu peux atteindre un par un ! C'est pour cette raison que la premire version du jeu n'implante que quelques-unes de ces rgles : elle dessine la table, dplace la raquette et affiche les coordonnes du pointeur de la souris quand on clique.
Au lieu de te contenter de dire "mon ordinateur ne fonctionne pas" (vaste problme), essaye de voir ce qui ne va pas exactement (trouve un problme plus petit). 1. L'ordinateur est-il branch au secteur (oui/non) ? Oui. 2. Quand je mets en route l'ordinateur, l'cran avec toutes ses icnes est-il affich (oui/non) ? Oui. 3. Puis-je dplacer le pointeur de la souris sur l'cran (oui/non) ? Non. 4. Le cble de la souris est-il branch correctement (oui/non) ? Non. Il suffit de brancher la souris et l'ordinateur fonctionnera nouveau ! Un gros problme a t rduit la simple correction du branchement du cble de la souris.
Code
Ce jeu est constitu des trois classes suivantes :
La classe TableVertePingPong se charge de la partie visuelle. Pendant la partie, elle affiche la table, les raquettes et la balle. La classe MoteurJeuPingPong est responsable du calcul des coordonnes de la balle et des raquettes, du dmarrage et de l'arrt de la partie, et du service. Cette classe passe les coordonnes des composants la classe TableVertePingPong, qui rafrachit son affichage en fonction de celles-ci. L'interface ConstantesDuJeu contient les dclarations de toutes les constantes ncessaires au jeu, telles que la largeur et la hauteur de la table, les positions de dpart des raquettes, etc..
180
Afficher une table de ping pong verte. Afficher les coordonnes du pointeur de la souris quand on clique. Dplacer la raquette de l'enfant vers le haut et vers le bas.
Le code de notre classe TableVertePingPong, qui est une sous-classe de la classe Swing JPanel, se trouve deux pages plus bas. Regarde-le pendant que tu lis le texte ci-dessous. Puisque notre jeu a besoin de connatre les coordonnes exactes du pointeur de la souris, le constructeur de la classe TableVertePingPong cre une instance du rcepteur d'vnements MoteurJeuPingPong. Cette classe effectue certaines actions quand l'enfant clique ou simplement dplace la souris. La mthode ajouteAuCadre() cre un libell qui affichera les coordonnes de la souris. Cette classe n'est pas une applet, raison pour laquelle elle utilise la mthode paintComponent() au lieu de la mthode paint(). Cette mthode est appele soit par Java quand il est ncessaire de rafrachir la fentre, soit quand notre programme appelle la mthode repaint(). Tu as bien lu, la mthode repaint() appelle en interne la mthode paintComponent() et fournit ta classe un objet Graphics pour que tu puisses dessiner dans la fentre. Nous appellerons cette mthode chaque fois que nous aurons recalcul les
181
coordonnes des raquettes ou de la balle pour les afficher au bon endroit. Pour dessiner une raquette, il faut lui affecter une couleur, puis remplir un rectangle avec cette peinture l'aide de la mthode fillRect() (remplir rectangle). Cette mthode doit connatre les coordonnes X et Y du coin haut gauche du rectangle, ainsi que sa largeur et sa hauteur en pixels. La balle est dessine l'aide de la mthode fillOval() (remplir ovale), qui a besoin de connatre les coordonnes du centre de l'ovale, sa hauteur et sa largeur. Si la hauteur et la largeur de l'ovale sont identiques, c'est un cercle. Dans une fentre, la coordonne X augmente de la gauche vers la droite et la coordonne Y augmente du haut vers le bas. Par exemple, les coordonnes des coins de ce rectangle de largeur 100 pixels et de hauteur 70 sont indiques entre parenthses : X
(0,0) (100,0)
Y
(0,70) (100,70)
Une autre mthode intressante est la mthode getPreferredSize(). Nous crons une instance de la classe Swing Dimension pour fixer la taille de la table. Java a besoin de connatre les dimensions de la fentre et appelle pour cela la mthode getPreferredSize() de l'objet TableVertePingPong. Cette mthode retourne Java un objet Dimension que nous avons cr dans le code en fonction de la taille de notre table. Les deux classes table et moteur utilisent des valeurs constantes, qui ne changent jamais. Par exemple, la classe TableVertePingPong utilise la largeur et la hauteur de la table et MoteurJeuPingPong doit connatre les incrments de dplacement de la balle (plus l'incrment est petit, plus le mouvement est fluide). Il est commode de runir toutes les constantes (variables final) au sein d'une interface. Dans notre jeu, l'interface se nomme ConstantesDuJeu. Si une classe a besoin de ces valeurs, il suffit d'ajouter implements ConstantesDuJeu la dclaration de la classe pour utiliser n'importe laquelle des variables final de cette interface comme si elle tait dclare dans la classe elle-mme. C'est pourquoi nos deux classes table et moteur implantent l'interface ConstantesDuJeu. Si tu dcides de modifier la taille de la table, de la balle ou des raquettes, tu n'as besoin de le faire qu' un endroit : dans l'interface ConstantesDuJeu. Examinons le code de la classe TableVertePingPong et de l'interface ConstantesDuJeu.
182
package crans; import import import import import import import import import import import javax.swing.JPanel; javax.swing.JFrame; javax.swing.BoxLayout; javax.swing.JLabel; javax.swing.WindowConstants; java.awt.Point; java.awt.Dimension; java.awt.Container; java.awt.Graphics; java.awt.Color; moteur.MoteurJeuPingPong;
/** * Cette classe dessine une table de ping-pong verte * et affiche les coordonnes du point o l'utilisateur * a cliqu. */ public class TableVertePingPong extends JPanel implements ConstantesDuJeu { JLabel label; public Point point = new Point(0,0); public int raquetteOrdinateur_X = 15; private int raquetteEnfant_Y = RAQUETTE_ENFANT_Y_DEPART; Dimension taillePrfre = new Dimension(LARGEUR_TABLE, HAUTEUR_TABLE); // Cette mthode affecte sa taille au cadre. // Elle est appele par Java. public Dimension getPreferredSize() { return taillePrfre; }
Programmation Java pour les enfants, les parents et les grands-parents // Constructeur. TableVertePingPong() {
183
MoteurJeuPingPong moteurJeu = new MoteurJeuPingPong(this); // Reoit les clics pour l'affichage de leurs coordonnes addMouseListener(moteurJeu); // Reoit les mouvements de la souris pour // le dplacement des raquettes addMouseMotionListener(moteurJeu); } // Ajoute une fentre un panneau contenant cette table et // un JLabel void ajouteAuCadre(Container conteneur) { conteneur.setLayout(new BoxLayout(conteneur, BoxLayout.Y_AXIS)); conteneur.add(this); label = new JLabel("Coordonnes..."); conteneur.add(label); } // Repeint la fentre. Cette mthode est appele par Java // quand il est ncessaire de rafrachir l'cran ou quand // la mthode repaint() est appele par le // MoteurJeuPingPong. public void paintComponent(Graphics contexteGraphique) { super.paintComponent(contexteGraphique); // Dessine la table verte contexteGraphique.setColor(Color.GREEN); contexteGraphique.fillRect( 0, 0, LARGEUR_TABLE, HAUTEUR_TABLE); // Dessine la raquette droite contexteGraphique.setColor(Color.yellow); contexteGraphique.fillRect(RAQUETTE_ENFANT_X_DEPART, raquetteEnfant_Y, 5, 30); // Dessine la raquette gauche contexteGraphique.setColor(Color.blue); contexteGraphique.fillRect( raquetteOrdinateur_X, 100, 5, 30); // Dessine la balle contexteGraphique.setColor(Color.red); contexteGraphique.fillOval(25, 110, 10, 10); // Dessine les lignes contexteGraphique.setColor(Color.white); contexteGraphique.drawRect(10, 10, 300, 200); contexteGraphique.drawLine(160, 10, 160, 210);
184
// Affiche un point sous forme de rectangle de 2x2 pixels if (point != null) { label.setText("Coordonnes (x, y) : " + point.x + ", " + point.y); contexteGraphique.fillRect(point.x, point.y, 2, 2); } } // Affecte sa position courante la raquette de l'enfant public void positionnerRaquetteEnfant_Y(int y) { this.raquetteEnfant_Y = y; } // Retourne la position courante de la raquette de l'enfant public int coordonneRaquetteEnfant_Y() { return raquetteEnfant_Y; } public static void main(String[] args) { // Cre une instance du cadre JFrame monCadre = new JFrame("Table verte de ping-pong"); // Permet la fermeture de la fentre par clic sur la // petite croix dans le coin. monCadre.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); TableVertePingPong table = new TableVertePingPong(); table.ajouteAuCadre(monCadre.getContentPane()); // Affecte sa taille au cadre et le rend visible. monCadre.pack(); monCadre.setVisible(true); } }
Classe TableVertePingPong (partie 3 de 3) Voici l'interface ConstantesDuJeu. Toutes les valeurs des variables sont en pixels. Ecris les noms des variables final en lettres majuscules.
package crans; public interface ConstantesDuJeu { public final int LARGEUR_TABLE = 320; public final int HAUTEUR_TABLE = 220; public final int RAQUETTE_ENFANT_Y_DEPART = 100; public final int RAQUETTE_ENFANT_X_DEPART = 300; public final int HAUT_TABLE = 12; public final int BAS_TABLE = 180; public final int INCREMENT_RAQUETTE = 4; }
Un programme en cours d'excution ne peut pas modifier les valeurs de ces variables, puisqu'elles sont dclares comme final. Mais si, par exemple, tu dcides d'augmenter la taille de la table, tu dois modifier
185
les valeurs de LARGEUR_TABLE et de HAUTEUR_TABLE, puis recompiler l'interface ConstantesDuJeu. Dans ce jeu, les dcisions sont prises par la classe MoteurJeuPingPong, qui implante deux interfaces concernant la souris. MouseListener n'a de code que dans la mthode mousePressed(). A chaque clic, cette mthode dessine un point blanc sur la table et affiche ses coordonnes. En ralit, ce code n'est d'aucune utilit pour notre jeu, mais il te montre d'une faon simple comment obtenir les coordonnes de la souris de l'objet MouseEvent pass au programme par Java. La mthode mousePressed() affecte les coordonnes de la variable point en fonction de la position du pointeur de la souris au moment o l'utilisateur a cliqu. Une fois les coordonnes affectes, elle demande Java de repeindre la table. MouseMotionListener rpond aux mouvements de la souris audessus de la table. Nous utilisons sa mthode mouseMoved() pour dplacer la raquette de l'enfant vers le haut et vers le bas. La mthode mouseMoved() calcule la position suivante de la raquette de l'enfant. Quand le pointeur de la souris se trouve au-dessus de la raquette (la coordonne Y de la souris est infrieure la coordonne Y de la raquette), cette mthode assure que la raquette n'ira pas plus loin que le haut de la table. Quand le constructeur de la table cre l'objet moteur, il lui passe une rfrence l'instance de table (le mot-cl this reprsente une rfrence l'emplacement en mmoire de l'objet TableVertePingPong). Le moteur peut maintenant "parler" la table, par exemple pour affecter de nouvelles coordonnes la balle ou pour repeindre la table si ncessaire. Si cette partie n'est pas claire, tu peux relire la section concernant le passage de donnes entre classes, au Chapitre 6. Dans notre jeu, les raquettes se dplacent verticalement d'une position une autre en utilisant un incrment de quatre pixels, comme le dfinit l'interface ConstantesDuJeu (la classe moteur implante cette interface). Par exemple, la ligne suivante soustrait quatre la valeur de la variable raquetteEnfant_Y :
raquetteEnfant_Y -= INCREMENT_RAQUETTE;
Si la coordonne Y de la raquette valait 100, elle devient 96 aprs cette ligne de code, ce qui signifie que la raquette doit tre dplace vers le haut. Tu obtiendrais le mme rsultat en utilisant la syntaxe suivante :
Programmation Java pour les enfants, les parents et les grands-parents raquetteEnfant_Y = raquetteEnfant_Y INCREMENT_RAQUETTE;
186
Souviens-toi, nous avons abord les diffrents moyens de modifier la valeur d'une variable au Chapitre 3. Voici la classe MoteurJeuPingPong.
package moteur; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import crans.*; public class MoteurJeuPingPong implements MouseListener, MouseMotionListener, ConstantesDuJeu { TableVertePingPong table; public int raquetteEnfant_Y = RAQUETTE_ENFANT_Y_DEPART; // Constructeur. Stocke une rfrence la table. public MoteurJeuPingPong(TableVertePingPong tableVerte) { table = tableVerte; } // Mthodes requises par l'interface MouseListener. public void mousePressed(MouseEvent vnement) { // Rcupre les coordonnes X et Y du pointeur de la // souris et les affecte au "point blanc" sur la table. table.point.x = vnement.getX(); table.point.y = vnement.getY(); // La mthode repaint appelle en interne la mthode // paintComponent() de la table qui rafrachit la // fentre. table.repaint(); } public void mouseReleased(MouseEvent vnement) {} public void mouseEntered(MouseEvent vnement) {} public void mouseExited(MouseEvent vnement) {} public void mouseClicked(MouseEvent vnement) {} // Mthodes requises par l'interface MouseMotionListener. public void mouseDragged(MouseEvent vnement) {} public void mouseMoved(MouseEvent vnement) { int souris_Y = vnement.getY(); // Si la souris est au-dessus de la raquette de l'enfant // et que la raquette n'a pas dpass la limite // suprieure de la table, la dplace vers le haut ; // sinon, la dplace vers le bas. if (souris_Y < raquetteEnfant_Y && raquetteEnfant_Y > HAUT_TABLE) { raquetteEnfant_Y -= INCREMENT_RAQUETTE; } else if (raquetteEnfant_Y < BAS_TABLE) { raquetteEnfant_Y += INCREMENT_RAQUETTE; } // Affecte la nouvelle position de la raquette dans la // classe table table.positionnerRaquetteEnfant_Y(raquetteEnfant_Y); table.repaint(); }
187
Certains des ordinateurs les plus chers ont aussi deux processeurs ou plus. Mais sans doute ton ordinateur n'a-t-il qu'un processeur qui effectue les calculs, envoie les commandes l'cran, au disque, aux ordinateurs distants, etc. Mme un unique processeur peut excuter plusieurs actions la fois si le programme utilise des fils d'excution multiples (multiple threads). Une classe Java peut lancer plusieurs fils d'excution qui obtiennent chacun leur tour des tranches du temps de l'ordinateur. Un bon exemple de programme capable de crer de multiples fils d'excution est un navigateur web. Tu peux naviguer sur Internet tout en tlchargeant des fichiers : un seul programme excute deux fils d'excution.
188
La version suivante de notre jeu de ping-pong a un fil d'excution ddi l'affichage de la table. Le second fil d'excution calcule les coordonnes de la balle et des raquettes et envoie les commandes au premier fil d'excution pour repeindre la fentre. Mais tout d'abord, je vais te montrer deux programmes trs simples pour mieux te faire comprendre pourquoi les fils d'excution sont ncessaires. Chacun de ces programmes d'exemple affiche un bouton et un champ textuel. Quand on appuie sur le bouton Tuer le temps, le programme entre dans une boucle qui incrmente une variable trente mille fois. La valeur courante de la variable compteur est affiche dans la barre de titre de la fentre. La classe ExempleSansFils n'a qu'un fil d'excution et il est impossible de saisir quelque chose dans le champ textuel tant que la boucle n'est pas termine. Cette boucle accapare tout le temps de calcul du processeur, c'est pourquoi la fentre est verrouille. Compile et excute cette classe et constate par toi-mme que la fentre est verrouille pendant un moment. Note que cette classe cre une instance de JTextField et la passe au contenu de la fentre sans dclarer de variable reprsentant cette instance. Si tu ne comptes pas lire ou modifier d'attributs de cet objet dans ton programme, tu n'as pas besoin de mmoriser une telle rfrence.
189
public class ExempleSansFils extends JFrame implements ActionListener { // Constructeur ExempleSansFils() { // Cre un cadre contenant un bouton et un champ textuel GridLayout disposition = new GridLayout(2,1); this.getContentPane().setLayout(disposition); JButton monBouton = new JButton("Tuer le temps"); monBouton.addActionListener(this); this.getContentPane().add(monBouton); this.getContentPane().add(new JTextField()); } // Traite les clics sur le bouton public void actionPerformed(ActionEvent vnement) { // Tue juste un peu le temps pour montrer que // les contrles de la fentre sont verrouills. for (int i = 0; i < 30000; i++) { this.setTitle("i = " + i); } } public static void main(String[] args) { // Cre une instance du cadre ExempleSansFils maFentre = new ExempleSansFils(); // Permet la fermeture de la fentre par clic sur la // petite croix dans le coin. maFentre.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); // Affecte sa taille au cadre coordonnes du coin haut // gauche, largeur et hauteur. maFentre.setBounds(0, 0, 200, 100); // Rend la fentre visible. maFentre.setVisible(true); } }
190
La version suivante de cette petite fentre cre et lance un fil d'excution spar pour la boucle ; le fil d'excution principal de la fentre te permet de taper dans le champ textuel pendant que la boucle s'excute. En Java, on peut crer un fil d'excution par l'un des moyens suivants : 1. Crer une instance de la classe Java Thread et lui passer un objet qui implante l'interface Runnable. Si cette classe implante l'interface Runnable, le code ressemble ceci :
Thread travailleur = new Thread(this);
Cette interface t'impose d'crire dans la mthode run() le code qui doit tre excut comme un fil d'excution spar. Mais pour lancer le fil d'excution, tu dois appeler la mthode start(), qui va en fait appeler ta mthode run(). D'accord, c'est un peu troublant, mais c'est comme a que tu dmarres le fil d'excution :
travailleur.start();
2. Crer une sous-classe de la classe Thread et y implanter la mthode run(). Pour dmarrer le fil d'excution, appeler la mthode start().
public class MonFil extends Thread { public static void main(String[] args) { MonFil travailleur = new MonFil(); travailleur.start(); } public void run() { // Place ton code ici. }
J'utilise la premire mthode dans la classe ExempleAvecFils parce que cette classe hrite dj de JFrame et qu'on ne peut pas hriter de plus d'une classe en Java.
191
public class ExempleAvecFils extends JFrame implements ActionListener, Runnable { // Constructeur ExempleAvecFils() { // Cre un cadre contenant un bouton et un champ textuel. GridLayout disposition = new GridLayout(2,1); this.getContentPane().setLayout(disposition); JButton monBouton = new JButton("Tuer le temps"); monBouton.addActionListener(this); this.getContentPane().add(monBouton); this.getContentPane().add(new JTextField()); } public void actionPerformed(ActionEvent vnement) { // Cre un fil et excute le code "tuer le temps" // sans bloquer la fentre. Thread travailleur = new Thread(this); travailleur.start(); // Ceci appelle la mthode run() } public void run() { // Tue juste un peu le temps pour montrer que // les contrles de la fentre NE sont PAS verrouills. for (int i = 0; i < 30000; i++) { this.setTitle("i = " + i); } } public static void main(String[] args) { ExempleAvecFils maFentre = new ExempleAvecFils(); // Permet la fermeture de la fentre par clic sur la // petite croix dans le coin. maFentre.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); // Affecte sa taille au cadre et le rend visible. maFentre.setBounds(0, 0, 200, 100); maFentre.setVisible(true); } }
192
La classe ExempleAvecFils dmarre un nouveau fil d'excution lorsque tu cliques sur le bouton Tuer le temps. Aprs quoi, le fil d'excution contenant la boucle et le fil d'excution principal utilisent chacun leur tour des tranches du temps du processeur. Tu peux maintenant saisir du texte dans le champ textuel (le fil d'excution principal) alors que l'autre fil d'excution excute la boucle ! Les fils d'excution mritent une tude bien plus approfondie que ces quelques pages et je t'encourage en amliorer ta comprhension par d'autres lectures.
193
package crans; import javax.swing.JPanel; import javax.swing.JFrame; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.WindowConstants; import java.awt.Dimension; import java.awt.Container; import java.awt.Graphics; import java.awt.Color; import moteur.MoteurJeuPingPong; /** * Cette classe dessine la table de ping-pong, la balle et * les raquettes et affiche le score */ public class TableVertePingPong extends JPanel implements ConstantesDuJeu { private JLabel label; private int raquetteOrdinateur_Y = RAQUETTE_ORDINATEUR_Y_DEPART; private int raquetteEnfant_Y = RAQUETTE_ENFANT_Y_DEPART; private int balle_X = BALLE_X_DEPART; private int balle_Y = BALLE_Y_DEPART; Dimension taillePrfre = new Dimension(LARGEUR_TABLE, HAUTEUR_TABLE); // Cette mthode affecte sa taille au cadre. // Elle est appele par Java. public Dimension getPreferredSize() { return taillePrfre; } // Constructeur. Cre un rcepteur d'vnements souris. TableVertePingPong() { MoteurJeuPingPong moteurJeu = new MoteurJeuPingPong(this); // Reoit les mouvements de la souris pour dplacer la // raquette. addMouseMotionListener(moteurJeu); // Reoit les vnements clavier. addKeyListener(moteurJeu);
194
// Ajoute un cadre la table et un JLabel void ajouteAuCadre(Container conteneur) { conteneur.setLayout(new BoxLayout(conteneur, BoxLayout.Y_AXIS)); conteneur.add(this); label = new JLabel( "Taper N pour une nouvelle partie, S pour servir" + " ou Q pour quitter"); conteneur.add(label); } // Repeint la fentre. Cette mthode est appele par Java // quand il est ncessaire de rafrachir l'cran ou quand // la mthode repaint() est appele. public void paintComponent(Graphics contexteGraphique) { super.paintComponent(contexteGraphique); // Dessine la table verte contexteGraphique.setColor(Color.GREEN); contexteGraphique.fillRect( 0, 0, LARGEUR_TABLE, HAUTEUR_TABLE); // Dessine la raquette droite contexteGraphique.setColor(Color.yellow); contexteGraphique.fillRect( RAQUETTE_ENFANT_X, raquetteEnfant_Y, LARGEUR_RAQUETTE, LONGUEUR_RAQUETTE); // Dessine la raquette gauche contexteGraphique.setColor(Color.blue); contexteGraphique.fillRect(RAQUETTE_ORDINATEUR_X, raquetteOrdinateur_Y, LARGEUR_RAQUETTE, LONGUEUR_RAQUETTE); // Dessine la balle contexteGraphique.setColor(Color.red); contexteGraphique.fillOval(balle_X, balle_Y, 10, 10); // Dessine les lignes blanches contexteGraphique.setColor(Color.white); contexteGraphique.drawRect(10, 10, 300, 200); contexteGraphique.drawLine(160, 10, 160, 210); // Donne le focus la table, afin que le rcepteur de // touches envoie les commandes la table requestFocus(); } // Affecte sa position courante la raquette de l'enfant public void positionnerRaquetteEnfant_Y(int y) { this.raquetteEnfant_Y = y; repaint(); }
195
// Retourne la position courante de la raquette de l'enfant public int coordonneRaquetteEnfant_Y() { return raquetteEnfant_Y; } // Affecte sa position courante la raquette de // l'ordinateur public void positionnerRaquetteOrdinateur_Y(int y) { this.raquetteOrdinateur_Y = y; repaint(); } // Affecte le texte du message du jeu public void affecterTexteMessage(String texte) { label.setText(texte); repaint(); } // Positionne la balle public void positionnerBalle(int x, int y) { balle_X = x; balle_Y = y; repaint(); } public static void main(String[] args) { // Cre une instance du cadre JFrame monCadre = new JFrame("Table verte de ping-pong"); // Permet la fermeture de la fentre par clic sur la // petite croix dans le coin. monCadre.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); TableVertePingPong table = new TableVertePingPong(); table.ajouteAuCadre(monCadre.getContentPane()); // Affecte sa taille au cadre et le rend visible. monCadre.setBounds(0, 0, LARGEUR_TABLE + 5, HAUTEUR_TABLE + 40); monCadre.setVisible(true); } }
196
J'ai ajout quelques variables dclares final l'interface ConstantesDuJeu. Tu devrais pouvoir en deviner le rle d'aprs leurs noms.
package crans; /** * Cette interface contient toutes les dfinitions des * variables invariantes utilises dans le jeu. */ public interface ConstantesDuJeu { // Taille de la table de ping-pong public final int LARGEUR_TABLE = 320; public final int HAUTEUR_TABLE = 220; public final int HAUT_TABLE = 12; public final int BAS_TABLE = 180; // Incrment du mouvement de la balle en pixels public final int INCREMENT_BALLE = 4; // Coordonnes maximum et minimum permises pour la balle public final int BALLE_X_MIN = 1 + INCREMENT_BALLE; public final int BALLE_Y_MIN = 1 + INCREMENT_BALLE; public final int BALLE_X_MAX = LARGEUR_TABLE - INCREMENT_BALLE; public final int BALLE_Y_MAX = HAUTEUR_TABLE - INCREMENT_BALLE; // Position de dpart de la balle public final int BALLE_X_DEPART = LARGEUR_TABLE / 2; public final int BALLE_Y_DEPART = HAUTEUR_TABLE / 2; // Taille, positions et incrment des raquettes public final int RAQUETTE_ENFANT_X = 300; public final int RAQUETTE_ENFANT_Y_DEPART = 100; public final int RAQUETTE_ORDINATEUR_X = 15; public final int RAQUETTE_ORDINATEUR_Y_DEPART = 100; public final int INCREMENT_RAQUETTE = 2; public final int LONGUEUR_RAQUETTE = 30; public final int LARGEUR_RAQUETTE = 5; public final int SCORE_GAGNANT = 21; // Ralentit mes ordinateurs rapides ; // modifier la valeur si ncessaire. public final int DUREE_SOMMEIL = 10; // En millisecondes. }
Voici les modifications les plus marquantes que j'ai effectues dans la classe MoteurJeuPingPong : J'ai supprim l'interface MouseListener et toutes ses mthodes, puisque nous ne nous intressons plus aux clics. MouseMotionListener se charge de tous les dplacements de la souris. Cette classe implante maintenant l'interface Runnable ; les prises de dcisions sont codes dans la mthode run(). Regarde le constructeur : j'y cre et lance un nouveau fil d'excution. La
197
mthode run() applique les rgles de la stratgie du jeu en plusieurs tapes, programmes l'intrieur de la clause if (balleServie). C'est une version courte de if (balleServie == true). Je te prie de noter l'utilisation de la clause conditionnelle if pour affecter une valeur la variable rebondPossible l'tape 1. En fonction de l'expression en surbrillance, cette variable prendra la valeur true ou la valeur false. La classe implante l'interface KeyListener ; la mthode keyPressed() examine la lettre entre au clavier pour dmarrer la partie, quitter le jeu ou servir la balle. Le code de cette mthode permet l'utilisateur de taper aussi bien des majuscules que des minuscules, par exemple N et n. J'ai ajout plusieurs mthodes private telles que afficherScore(), serviceEnfant() et balleSurLaTable(). Ces mthodes sont dclares prives parce qu'elles ne sont utilises que dans cette classe et que les autres classes n'ont mme pas connatre leur existence. C'est un exemple d'encapsulation. Certains ordinateurs sont trop rapides, ce qui rend les dplacements de la balle difficiles contrler. C'est pourquoi j'ai ralenti le jeu en appelant la mthode Thread.sleep(). La mthode statique sleep() met ce fil d'excution en pause pour le nombre de millisecondes qui lui est pass en argument. Pour ajouter un peu de piment au jeu, la balle se dplace en diagonale quand la raquette de l'enfant la frappe. C'est pourquoi le code modifie non seulement la coordonne X, mais aussi la coordonne Y de la balle.
198
package moteur; import java.awt.event.MouseMotionListener; import java.awt.event.MouseEvent; import java.awt.event.KeyListener; import java.awt.event.KeyEvent; import crans.*; /** * Cette classe est un rcepteur de souris et de clavier. * Elle calcule les dplacements de la balle et des raquettes * et change leurs coordonnes. */ public class MoteurJeuPingPong implements Runnable, MouseMotionListener, KeyListener, ConstantesDuJeu { private TableVertePingPong table; // Rfrence la table. private int raquetteEnfant_Y = RAQUETTE_ENFANT_Y_DEPART; private int raquetteOrdinateur_Y = RAQUETTE_ORDINATEUR_Y_DEPART; private int scoreEnfant; private int scoreOrdinateur; private int balle_X; // position X de la balle private int balle_Y; // position Y de la balle private boolean dplacementGauche = true; private boolean balleServie = false; //Valeur en pixels du dplacement vertical de la balle. private int dplacementVertical; // Constructeur. Stocke une rfrence la table. public MoteurJeuPingPong(TableVertePingPong tableVerte) { table = tableVerte; Thread travailleur = new Thread(this); travailleur.start(); } // Mthodes requises par l'interface MouseMotionListener // (certaines sont vides, mais doivent tre incluses dans // la classe de toute faon). public void mouseDragged(MouseEvent vnement) { }
199
public void mouseMoved(MouseEvent vnement) { int souris_Y = vnement.getY(); Si la souris est au-dessus de la raquette de l'enfant et que la raquette n'a pas dpass le haut de la table, la dplace vers le haut ; sinon, la dplace vers le bas. (souris_Y < raquetteEnfant_Y && raquetteEnfant_Y > HAUT_TABLE) { raquetteEnfant_Y -= INCREMENT_RAQUETTE; } else if (raquetteEnfant_Y < BAS_TABLE) { raquetteEnfant_Y += INCREMENT_RAQUETTE; } // Affecte la nouvelle position de la raquette table.positionnerRaquetteEnfant_Y(raquetteEnfant_Y); } // Mthodes requises par l'interface KeyListener. public void keyPressed(KeyEvent vnement) { char touche = vnement.getKeyChar(); if ('n' == touche || 'N' == touche) { dmarrerNouvellePartie(); } else if ('q' == touche || 'Q' == touche) { terminerJeu(); } else if ('s' == touche || 'S' == touche) { serviceEnfant(); } } public void keyReleased(KeyEvent vnement) {} public void keyTyped(KeyEvent vnement) {} // Dmarre une nouvelle partie. public void dmarrerNouvellePartie() { scoreOrdinateur = 0; scoreEnfant = 0; table.affecterTexteMessage("Scores - Ordinateur : 0" + "Enfant : 0"); serviceEnfant(); } // Termine le jeu. public void terminerJeu(){ System.exit(0); } // // // // if
200
// La mthode run() est requise par l'interface Runnable. public void run() { boolean rebondPossible = false; while (true) { if (balleServie) { // Si la balle est en mouvement // Etape 1. La balle se dplace-t-elle vers la // gauche ? if (dplacementGauche && balle_X > BALLE_X_MIN) { rebondPossible = (balle_Y >= raquetteOrdinateur_Y && balle_Y < (raquetteOrdinateur_Y + LONGUEUR_RAQUETTE) ? true : false); balle_X -= INCREMENT_BALLE; // Ajoute un dplacement vertical chaque // mouvement horizontal de la balle. balle_Y -= dplacementVertical; table.positionnerBalle(balle_X, balle_Y); // La balle peut-elle rebondir ? if (balle_X <= RAQUETTE_ORDINATEUR_X && rebondPossible) { dplacementGauche = false; } } // Etape 2. La balle se dplace-t-elle vers la // droite ? if (!dplacementGauche && balle_X <= BALLE_X_MAX) { rebondPossible = (balle_Y >= raquetteEnfant_Y && balle_Y < (raquetteEnfant_Y + LONGUEUR_RAQUETTE) ? true : false); balle_X += INCREMENT_BALLE; table.positionnerBalle(balle_X, balle_Y); // La balle peut-elle rebondir ? if (balle_X >= RAQUETTE_ENFANT_X && rebondPossible) { dplacementGauche = true; } }
// Etape 3. Dplace la raquette de l'ordinateur vers le // haut ou vers le bas pour bloquer la balle.
201
if (raquetteOrdinateur_Y < balle_Y && raquetteOrdinateur_Y < BAS_TABLE) { raquetteOrdinateur_Y += INCREMENT_RAQUETTE; } else if (raquetteOrdinateur_Y > HAUT_TABLE) { raquetteOrdinateur_Y -= INCREMENT_RAQUETTE; } table.positionnerRaquetteOrdinateur_Y( raquetteOrdinateur_Y); // Etape 4. Sommeiller un peu try { Thread.sleep(DUREE_SOMMEIL); } catch (InterruptedException exception) { exception.printStackTrace(); } // Etape 5. Mettre le score jour si la balle est // dans la surface verte mais ne bouge plus. if (balleSurLaTable()) { if (balle_X > BALLE_X_MAX ) { scoreOrdinateur++; afficherScore(); } else if (balle_X < BALLE_X_MIN) { scoreEnfant++; afficherScore(); } } } // Fin du if balleServie } // Fin du while }// Fin de run() // Sert depuis la position courante de la raquette // de l'enfant. private void serviceEnfant() { balleServie = true; balle_X = RAQUETTE_ENFANT_X - 1; balle_Y = raquetteEnfant_Y; if (balle_Y > HAUTEUR_TABLE / 2) { dplacementVertical = -1; } else { dplacementVertical = 1; } table.positionnerBalle(balle_X, balle_Y); table.positionnerRaquetteEnfant_Y(raquetteEnfant_Y); }
Programmation Java pour les enfants, les parents et les grands-parents private void afficherScore() { balleServie = false;
202
if (scoreOrdinateur == SCORE_GAGNANT) { table.affecterTexteMessage("L'ordinateur a gagn ! " + scoreOrdinateur + " : " + scoreEnfant); } else if (scoreEnfant == SCORE_GAGNANT) { table.affecterTexteMessage ("Tu as gagn ! "+ scoreEnfant + " : " + scoreOrdinateur); } else { table.affecterTexteMessage ("Ordinateur : "+ scoreOrdinateur + " Enfant: " + scoreEnfant); }
// Vrifie que la balle n'a pas dpass la limite // infrieure ou suprieure de la table. private boolean balleSurLaTable() { if (balle_Y >= BALLE_Y_MIN && balle_Y <= BALLE_Y_MAX) { return true; } else { return false; } }
Classe MoteurJeuPingPong (partie 5 de 5) Flicitations ! Tu as termin ton second jeu. Compile les classes et fais une partie. Lorsque tu te sentiras l'aise avec le code, essaie de le modifier ; je suis sr que tu as des ides d'amlioration.
2. Robocode est un jeu de programmation trs amusant qui t'apprend le Java en te faisant crer des robots.
http://www.alphaworks.ibm.com/tech/robocode
203
Autres lectures
Didacticiel sur les fils d'excution Java :
http://java.sun.com/docs/books/tutorial/essential/threads/
Classe java.awt.Graphics :
http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Graphics.html
Exercices
1. La classe MoteurJeuPingPong affecte ses coordonnes au point blanc l'aide de ce code : table.point.x = vnement.getX();. Dans la classe TableVertePingPong, rend prive la variable point et ajoute la mthode publique : affecteCoordonnesPoint(int x, int y). Modifie le code de la classe moteur en utilisant cette mthode. 2. Notre jeu de ping-pong a un bogue : aprs qu'un gagnant ait t annonc, on peut toujours appuyer sur la touche S du clavier et le jeu continue. Corrige ce bogue.
204
205
d'changer des fichiers. Ils peuvent les copier sur des disquettes ou sur des CD, utiliser le courrier lectronique ou juste envoyer les donnes travers le rseau. Il existe des programmes spciaux capables de compresser de multiples fichiers en un unique fichier d'archive. La taille d'une telle archive est en gnrale infrieure la somme des tailles des fichiers inclus, ce qui rend la copie plus rapide et conomise de la place sur tes disques. Java est fourni avec un programme appel jar, utilis pour archiver de multiples classes Java et d'autres fichiers en un fichier d'extension .jar. Le format interne des fichiers jar est le mme que celui du populaire WinZip (nous l'avons utilis au Chapitre 2). Les trois commandes suivantes illustrent l'utilisation de l'outil jar. Pour crer un jar contenant tous les fichiers dont l'extension est .class, ouvre une fentre de commande, place-toi dans le rpertoire o se trouvent tes classes et tape la commande suivante : jar cvf mesClasses.jar *.class
206
Aprs le mot jar, tu dois prciser les options de cette commande. Dans l'exemple prcdent, c signifie cration d'une nouvelle archive, v demande l'affichage de ce que fait la commande et f indique que le nom du nouveau fichier d'archive est fourni. Tu peux maintenant copier ce fichier sur un autre disque ou l'envoyer par courrier lectronique un ami. Pour extraire (unjar) les fichiers de l'archive mesClasses.jar, tape la commande suivante : jar xvf mesClasses.jar Tous les fichiers seront extraits dans le rpertoire courant. Dans cet exemple, l'option x signifie extraction des fichiers de l'archive. Si tu veux juste voir le contenu d'un fichier jar sans extraire les fichiers, utilise cette commande, o t signifie sommaire (table of contents) : jar tvf mesClasses.jar En ralit, je prfre utiliser le programme WinZip pour voir ce qu'il y a dans un fichier jar. Trs souvent, les applications Java du monde rel sont constitues de multiples clases stockes dans des fichiers jar. Mme s'il y a beaucoup d'autres options utilisables avec le programme jar, les trois exemples de ce chapitre te suffiront pour la plupart de tes projets.
Autres lectures
Outil d'archivage Java :
http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/jar.html
207
rendent la programmation Java un peu plus rapide. Je te propose une liste de commandes Eclipse utiles, mais je suis sr que tu en trouveras d'autres quand tu commenceras utiliser cet outil. Si tu vois un petit astrisque dans l'onglet classe, cela signifie que des modifications du code de la classe n'ont pas t enregistres. Met en surbrillance le nom d'une classe ou d'une mthode utilise dans ton code et appuie sur la touche F3 de ton clavier pour aller la ligne o a t dclare cette classe ou cette mthode. Si une ligne est marque avec un rond rouge, symbole d'erreur, dplace la souris au-dessus du rond pour voir le texte de l'erreur. Appuie sur Ctrl-F11 pour excuter nouveau le dernier programme excut. Place le curseur aprs une accolade pour marquer l'accolade correspondante. Pour modifier la superclasse lorsque tu cres une classe, clique sur le bouton Parcourir, supprime java.lang.Object et entre la premire lettre de la classe que tu souhaites utiliser. Tu peux alors choisir ta classe dans une liste. Pour copier une classe d'un paquetage un autre, slectionne-la et appuie sur Ctrl-C. Slectionne ensuite sa destination et appuie sur Ctrl-V. Pour renommer une classe, une variable ou une mthode, clique dessus avec le bouton droit de la souris et slectionne Propager
208
les modifications puis Renommer dans le menu contextuel. Toutes les occurrences de ce nom seront renommes. Si ton projet ncessite des fichiers jar externes, clique avec le bouton droit sur le nom du projet, slectionne Proprits, Chemin de compilation Java, choisis l'onglet Bibliothques et clique sur le bouton Ajouter des fichiers JAR externes.
Dbogueur Eclipse
Selon la rumeur, il y a 40 ans, quand les ordinateurs taient tellement gros qu'ils n'auraient mme pas pu entrer dans ta chambre, l'un des programmes se mit soudain donner des rsultats errons. Tous ces problmes taient le fait d'un petit insecte install quelque part dans les cbles de l'ordinateur8. Quand on retira l'insecte, le programme se remit fonctionner correctement. Depuis lors, dboguer un programme signifie trouver ce qui ne donne pas les rsultats attendus. Ne confonds pas les bogues et les erreurs de compilation. Disons par exemple que, au lieu de multiplier une variable par 2, tu la multiplies par 22. Cette erreur de frappe ne gnre aucune erreur de compilation, mais le rsultat sera faux. Les dbogueurs te permettent de drouler l'excution d'un programme ligne ligne et de voir ou modifier la valeur des variables chaque tape de l'excution du programme.
Je vais t'expliquer comment utiliser le dbogueur d'Eclipse en prenant l'exemple du programme MatrePoisson du Chapitre 4.
209
Un point d'arrt (breakpoint) est une ligne du code o tu voudrais que ton programme s'arrte afin de voir ou changer la valeur courante des variables et d'autres informations d'excution. Pour dfinir un point d'arrt, double-clique simplement sur la gauche de la ligne o tu veux que le programme s'arrte. Essayons sur la ligne monPoisson.plonger(2). Tu peux voir sur cette ligne une puce ronde qui indique un point d'arrt. Maintenant, slectionne les menus Excuter, Dboguer. Slectionne l'application MatrePoisson et appuie sur le bouton Dboguer. MatrePoisson dmarre en mode dbogage (in the debug mode) et s'arrte en attendant de nouvelles instructions de ta part ds qu'il atteint la ligne monPoisson.plonger(2). Une fentre comme celle-ci est affiche :
En bas gauche de la perspective de dbogage, la ligne correspondant au point d'arrt est en surbrillance. La flche bleue pointe sur la ligne qui est sur le point d'tre excute. Sur le ct droit (dans la vue Variables), clique sur le petit signe + prs de la variable monPoisson. Comme cette variable pointe sur l'objet Poisson, on peut examiner
210
toutes les variables membres de cette classe et leurs valeurs courantes ; par exemple, profondeurCourante = 0. Les flches de la partie haut gauche de la fentre permettent de poursuivre l'excution du programme dans diffrents modes. La premire flche jaune signifie Avance d'un pas avec entre, ou entre dans (step into) la mthode. Si tu appuies sur cette flche (ou sur F5), tu te retrouveras l'intrieur de la mthode plonger(). La fentre change et te prsente la valeur de l'argument combienDePlus = 2 comme dans la capture d'cran ci-dessous. Clique sur le petit signe + ct du mot this pour voir quelles sont les valeurs courantes des variables membres de cet objet. Pour modifier la valeur de la variable, clique dessus avec le bouton droit et entre la nouvelle valeur. Cela peut t'aider quand tu n'es pas sr de comprendre pourquoi le programme ne fonctionne pas correctement et que tu veux jouer au jeu du et si.
Pour poursuivre l'excution ligne ligne, clique sur la flche suivante, Avance d'un pas sans entre (ou appuie sur le bouton F6). Si tu veux reprendre l'excution normale du programme, clique sur le bouton Reprise (petit triangle vert gauche) ou appuie sur le bouton F8. Pour supprimer le point d'arrt, double-clique sur la petite puce ronde, qui disparat. J'aime utiliser le dbogueur mme si mon programme ne
211
contient pas de bogue : a m'aide mieux comprendre ce qu'il se passe exactement dans le programme qui s'excute. O placer un point d'arrt ? Si tu as une ide de la mthode qui te pose problme, mets-le juste avant la ligne suspecte. Si tu n'en es pas sr, place-le simplement sur la premire ligne de la mthode main() et avance petit petit dans le programme.
212
d'images, de fichiers son, etc. Nous avons brivement mentionn HTML au Chapitre 7, mais si tu envisages de devenir un designer web, tu dois passer plus de temps apprendre l'HTML ; l'un des bons endroits par o commencer est la page web www.w3schools.com. En ralit, il y a de nombreux sites web et programmes permettant de crer une page web en quelques minutes sans mme savoir comment c'est fait. Ces programmes gnrent de toutes faons de l'HTML, mais ils te le cachent. Cela dit, si tu as matris ce livre, je te dclare Programmeur Java Junior (je ne plaisante pas !) et l'apprentissage d'HTML sera du gteau pour toi. Pour dvelopper une page web, tu cres en gnral un ou plusieurs fichiers HTML sur le disque de ton ordinateur ; mais le problme, c'est que ton ordinateur n'est pas visible par les autres utilisateurs d'Internet. C'est pourquoi, une fois la page termine, tu dois remonter (upload) ces fichiers en un lieu visible de tous. C'est le cas d'un disque situ dans l'ordinateur de la compagnie qui est ton Fournisseur d'accs Internet (FAI). Premirement, tu dois avoir ton propre rpertoire sur l'ordinateur de ton FAI. Contacte ton FAI par tlphone ou par courrier lectronique en lui expliquant que tu as cr une page HTML et que tu veux la publier. Sa rponse contient en gnral les informations suivantes :
Le nom de rseau de son ordinateur hte (host machine). Le nom du rpertoire de son ordinateur o il t'est permis de stocker tes fichiers. L'adresse web (URL) de ta nouvelle page que tu indiqueras aux personnes qui sont intresses par ta page.
213
L'identifiant utilisateur (user id) et le mot de passe (password) dont tu auras besoin pour tlcharger de nouveaux fichiers ou pour en modifier d'anciens.
Ces temps-ci, la plupart des FAI mettent gratuitement disposition au moins 10 Mo d'espace sur leur disque, ce qui est plus qu'assez pour la plupart des gens. Il te faut maintenant un programme qui te permette de copier des fichiers de ton ordinateur sur celui de ton FAI. La copie de fichiers de ton ordinateur vers un ordinateur sur Internet est appele tlchargement ascendant (uploading) et la copie de fichiers d'Internet vers ta machine est appele tlchargement descendant (downloading). Tu peux tlcharger des fichiers dans les deux sens l'aide de ce qu'on appelle un programme FTP client. L'un des clients FTP simples et faciles d'utilisation est FTP Explorer ; tu peux le tlcharger depuis www.ftpx.com. Installe ce programme et ajoute la machine de ton FAI la liste de connexions de ton client FTP : dmarre FTP Explorer ; la premire fentre qui s'ouvre est un cran de connexion. Tu peux aussi cliquer sur l'item Connection du menu Tools.
Clique sur le bouton Add et entre l'hte, l'identifiant de connexion et le mot de passe que t'a fournis ton FAI. Entre le nom de ton FAI dans le champ Profile Name. Si tu as fais les choses correctement, tu dois voir ton nouveau profil de connexion dans la liste des serveurs FTP disponibles. Clique sur le bouton Connect et tu verras les rpertoires de
214
la machine de ton FAI. Trouve ton rpertoire et suis la procdure de tlchargement dcrite ci-dessous. La barre d'outils contient deux flches bleues. Celle qui pointe vers le haut sert aux tlchargements ascendants. Clique sur cette flche pour ouvrir une fentre standard qui te permet d'aller dans le rpertoire qui contient tes fichiers HTML. Slectionne les fichiers que tu souhaites tlcharger et appuie sur le bouton Open. Au bout de quelques secondes, ces fichiers sont visibles sur la machine de ton FAI.
Surveille le bas de la fentre pour t'assurer qu'il n'y a pas eu de problmes pendant le tlchargement. Nomme le fichier principal de ta page index.html. De cette faon, ton URL sera plus courte et les gens n'auront pas besoin d'y ajouter celui de ton fichier. En effet, si le nom du rpertoire sur le disque de ton FAI est www.xyz.com/~David et que le fichier principal de ta page web est maPagePrincipale.html, l'adresse de ta page web est www.xyz.com/~David/maPagePrincipale.html. Mais si le nom de ton fichier principal est index.html, l'URL de ta page est plus court : www.xyz.com/~David. Dsormais, tous ceux qui connaissent cette URL pourront voir ta page en ligne. Si, plus tard, tu dcides de modifier cette page web, rpte la mme procdure : effectue les corrections sur ton disque, puis tlcharge-les pour remplacer les anciens fichiers par les nouveaux. Si tu dcides de devenir un concepteur web, le prochain langage apprendre est JavaScript. Ce langage est beaucoup plus simple que Java et te permettra de fabriquer des pages web plus attractives.
215
Autres lectures
1. Webmonkey pour les enfants :
http://hotwired.lycos.com/webmonkey/kids/
Exercices
Cre une page web et publie le jeu de morpion du Chapitre 7. Pour commencer, tlcharge simplement les fichiers Morpion.html et Morpion.class sur ta page web.
Fin
216
Index
! ............................................................................................................. 58 && ............................................................................................................ 57 == ............................................................................................................ 66 argument .......................................................................................... 33, 49 arguments de ligne de commande ....................................................... 147 ArrayList ............................................................................173, 174, 175 AWT ........................................................................................................ 70 bote de message............................................................................... 94, 95 BorderLayout....................................................................................... 77 boucles .................................................................................................... 65 break...................................................................................................... 66 BufferedInputStream...................................................................... 145 BufferedOutputStream.................................................................... 147 cadre ....................................................................................................... 72 CardLayout ........................................................................................... 83 catch............................................................................................ 133, 134 CLASSPATH .......................................................................................... 16 concatnation ......................................................................................... 39 constantes............................................................................................... 40 constructeur ........................................................................................... 62 continue ............................................................................................... 67 conversion de type explicite ................................................................... 95 Eclipse .................................................................................................... 22 else if ................................................................................................. 58 equals() ............................................................................................... 57 vnements....................................................................................... 72, 95 Exception ........................................................................................... 131 extends ................................................................................................. 50 FAI ........................................................................................................ 212 File...................................................................................................... 153 FileInputStream .............................................................................. 143 FileOutputStream ............................................................................ 144 FileReader ......................................................................................... 150 FileWriter ......................................................................................... 150 final...................................................................................................... 40 finally ....................................................................................... 136, 137 flux tampon ....................................................................................... 145 flux de sortie......................................................................................... 142 flux d'entre.......................................................................................... 142 for .......................................................................................................... 65 gestionnaire de disposition .................................................................... 72 Graphics ............................................................................................. 180 GridBagLayout..................................................................................... 81 GridLayout ........................................................................................... 75 GUI ......................................................................................................... 87
217
HTML ........................................................................................... 109, 111 IDE.......................................................................................................... 22 implanter ................................................................................................ 91 import.................................................................................................... 71 instance .................................................................................................. 97 instanceof ........................................................................................... 97 interfaces ........................................................................................ 90, 184 jar.................................................................................................. 205, 206 Javadoc ................................................................................................. 54 JRE ......................................................................................................... 20 Math........................................................................................................ 61 MouseListener................................................................................... 185 MouseMotionListener...................................................................... 185 new .......................................................................................................... 62 niveaux d'accs ..................................................................................... 166 Object.................................................................................................... 99 package ............................................................................................... 166 panneau .................................................................................................. 72 paquetages...................................................................................... 70, 163 Path ........................................................................................................ 16 porte ...................................................................................................... 61 primaire .................................................................................................. 40 private ....................................................................................... 166, 167 protected ........................................................................................... 166 public............................................................................................ 32, 166 rcepteurs ............................................................................................... 90 signature de mthode............................................................................. 31 sous-classe .............................................................................................. 47 static.............................................................................................. 32, 61 String.................................................................................................... 41 style orient objet................................................................................... 35 superclasse ....................................................................................... 47, 50 surcharge de mthode .............................................................. 50, 51, 159 Swing .............................................................................................. 71, 178 switch.................................................................................................... 60 SWT ........................................................................................................ 70 tableau .................................................................................................... 63 this........................................................................................................ 63 throw.................................................................................................... 137 throws.................................................................................................. 135 try ................................................................................................ 132, 134 types de donnes .................................................................................... 38 variable d'instance ................................................................................. 61 variable membre .................................................................................... 61 void........................................................................................................ 32 while...................................................................................................... 67 WinZip ............................................................................................ 23, 206