Cahier de TP Java - Examen corrige
2 déc. 2002 ... Programmation avancée: TP Java. ... 2.8 Vos notes. 3 TP n°3 : Affiner la définition
des classes ? Constructeurs et visibilités. 3.1 Constructeurs.
part of the document
DESS IGSI
Java
À : DESS IGSI
De : Laurent Perrussel (Laurent.Perrussel@univ-tlse1.fr)
Date : DATE \@ "dd/MM/yy" \* MERGEFORMAT 02/12/02
Introduction
Lobjectif de ce mémo est de présenter le langage Java. La programmation Java seffectuera à laide de loutil de développement JBuilder. Chaque chapitre fait lobjet dune séance de travaux pratiques. Les travaux pratiques complètent le cours de programmation : les concepts de programmation (structures de données et de contrôles) sont supposés connus.
Le mémo est organisé en chapitres : chaque chapitre traite dun thème et fait lobjet dune mise en pratique en T.P. Les thèmes ne sont pas indépendants : ils supposent une certaine continuité dans lapprentissage.
TABLES DES MATIERES
TOC \o "1-4" Introduction PAGEREF _Toc464381576 \h 1
1 TP n° 1 : Concepts de base PAGEREF _Toc464381577 \h 6
1.1 Programmation orienté-objet PAGEREF _Toc464381578 \h 6
1.2 Identifier et créer un objet PAGEREF _Toc464381579 \h 6
1.3 Les données PAGEREF _Toc464381580 \h 7
1.3.1 Données primitives PAGEREF _Toc464381581 \h 8
1.3.2 Les tableaux PAGEREF _Toc464381582 \h 8
1.3.3 Les chaînes de caractères PAGEREF _Toc464381583 \h 9
1.3.4 Accès aux données PAGEREF _Toc464381584 \h 9
1.4 Les classes PAGEREF _Toc464381585 \h 7
1.4.1 Description type dune classe PAGEREF _Toc464381586 \h 7
1.5 JBuilder 3 PAGEREF _Toc464381587 \h 10
1.6 Exercice PAGEREF _Toc464381588 \h 10
1.6.1 A faire PAGEREF _Toc464381589 \h 14
1.7 Ce quil faut retenir PAGEREF _Toc464381590 \h 14
1.8 Vos notes PAGEREF _Toc464381591 \h 14
2 TP n° 2 : définir des méthodes PAGEREF _Toc464381592 \h 15
2.1 Squelette dune méthode PAGEREF _Toc464381593 \h 15
2.2 Valeur de retour PAGEREF _Toc464381594 \h 16
2.3 Appeler la méthode dun objet PAGEREF _Toc464381595 \h 16
2.4 La liste des arguments PAGEREF _Toc464381596 \h 16
2.5 Les instructions de traitements PAGEREF _Toc464381597 \h 17
2.5.1 Opérateurs mathématiques PAGEREF _Toc464381598 \h 17
2.5.2 Instructions de contrôle PAGEREF _Toc464381599 \h 17
2.5.2.1 Instruction conditionnelle PAGEREF _Toc464381600 \h 18
2.5.2.2 Les instructions ditérations PAGEREF _Toc464381601 \h 18
2.6 Exercice PAGEREF _Toc464381602 \h 19
2.6.1 A faire PAGEREF _Toc464381603 \h 20
2.7 Ce quil faut retenir PAGEREF _Toc464381604 \h 20
2.8 Vos notes PAGEREF _Toc464381605 \h 20
3 TP n°3 : Affiner la définition des classes Constructeurs et visibilités PAGEREF _Toc464381606 \h 21
3.1 Constructeurs PAGEREF _Toc464381607 \h 21
3.2 Visibilité des classes et de leur contenu PAGEREF _Toc464381608 \h 22
3.2.1 Visibilité de la classe PAGEREF _Toc464381609 \h 22
3.2.2 Visibilité des données et méthodes PAGEREF _Toc464381610 \h 22
3.3 Exercice PAGEREF _Toc464381611 \h 23
3.3.1 A faire PAGEREF _Toc464381612 \h 24
3.4 Ce quil faut retenir PAGEREF _Toc464381613 \h 24
3.5 Vos notes PAGEREF _Toc464381614 \h 24
4 TP 4 : Création dun dialogue PAGEREF _Toc464381615 \h 25
4.1 La construction dune interface PAGEREF _Toc464381616 \h 25
4.2 Les composants PAGEREF _Toc464381617 \h 25
4.2.1 Chargement des bibliothèques PAGEREF _Toc464381618 \h 25
4.2.2 Type de composants PAGEREF _Toc464381619 \h 25
4.2.2.1 Les conteneurs PAGEREF _Toc464381620 \h 25
4.2.2.2 Les contrôles PAGEREF _Toc464381621 \h 26
4.3 Description des contrôles PAGEREF _Toc464381622 \h 27
4.3.1 Les boutons PAGEREF _Toc464381623 \h 27
4.3.1.1 Constructeurs PAGEREF _Toc464381624 \h 27
4.3.1.2 Quelques méthodes PAGEREF _Toc464381625 \h 27
4.3.2 Les boites à cocher PAGEREF _Toc464381626 \h 28
4.3.2.1 Constructeurs PAGEREF _Toc464381627 \h 28
4.3.2.2 Quelques méthodes PAGEREF _Toc464381628 \h 28
4.3.3 Les listes de choix PAGEREF _Toc464381629 \h 28
4.3.3.1 Constructeurs PAGEREF _Toc464381630 \h 28
4.3.3.2 Quelques méthodes PAGEREF _Toc464381631 \h 29
4.3.4 Les listes PAGEREF _Toc464381632 \h 29
4.3.4.1 Constructeurs PAGEREF _Toc464381633 \h 29
4.3.4.2 Quelques méthodes PAGEREF _Toc464381634 \h 30
4.3.5 Les zones de saisie PAGEREF _Toc464381635 \h 30
4.3.5.1 Constructeurs PAGEREF _Toc464381636 \h 30
4.3.5.2 Quelques méthodes PAGEREF _Toc464381637 \h 31
4.4 Disposer les contrôles PAGEREF _Toc464381638 \h 31
4.4.1 FlowLayout PAGEREF _Toc464381639 \h 31
4.4.2 BorderLayout PAGEREF _Toc464381640 \h 32
4.4.3 GridLayout PAGEREF _Toc464381641 \h 32
4.4.4 GridBagLayout PAGEREF _Toc464381642 \h 32
4.5 Exercice PAGEREF _Toc464381643 \h 32
4.6 A faire PAGEREF _Toc464381644 \h 35
4.7 Ce quil faut retenir PAGEREF _Toc464381645 \h 35
4.8 Vos notes PAGEREF _Toc464381646 \h 35
5 TP n°5 : Gérer des événements PAGEREF _Toc464381647 \h 36
5.1 La gestion des événements PAGEREF _Toc464381648 \h 36
5.1.1 Le contrôleur de la fenêtre PAGEREF _Toc464381649 \h 36
5.1.2 Le contrôleur des contrôles PAGEREF _Toc464381650 \h 36
5.2 question de méthode PAGEREF _Toc464381651 \h 37
5.3 Exercice PAGEREF _Toc464381652 \h 37
5.4 A faire PAGEREF _Toc464381653 \h 38
5.5 Ce quil faut retenir PAGEREF _Toc464381654 \h 38
5.6 Vos notes PAGEREF _Toc464381655 \h 39
6 TP n°6 : Héritage et interface PAGEREF _Toc464381656 \h 40
6.1 Héritage PAGEREF _Toc464381657 \h 40
6.1.1 Une seconde visite du parking PAGEREF _Toc464381658 \h 40
6.2 Classes abstraites PAGEREF _Toc464381659 \h 42
6.3 Interface PAGEREF _Toc464381660 \h 42
6.4 Exercice PAGEREF _Toc464381661 \h 43
6.5 Ce quil faut retenir PAGEREF _Toc464381662 \h 43
Vos notes PAGEREF _Toc464381663 \h 43
7 TP n° 7 : Vecteurs et listes PAGEREF _Toc464381664 \h 44
7.1 Description dun vecteur PAGEREF _Toc464381665 \h 44
7.1.1 Création dun vecteur PAGEREF _Toc464381666 \h 44
7.1.2 Quelques méthodes PAGEREF _Toc464381667 \h 44
7.2 Concordance de types et transtypage PAGEREF _Toc464381668 \h 45
7.3 Exercice PAGEREF _Toc464381669 \h 45
7.4 Ce quil faut retenir PAGEREF _Toc464381670 \h 46
Vos notes PAGEREF _Toc464381671 \h 46
8 TP n°8 : Larchitecture modèle Vue Contrôleur PAGEREF _Toc464381672 \h 47
8.1 Fonctionnement PAGEREF _Toc464381673 \h 47
8.2 Présenter des données dans des tables PAGEREF _Toc464381674 \h 48
8.3 Description des composants Listes et Tables PAGEREF _Toc464381675 \h 50
8.3.1 Les Listes PAGEREF _Toc464381676 \h 50
8.3.1.1 Constructeurs PAGEREF _Toc464381677 \h 50
8.3.1.2 Quelques méthodes PAGEREF _Toc464381678 \h 50
8.3.2 Les modèles de données « Liste » PAGEREF _Toc464381679 \h 50
8.3.2.1 Linterface ListModel PAGEREF _Toc464381680 \h 50
8.3.2.2 La classe abstraite AbstractListModel et la classe DefaultListModel PAGEREF _Toc464381681 \h 50
8.3.3 Les Tables PAGEREF _Toc464381682 \h 51
8.3.3.1 Constructeurs PAGEREF _Toc464381683 \h 51
8.3.3.2 Quelques méthodes PAGEREF _Toc464381684 \h 52
8.3.4 Les modèles de données « Table » PAGEREF _Toc464381685 \h 52
8.3.4.1 Linterface TableModel PAGEREF _Toc464381686 \h 52
8.3.4.2 La classe abstraite AbstractTableModel et la classe DefaultTableModel PAGEREF _Toc464381687 \h 53
8.4 Exercice PAGEREF _Toc464381688 \h 54
8.4.1 A faire PAGEREF _Toc464381689 \h 54
8.5 Ce quil faut retenir PAGEREF _Toc464381690 \h 55
8.6 Vos Notes PAGEREF _Toc464381691 \h 55
9 TP n°9 : Hashtables PAGEREF _Toc464381692 \h 56
9.1 Description de la classe HashTable PAGEREF _Toc464381693 \h 56
9.1.1 Constructeurs PAGEREF _Toc464381694 \h 56
9.1.2 Quelques méthodes PAGEREF _Toc464381695 \h 56
9.2 Description de linterface Enumeration PAGEREF _Toc464381696 \h 57
9.2.1 Les méthodes PAGEREF _Toc464381697 \h 58
9.3 Exercice PAGEREF _Toc464381698 \h 58
9.4 A faire PAGEREF _Toc464381699 \h 58
9.5 Ce quil faut retenir PAGEREF _Toc464381700 \h 58
9.6 Vos Notes PAGEREF _Toc464381701 \h 59
10 TP n° 10 : Arbres, récursivité PAGEREF _Toc464381702 \h 60
10.1 Spécification dun arbre PAGEREF _Toc464381703 \h 61
10.2 Exercice PAGEREF _Toc464381704 \h 62
10.2.1 A faire PAGEREF _Toc464381705 \h 63
10.3 Ce quil faut retenir PAGEREF _Toc464381706 \h 63
Vos Notes PAGEREF _Toc464381707 \h 63
A. Quelques Références PAGEREF _Toc464381708 \h 64
TP n° 1 : Concepts de base
Programmation orienté-objet
Java est un langage orienté objet. Un objet est, de manière intuitive, un ensemble de données et un ensemble de fonctions/procédures sappliquant sur ces données.
Exemple : une calculatrice élémentaire. Les deux nombres représentent les données et les opérations de base comme la multiplication ou la soustraction sont les fonctions.
Les fonctions/procédures sont appelées des méthodes. Les méthodes décrivent le comportement de lobjet.
Un programme en Java est un ensemble dobjets exécutant des méthodes ou demandant lexécution de méthodes par les autres objets en leur envoyant des messages.
Lensemble des objets de même type forme une classe dobjets.
Identifier et créer un objet
Tous les objets manipulés en Java doivent être identifiés. Cette identification permet de désigner et donc de manipuler lobjet : modifier ses données ou demander lexécution de méthodes. Une identification seffectue en mentionnant deux caractéristiques : quel est lidentifiant de lobjet et sa classe :
ClasseObjet NomObjet ;
Exemple : Pour pouvoir manipuler la calculatrice, nous déclarons un identifiant dobjet : c. Cet identifiant permettra de désigner des objets de la classe des calculatrices.
Calculatrice c ;
La ligne précédente est une déclaration. Cette définition ne permet pas davoir lobjet identifié par c à notre disposition, cest-à-dire quon ne peut pas, par exemple, demander à la calculatrice ayant lidentifiant c deffectuer une opération arithmétique. Il faut pour cela créer lobjet. La création seffectue à laide de lopérateur new. Cette instruction fait partie du jeu dinstructions de base du langage. Une création dobjet suit la syntaxe suivante :
NomObjet = new ClasseObjet(
) ;
Exemple : Pour pouvoir manipuler la calculatrice, nous créons un objet de la classe Calculatrice. Lobjet est désigné à laide de lidentifiant c. Autrement dit, c référence un objet de la classe des calculatrices
c = new Calculatrice() ;
Les données
Les données manipulées dans un objet décrivent létat dun objet. Ainsi dans un objet de la classe des thermostats, la température qui est une valeur numérique représente la température désirée. Le comportement est lui limiter à deux fonctionnalités : monter la température et descendre la température.
Maintenant considérons un client et ses commandes :
SHAPE \* MERGEFORMAT
Si nous considérons maintenant des objets de ces classes :
Un client à des caractéristiques de base (nom, ville,
) qui sont du texte et des caractéristiques plus complexes : la liste des commandes. Cette liste est en fait un objet composé dun ensemble de commandes. De fait, nous voyons que chaque commande est-elle même un objet et, que chaque ligne de commande contient deux informations : larticle et la quantité commandé. Larticle est un objet et la quantité est une valeur numérique.
Les classes
Une classe est décrite dans un document portant lextension .java. Ce document ne doit contenir quune seule classe et le nom du document est le même nom que celui de la classe.
Exemple : Nom du fichier associé à la classe LignesDeCdes : LignesDeCdes.java
Description type dune classe
Une classe est décrite à laide du mot-clef class :
class maClasse {
description de la classe (données + méthodes)
}
La description proprement dite, appelée corps de la classe, est spécifiée entre accolades.
Exemple : description de la classe lignes de commandes. Une ligne de commande contient un article et une quantité commandée. Larticle sappelle article_commande et est un objet de la classe Article. La quantité est une valeur entière.
class LignesDeCdes {
Article article_commande ; int qte_cdee ;
}
Dans un objet il ne peut y avoir que deux types dattributs :
des objets,
des valeurs primitives (qui ne sont pas des objets).
Données primitives
Les principaux types de données primitives sont représentés dans le tableau ci-après.
NomDescriptionbooleanValeur logique (true, false)charCaractèreintEntierlongEntier longfloatRéeldoubleRéel long
La déclaration de variables primitives nécessite uniquement une déclaration.
Exemple : Pour pouvoir manipuler une quantité
int qte ;
Les tableaux
Les tableaux permettent de manipuler des listes dobjets ou de données primitives. Un tableau quil soit un tableau dobjets ou un tableau de valeurs primitives est lui-même un objet.
La déclaration et la manipulation des tableaux seffectuent à laide des crochets []. Le premier indice du tableau est toujours 0. Le nom du tableau indicé permet daccéder à un item du tableau.
Exemple : déclaration dun tableau tableauValeurs de valeurs entières. Ce tableau contient dix cases.
int[] tableauValeurs ;
Les tableaux étant des objets, il convient donc de créer le tableau proprement dit après lavoir identifié. Cette opération est effectuée à laide du mot clef new.
tableauValeurs = new int[10] ;
Accès au cinquième élément du tableau et initialisation de sa valeur (à 9) :
tableauValeurs[4] = 9 ;
Plus généralement, il est tout à fait possible davoir un tableau dobjets. Dans ce cas, nous avons la même procédure en deux temps : déclaration puis création du tableau :
LignesDeCdes[] les_lignes ;
les_lignes = new LignesDeCdes[10] ;
Le résultat produit par cette dernière instruction a été la déclaration dun tableau de 10 identifiants dobjets LignesDeCdes. Il faut donc ensuite créer chaque élément du tableau individuellement. Ainsi, si nous considérons la création de la troisième ligne de commande :
les_lignes[2] = new LignesDeCdes() ;
Les chaînes de caractères
Pour manipuler les chaînes de caractères, Java propose une classe prédéfinie : String. Pour créer une chaîne, plusieurs commandes sont possibles : création dun objet ou affectation directe.
String chaine1, chaine2;
chaine1 = new String("toto") ;chaine2 = "titi" ;
Accès aux données
Les fonctions et procédures vont manipuler les données. Laccès aux données dun objet doit mentionner deux éléments : quel est lobjet accédé et quelle information de cet objet souhaitons nous consulter et/ou modifier. En Java, nous « connectons » ces deux informations à laide dun point : NomObjet.NomDonnee
Exemple : modifier la valeur du premier nombre, nommé Nombre1 de notre calculatrice c, en initialisant la valeur à 10
c.Nombre1 = 10 ;
Traduction Java de lexemple
Nous nous limitons ici à la définition des attributs. Lorsque les attributs sont des objets, nous navons donc que la spécification de lidentifiant.
Notons que chaque classe est contenue dans un fichier différent :
Client.java, Commande.java, LigneCommande.java, Article.java.
class Client {
String nom, ville, telephone ; Commande[] commandes ;
}
class Commande {
String noCde ; LigneDeCde[] lesLignes;
}class LigneCommande {
Article articleCommande ; int qte;
}
class Article {
;
}JBuilder 3
JBuilder est un outil daide au développement : aide à la définition dinterfaces, documentation, déboguage
La réalisation dun programme seffectue dans un projet : un projet regroupe un ensemble de classes et de fichiers de documentation.
Les classes sont des fichiers textes portant lextension .java et les documents sont des pages Web portant lextension .html.
Exercice
Lobjectif est de créer une première classe élémentaire pour découvrir lenvironnement JBuilder 3.
Cette classe a pour objet de décrire des bureaux. Un bureau est défini par un numéro de bureau et un occupant.
La première étape est de créer un projet : lappel de lexpert se fait avec la commande Fichier/Nouveau Projet. Lexpert projet permet de donner une première description du projet.
Cette description est utilisée par JBuilder pour créer le premier document décrivant votre projet. Ce document est présenté dans loutil de navigation du projet. Le navigateur présente dans la partie gauche deux zones : la zone supérieure répertorie lensemble des composants du projet. La partie inférieure gauche indique les caractéristiques du composant sélectionné. La partie droite affiche le document.
La seconde étape consiste à créer notre première classe. La création dune classe seffectue à laide de la commande Fichier/Nouveau
, commande présentant linvite suivant :
Après avoir choisi le composant Classe, spécifier la description de votre classe : indiquer Bureau comme nom de classe et cochez la case public.
La description de votre classe est la suivante :
class Bureau {
}
Compléter votre classe en précisant les données manipulées :
String nom_bureau;String occupant;
Létape suivante consiste à créer deux bureaux : bureau1 et bureau2 et à garnir les informations de ces bureaux.
Pour que le programme puisse fonctionner, nous devons indiquer un point de démarrage. Au démarrage, le programme créera les deux bureaux. Dans une classe le point de démarrage est spécifier à laide dune fonction particulière appelée main. La déclaration complète de cette fonction est :
public static void main(String[] args)
La description de notre classe est donc maintenant
class Bureau {
public static void main(String[] args) {
Bureau bureau1 ;
bureau1 = new Bureau() ; bureau1.nom_bureau = "ME403" ;
}
}
Le programme écrit il faut compiler et exécuter le programme :
La compilation du programme seffectue à laide de la commande Projet/Make pour le projet.
Lexécution du programme seffectue à laide de la commande Exécuter/Exécuter "bureau". Lexécution ouvre une fenêtre console et le programme sexécute dans cette fenêtre. Si la fenêtre console se referme automatiquement, bloquez son affichage en modifiant les paramètres dexécution avec le menu Exécuter/Paramètres
et inhiber la fermeture de la fenêtre :
La compilation et lexécution ne produisent aucun résultat. Il faut demander à ce que le programme affiche des données. Linstruction daffichage est la suivante :
System.out.println(valeurAAfficher) ;
Si vous demander laffichage dun des numéros de bureau, vous obtenez :
AppAccelerator(tm) 1.2.010 for Java (JDK 1.2), x86 version.
Copyright (c) 1997-1999 Inprise Corporation. All Rights Reserved.
ME403
Tapez Ctrl+C pour terminer l'application
A faire
Créer une seconde classe dans votre projet décrivant les occupants des bureaux. Les occupants ont un numéro de badge (valeur entière), un nom et un prénom.
Modifiez la classe Bureau afin que loccupant soit un objet de la classe créée précédemment. Demandez la création de deux bureaux et affichez leurs contenus.
Modifiez la classe Bureau afin de pouvoir représenter le fait quil y ait deux personnes occupant un bureau. Prenez cette modification en compte en utilisant un tableau à deux positions. Demandez la création dun bureau, initialisez les valeurs et affichez les valeurs.
Ce quil faut retenir
Comment définir une classe ;
Comment identifier et créer des objets ;
Les types de données primitives ;
La méthode main ;
Ecrire, compiler et exécuter un programme avec JBuilder.
Vos notes
TP n° 2 : définir des méthodes
Dans le TP précédent, nous nous sommes focalisés sur la description des données. Nous abordons dans ce TP la description du comportement des données. Le comportement des données est décrit à laide de méthodes. Les méthodes sont des fonctions ou procédures. Les méthodes décrivent des traitements.
Squelette dune méthode
La description dune méthode contient les éléments suivants : son nom, les arguments, la valeur de retour et la description du traitement. Autrement dit :
TypeDonneeRetour NomMethode(ListeDesArguments) {
Description de la méthode
}
De fait, la description dune classe devient : description des données et description des méthodes.
class NomClasse {
/* Description des données */
typeDonnee1 nomDonnee1 ; typeDonnee2 nomDonnee2 ;
/* Description des méthodes */
typeRetour1 methode1(
) {
}
typeRetour2 methode2(
) {
}
}
Exemple : reprenons lexemple du TP précédent : une calculatrice élémentaire. Nous ajoutons une méthode additionner à la classe. La classe contient deux nombres entiers nb1 et nb2 :
class Calculatrice {
/* Description des données */
int nb1, nb2 ;
/* Description des méthodes */
}
Décrivons tout dabord lentête : la valeur retournée est un nombre entier, le nom de la méthode est additionner et la liste des arguments est vide car les deux nombres à additionner sont déjà dans la calculatrice (nb1 et nb2). Le corps de la méthode doit additionner ces deux valeurs et indiquer que le total doit être la valeur à retourner. Autrement dit :
int additionner() {
int total ; // déclaration dune variable
total = nb1 + nb2 ; // traitement
return total ; // retour de la méthode
}
Nous voyons sur lexemple que nous pouvons déclarer des variables ou plus généralement des données dans le corps dune méthode. Le corps dune méthode contient trois éléments principaux :
Instructions de déclarations de données + instructions de traitements + instructions de retour
Notons aussi dans lexemple que la valeur retournée est bien une valeur entière (cf. déclaration de total).
Valeur de retour
Linstruction de retour, qui « normalement » conclut le corps de la méthode est return suivi de lobjet retourné. Le type de lobjet doit être le même que celui mentionné dans lentête de la méthode. Notons quune méthode peut aussi bien retourner un objet, quune valeur primitive.
Lorsquune méthode ne retourne aucune valeur celle-ci est de type void. Linstruction return qui apparaît dans la liste des instructions ne mentionne pas dans ce cas dobjet.
Appeler la méthode dun objet
Les méthodes sont dans des objets. Lappel dune méthode doit donc mentionner lobjet associé. Autrement dit, il faut mentionner : le nom de lobjet + le nom de la méthode. Lassociation entre ces deux éléments se fait avec un point :
variableRecuperation = nomObjet.nomMethode(listeDesArguments) ;
Il est clair que la variable récupérant la valeur renvoyée par la méthode doit être compatible avec la valeur retournée par la méthode.
Lorsque la méthode est de type void, il ne faut pas mentionner de variable de récupération :
nomObjet.nomMethode(listeDesArguments) ;
La liste des arguments
La liste des arguments spécifie les informations additionnelles nécessaires au traitement effectué par la méthode. Additionnelles car elles ne sont pas présentes dans les données internes à la classe. La liste des arguments est une liste dobjets et/ou de données de base. Chaque argument de la liste est séparé par une virgule, et la description de largument se fait en deux temps : type de la variable et nom de la variable. Autrement dit :
TypeRetour nomMethode(typeVar1 nomVar1, typeVar2 nomVar2,
) {
}
Exemple : supposons que nous ajoutions une méthode pour initialiser les deux nombres de notre calculatrice. Cette méthode reçoit en paramètre deux valeurs entières et ne retourne aucune valeur.
void initNombres(int valeur1, int valeur2) {
nb1 = valeur1 ; // traitement nb2 = valeur2 ;
return ; // retour de la méthode
}
Lappel se fera comme suit, si nous supposons disposer dun objet calculatrice nommé c :
c.initNombres(3,7) ;
i = 10 ;c.initNombres(i,8) ;
Les instructions de traitements
Le dernier point concerne le jeu dinstructions proprement dit. Nous donnons ici quelques instructions types. Pour une liste exhaustive, se référer au manuel Java en ligne.
Opérateurs mathématiques
Les opérateurs mathématiques se subdivisent en trois catégories : les opérateurs arithmétiques, les opérateurs de comparaison, les opérateurs logiques.
Tableau SEQ Tableau \* ARABIC 1 : opérateurs arithmétiques
SymboleDescription+Addition-Soustraction*Multiplication/Division%Modulo =Assignation++Opérateur unaire dincrémentation.--Opérateur unaire de décrémentation.
Tableau SEQ Tableau \* ARABIC 2 : opérateurs de comparaison
SymboleDescription>Supérieur valeur2) rst = 1; else rst = -1 ;
return rst;
Les instructions ditérations
Les instructions ditérations sont au nombre de trois : le TANTQUE FIN TANTQUE, le REPETER JUSQUA et la boucle POUR. Les deux premières boucles sont représentées ci-après. Notons que le REPETER JUSQUA (boucle de droite) na pas de représentation directe. En effet la condition est une condition darrêt alors que la traduction en Java par un do
while exige une condition de poursuite.
while(condition) instruction do instructionwhile(condition) ;
La boucle POUR est représentée par linstruction for. Linstruction exige trois arguments : une instruction dinitialisation, une expression logique de poursuite et une instruction à exécuter à chaque boucle.
for(initialisation ; condition de poursuite ; pas) instruction
Exemple : initialiser un tableau à 0. Supposons une classe Tableau contenant comme attribut un tableau de valeurs entières :
class Tableau {
static int DIMENSIONTABLEAU = 10;
int[] tableau;
}
La méthode initialise crée le tableau et initialise toutes les valeurs à zéro.
class Tableau {
static int DIMENSIONTABLEAU = 10;
int[] tableau;
void initialiser() {
int i ;
tableau = new int[DIMENSIONTABLEAU];for(i = 0 ; i < DIMENSIONTABLEAU ; i++) tableau[i]=0 ;
}
}
Exercice
Lobjectif de ce programme est de pouvoir calculer des résultats électoraux. Il sagit de pouvoir construire des méthodes simples et de les appeler.
IL sagit de décrire des élections locales. Dans une élection, il y a plusieurs candidats. Chaque candidat a un nom et un prénom. Nous supposons quà chaque élection il y a trois candidats. Dans une élection, chaque candidat obtient des suffrages (nombres de voix). Autrement dit, les données vont être structurées comme suit :
Implémenter les classes en Java.
Ajouter une méthode main à votre classe Election et créer des objets des différentes classes.
Implémenter les fonctionnalités ci-après. Pour chaque service, définissez tout dabord à quelle classe celui-ci doit être attaché. Ensuite, déterminez la spécification de vos méthodes : valeur retournée et paramètres attendus :
Un service calculant la proportion de voix obtenues par un candidat.
Un service déterminant si un candidat est éliminé (nb. voix < 25%), maintenu au second tour (25% < nb. voix < 50%) ou élu (> 50%).
Prenez soin de créer un nouveau projet pour votre travail. Vous supposerez que les données sont chargées dans la fonction main. La fonction main appellera aussi les méthodes et affichera les résultats.
A faire
Modifier le programme pour quil puisse prendre en compte plusieurs bureaux de vote. La définition de classe(s) supplémentaire(s) est nécessaire.
Définir une méthode retournant un tableau contenant le(s) nom(s) des candidats admis au second tour ou du candidat élu.
Ce quil faut retenir
Description dune méthode (Type de donnée en retour, arguments,
) ;
Appel de méthodes ;
Instructions de traitement : les instructions, bloc dinstructions, les boucles les conditionnels.
Vos notes
TP n°3 : Affiner la définition des classes Constructeurs et visibilités
Lobjectif du TP est de détailler le processus de création des classes : travail dinitialisation lors de la création dobjets et contrôle des accès aux données internes dune classe.
Constructeurs
Il est fréquent lors de la création dobjets quune étape dinitialisation soit nécessaire. Il sagit par exemple dinitialiser un tableau à zéro, ou bien effectuer des créations préalables. Ces instructions sont à effectuer à la création de lobjet. Il faut donc préciser dans le programme quà lexécution de linstruction new Classe(), il faut exécuter un bloc dinstructions additionnel. Ce mécanisme peut être garanti par lutilisation de constructeurs. Un constructeur est une méthode spéciale où sont spécifiées les instructions dinitialisation. Un constructeur est facilement identifiable car il porte le même nom que la classe.
La présence dun constructeur nest pas obligatoire. Il y a toujours une procédure de création implicite par défaut définie dans Java.
Exemple : constructeur initialisant directement les valeurs dun occupant de bureau. Un occupant est décrit par un nom et un prénom ainsi quun numéro de badge.
class Occupant {
String nom, prenom ; int num_badge ;
Occupant(String nom, String prenom, int badge) {
this.nom = nom ; // description du constructeur this.prenom = prenom ; this.num_badge = badge ; }
}
Notons quun constructeur ne retourne jamais de valeur. Autrement dit un constructeur nest pas une méthode. Les instructions sont exécutées lors de la création de lobjet. A lutilisation de linstruction, il doit y avoir correspondance entre les types de données spécifiés dans le constructeur et les arguments envoyés :
o = new Occupant("Sartre","Raymond",12) ;
Le constructeur permet dunifier la création et linitialisation. Si lobjet doit être initialisé différemment en fonction des paramètres reçus, il faut alors définir plusieurs constructeurs.
Exemple : dans la classe Occupant, nous ajoutons un second constructeur. Ce constructeur permet de créer un occupant sans initialiser les valeurs.
class Occupant {
String nom, prenom ; int num_badge ;
Occupant() {
nom = "" ; // description du premier constructeur prenom = ""; num_badge = 0 ;
}
Occupant(String nom, String prenom, int badge) {
this.nom = nom ; // description du second constructeur this.prenom = prenom ; num_badge = badge ;
}
}
Visibilité des classes et de leur contenu
Les informations contenues dans une classe sont accessibles, par défaut, depuis les autres classes. Cette visibilité nest que partiellement nécessaire, certaines données sont des informations temporaires ou de travail et nexigent pas dêtre visibles depuis lextérieur, cest-à-dire des autres classes.
Visibilité de la classe
Afin que les classes soient accessibles elles doivent être déclarées publiques (public). Les classes qui ne sont pas publiques sont accessibles uniquement par les classes contenues dans le paquetage dorigine de cette classe.
Visibilité des données et méthodes
Les droits daccès aux données et méthodes dun objet sont de trois niveaux : public, privé et protégé.
public : les méthodes et données mentionnées comme publiques sont visibles depuis nimporte quel autre objet (i.e. les données étant accessibles, elles sont donc modifiables).
private : les méthodes et données privées sont inaccessibles depuis les autres classes. Le seul moyen daccès est depuis la classe elle-même.
protected : les données sont visibles et modifiables par les sous-classes de la classe. Elles sont aussi accessibles depuis les classes du même paquetage.
Une règle, qui nest pas systématique, veut que les données soient privées. Ceci permet de les protéger daccès malencontreux mais garantit une indépendance des services : les classes sont utilisées conformément aux services annoncés et les services utilisent les données quils souhaitent (autrement dit peu importe la manière dont le service est rendue).
Laccès aux données sera défini plus finement en spécifiant des méthodes permettant de connaître une valeur (get) et des méthodes permettant de modifier une valeur (set).
Exemple : La classe Occupant est spécifiée publique et les données privées. Nous donnons une méthode daccès aux noms et de modification du prénom qui sont publiques. Les constructeurs sont spécifiés en tant que publics.
public class Occupant {
private String nom, prenom ; private int num_badge ;
public Occupant() {
nom = "" ; // description du premier constructeur prenom = ""; num_badge = 0 ;
}
public Occupant(String nom, String prenom, int badge) {
this.nom = nom ; // description du second constructeur this.prenom = prenom ; num_badge = badge ;
}
public String getNom() {
return nom ;
}
public void setPrenom(String p) {
prenom = p ; return ; }
}
Exercice
Lobjectif du programme est de pouvoir ranger des véhicules dans un parking. Un parking est un ensemble de places et à chaque place il peut y avoir un véhicule :
1111 AA 312222 BB 324444 DD 33Vide3333 EE 34
Un véhicule est identifié par son numéro et est localisé par son numéro de place. Un véhicule est rangé à la première place libre trouvée.
La classe parking doit rendre les services suivants :
Ranger une voiture,
Enlever une voiture,
Indiquer le nombre de places libres.
Faire le diagramme de classes. Spécifiez les attributs et méthodes. Précisez la visibilité des attributs et méthodes.
Définissez le constructeur de chaque classe.
Prenez soin de créer un nouveau projet pour votre travail. En plus de vos classes, créez une classe Programme. La classe Programme contiendra uniquement une fonction main qui créera un parking et chargera des valeurs dans celui-ci (c.à.d. ranger des voitures). La fonction main appellera aussi les méthodes et affichera les résultats. Cette distinction permettra de réutiliser la classe Parking ultérieurement.
A faire
Réutiliser votre classe pour définir les parkings de bateau : dans un bateau (un ferry) les véhicules sont rangés les uns derrière les autres. Lentrée des véhicules seffectue par une porte et la sortie seffectue soit par la même porte ou soit par la porte opposée. Dans le petit parking de bateau ci-après la porte avant est à gauche :
3333 EE 342222 BB 324444 DD 331111 AA 31Vide
Vous détaillerez les deux cas suivants (les classes représentant les parkings de ferry doivent rendre les mêmes services que pour les parkings simples) :
Entrée par la porte arrière et sortie par la porte avant. (cf. illustration ci-dessus). Le dernier véhicule entré est le véhicule 1111 AA 31 et le seul véhicule pouvant sortir est celui près de la porte, à savoir le 3333 EE 34.
Entrée par la porte avant et sortie par la porte avant. Le dernier véhicule entré est le véhicule 1111 AA 31. Ce véhicule est le seul pouvant sortir car il est le plus près de la porte (avant).
2. Grand parking : un grand parking est un parking composé de plusieurs rangées de places. Autrement dit un grand parking est composé de plusieurs parkings élémentaires. Lorsquune voiture veut stationner dans un grand parking, elle se range dans la première place libre dune rangée incomplète.
Un véhicule est localisé par son numéro de rangée et numéro de place dans la rangée.
Un grand parking rend les mêmes services quun parking élémentaire.
Ce quil faut retenir
Les constructeurs, constructeurs multiples et leur rôle dinitialisation ;
La visibilité des classes et de leur contenu (plus particulièrement les droits public et private).
Vos notes
TP 4 : Création dun dialogue
Lobjectif de ce TP est de créer une interface simple afin de mettre en uvre les principaux concepts nécessaire à la gestion de dialogue.
Java fourni en standard une bibliothèque de composants pour la création dinterfaces graphique : fenêtre, boutons, menus
Cette bibliothèque permet de construire des applications qui auront le même aspect quelque soit la machine cible (Unix, MacOS, Windows
).
Une première version appelée AWT (Abstract Window Toolkit) a été proposée et grandement amélioré avec les JDK de la série 1.1.x. Avec Java 2, ou encore Java 1.2, Sun a proposé une deuxième bibliothèque appelé Swing et exploitant lAWT. Swing permet de construire des interfaces ayant un aspect beaucoup plus agréable et offrant des possibilités beaucoup plus importante.
La construction dune interface
La définition de linterface utilisateur se décompose en trois activités principales :
Création des composants,
Placement des composants,
Rendre actif les composants : prise en compte des événements.
Les composants
Chargement des bibliothèques
Afin de pouvoir utiliser les composants Swing, il faut faire appel à cette bibliothèque. En Java, une bibliothèque est un paquetage et le chargement dun paquetage seffectue avec la clause import. Le nom de la bibliothèque est javax.swing. Dans cette bibliothèque, nous souhaitons utiliser de nombreux composants, aussi chargeons nous toute la bibliothèque :
import java.awt.*;import javax.swing.*;
Nous chargeons lensemble des composants de la bibliothèque AWT car Swing sappuie sur celle-ci. Toutes les classes définies dans ces deux paquetages (packages) sont maintenant accessibles.
Type de composants
Les composants sont de deux types : les conteneurs et les contrôles. Les conteneurs sont les espaces daccueil des contrôles.
Conteneurs : fenêtre, panneau,
Contrôles : bouton, liste, boite à cocher,
Les conteneurs
On distingue deux principaux types de conteneur (Container) : une fenêtre ou un morceau de fenêtre. Un morceau de fenêtre est un panneau (classe Panel en AWT ou la classe JPanel en Swing). Les fenêtres (Window ou JWindow) se subdivisent en deux catégories : les fenêtres de dialogue souvent appelée boites de dialogue (Dialog ou JDialog) et les fenêtres de travail (Frame ou JFrame). Cest dans ces dernières que sexécutent les applications. Les boites de dialogue servent principalement à la production de messages dinformation ou à la saisie dinformation. La hiérarchie des conteneurs est la suivante :
EMBED OrgPlusWOPX.4
Dimensionner une fenêtre
Spécifier la taille de la fenêtre :
// longueur et largeur : nombre de pixels.
d = new Dimension(longueur, largeur);
nomFenetre.setSize(d);
Laisser JAVA dimensionner la fenêtre en la compactant :
nomFenetre.pack(d);
Les contrôles
Les contrôles permettant de conduire des dialogues simples avec un utilisateur sont respectivement : JButton (bouton), JCheckbox (boite à cocher), JChoice (les listes à choix), JList (listes simples). Parmi les contrôles auxiliaires citons ceux relatifs aux menus : JMenu, JMenuitem (les différents choix dun menu), JMenubar (un ensemble de menus).
Les contrôles de bases sont suffisants pour effectuer nombre de tâches. Les contrôles offerts par JBuilder (paquetage com.borland.jbcl.control.*) et par AWT utilisent des méthodes « relativement » similaires à celles du paquetage Swing. Comme pour les conteneurs, nous indiquons la hiérarchie des contrôles :
EMBED OrgPlusWOPX.4
Ajouter un contrôle à un conteneur
Lajout dun contrôle à un conteneur seffectue toujours dans un panneau JPanel. Par défaut toutes les fenêtres ont un panneau central. Pour accéder à ce panneau, il faut utiliser linstruction getContentPane().
Exemple : Ajouter un bouton dans une fenêtre sappelant maFenetre.
maFenetre.getContentPane().add(new JButton("OK"))
Lajout dun composant seffectue à laide de la commande add.
Un contrôle qui est ajouté est positionné dans le conteneur en fonction du gestionnaire de positionnement (layout).
Quelques méthodes communes à tous les contrôles
Nom méthodeRôleboolean isEnabled()Renvoie si le contrôle est actif ou nonvoid setEnabled(boolean b)b specifie si le composant doit être actif ou non.Void setSize(int l, int h) Dimensionne le composant aux tailles l(ongueur) et h(auteur).String toString()Transforme lobjet au format chaîne.
Description des contrôles
Les boutons
Constructeurs
JButton()
JButton(String caption)
Quelques méthodes
Nom méthodeRôleString getText()Obtenir le texte saffichant dans le boutonvoid setText(String s)La chaîne s est le nouveau texte saffichant dans le bouton.
Exemple :
b1 = new JButton() ;
b1.setText("OK") ;
maFenetre.getContentPane().add(b1) ; // ajout à la fenêtre courante.
maFenetre. getContentPane().add(new JButton("Cancel")) ; // idem mais plus compact.
Les boites à cocher
Une boite à cocher est un contrôle pouvant être à vrai ou faux.
Constructeurs
JCheckbox()
JCheckbox(String label) : label contient le libelle de la boite.
JCheckbox(String l, boolean s) : l contient le libelle et s létat initial de la boite.
Quelques méthodes
Nom méthodeRôleCheckboxGroup getCheckboxGroup()Obtenir le groupe où la boite est membreString getText()Obtenir le libellé de la boite.Boolean getSelected()Obtenir létat de la boite (vrai ou faux)void setText(String s)Assigner le libellé s à la boite.void setSelected(boolean b)Assigner létat b à la boite (vrai ou faux)
Exemple :
c = new JCheckbox() ;
c2 = new JCheckBox("Me tenir informé", true)
c.setSelected(true) ;
Les listes de choix
Les listes de choix (ComboBox) fonctionnent comme un menu : lutilisateur sélectionne un composant dans la liste proposée et celui-ci devient actif. Les listes de choix permettent doffrir différentes éventualités en un espace compacte.
Constructeurs
JComboBox()
JComboBox(Object[] tableauObjets) : la liste des choix qui doit être présentée à lutilisateur est transmise avec un tableau dobjets.
JComboBox(Vector vecteurObjets) : idem sauf que la liste est transmise avec un vecteur.
Quelques méthodes
Nom méthodeRôlevoid addItem(Object o)Ajouter lobjet o à la liste de choix. void addItemAt(Object o, int p)Ajouter lobjet o à la liste de choix à la place mentionné par p.Object getItemAt(int i)Obtenir le ième élément sous la forme dune chaîne. int getItemCount()Obtenir le nombre déléments dans la liste.int getSelectedIndex()Obtenir la position dans la liste de lélément sélectionné. La liste débute à zéro.Object getSelectedItem()Obtenir lélément sélectionné dans la liste.void insertItemAt(Object o, int i)Ajoute lélément o à la position i dans la liste.void removeItemAt(int i)Oter le ième élément de la liste.void removeItem(Object o)Oter lélément o de la liste.void removeAllItems()Oter tout les éléments de la liste.void setSelectedIndex(int i)Lélément sélectionné est le ième élément.void seSelectedItem(Object o)Lélément sélectionné est lélément o.
Exemple :
coloris = new JComboBox();
coloris.addItem("Vert");
coloris.addItem("Rouge");
coloris.addItem("Bleu");
coloris.setSelectedIndex(2)
// la couleur sélectionnée par défaut est le bleu.
System.out.println(coloris. GetItemCount()) // affiche 3 dans la console
String[] oiseaux = {"corbeau", "canari", "perroquet"} ;
// créer et charger un tableau de chaines
listeOiseaux = new JcomboBox(oiseaux) ;
Les listes
Les listes fonctionnent différemment des liste de choix : lutilisateur fait défiler la liste pour sélectionner (éventuellement) un ou plusieurs éléments. Un élément est sélectionné en cliquant sur celui-ci (une nouvelle sélection annulant la première).
Constructeurs
JList()
JList(Object[] tableauObjets) : les données qui doivent être présentées à lutilisateur sont transmises avec un tableau dobjets.
JList(Vector vecteurObjets) : idem sauf que les données sont transmises avec un vecteur.
Quelques méthodes
Nom méthodeRôlevoid clearSelection()Effacer la sélection.int getSelectedIndex()Obtenir la position dans la liste de lélément sélectionné. La liste débute à zéro.int[] getSelectedIndices()Obtenir lensemble des positions sélectionnés dans la liste. Le résultat est donné sous la forme dun tableau.Object getSelectedValue()Obtenir lélément sélectionné dans la liste.Object[] getSelectedValues()Obtenir sous la forme dun tableau dobjets, lensemble des éléments sélectionnés de la liste.boolean isSelectedIndex(int i)Renvoie vraie si lélément i est sélectionné (sinon faux).boolean isSelectionEmpty()Vrai si aucun élément nest sélectionné dans la liste.void setSelectedIndex(int i)Sélectionne lélément dindice i dans la liste.void setSelectedIndices(int[] tab)Sélectionne la valeur spécifiée par les indices du tableau tab.void setSelectionMode(int mode)Spécifie le mode de sélection unitaire ou multiple. Les valeurs possibles sont SINGLE_SELECTION, SINGLE_INTERVAL_SELECTION, MULTIPLE_INTERVAL_SELECTION.void setVisibleRowCount(int i)Spécifie le nombre de lignes affichées par la liste.
Exemple :
String[] oiseaux = {"corbeau", "canari", "perroquet"} ;
// créer et charger un tableau de chaines
String s ;
listeOiseaux = new JList(oiseaux) ;
listeOiseaux.setSelectedIndex(1) ; // sélection de canari
s = (String)listeOiseaux.getSelectedValue // s contient canari.
Les zones de saisie
Les zones de saisie sont des contrôles textuels. Ils permettent lédition de texte sur une seule ligne.
Constructeurs
JTextField()
JTextField(int nbChar) : créer une zone de saisie de nbChar caractères.
JTextField(String s) : créer une zone de saisie contenant la chaîne s (valeur par défaut).
JTextField(String s, int nbChar) : créer une zone de saisie contenant la chaîne s (valeur par défaut) et ayant un longueur de nbChar caractères.
Quelques méthodes
Nom méthodeRôleString getText()Obtenir le texte saffichant dans la zone de saisie.Boolean isEditable()Renvoie vraie si la zone peut être éditée (cest-à-dire saisie).Void setEditable(boolean b)Spécifie si le contenu de la zone est modifiable ou non.Void setText(String s)La chaîne s est le nouveau texte de la zone de saisie.
Disposer les contrôles
Les programmes en Java sont supposés sexécuter sur tout type de machine. Ceci contraint à exclure le plus possible les références au matériel dans la définition et le placement des composants. La disposition des contrôles est relative. Cest-à-dire quil faut indiquer les positions à laide de balises : à gauche, au nord
Pour effectuer la disposition des contrôles, les contrôleurs ont besoin dun gestionnaire de disposition. En Java, un gestionnaire de disposition sappelle un LayoutManager. Lassociation se fait en plusieurs temps :
Création dun gestionnaire de disposition ;
Association du gestionnaire au conteneur ;
Utilisation du gestionnaire pour placer les contrôles.
// associer un gestionnaire de type BorderLayout.
g = new BorderLayout();
nomFenetre.getContentPane().setLayout(g);
// ajout dun controle
nomFenetre.getContentPane().add(nomControle, "North") ;
En fonction de la disposition souhaitée, Swing (et AWT) nous propose différents gestionnaires de disposition :
EMBED OrgPlusWOPX.4
FlowLayout
Les éléments sont en ligne les uns après les autres. Si la ligne ne peut contenir tous les composants, ceux-ci sont alors disposés sur plusieurs lignes.
BorderLayout
Les éléments sont placés dans un espace de cinq zones : North, South, West, Center, East
.
GridLayout
Les éléments sont placés dans un espace divisés en ligne et colonnes. Le nombre de lignes et colonnes est indiqué en paramètre dans le constructeur du gestionnaire.
GridBagLayout
Les éléments sont placés dans un espace divisés en ligne et colonnes. Le nombre de lignes et colonnes est indiqué en paramètre dans le constructeur du gestionnaire. Ce gestionnaire est plus sophistiqué que le précédent car il permet davoir des lignes et colonnes de taille différente et il permet aussi de poser des contrôles sur plus dune cellule.
Exercice
Lobjectif de ce programme est de définir une interface pour une utilisation ultérieure de la classe Parking. Pour ceci nous allons créer deux classes : une classe programme et une fenêtre. La classe programme contient la fonction main. Cette fonction va créer la fenêtre et afficher la fenêtre. Pour effectuer cette opération, il faut créer une application dans JBuilder.
La seconde étape consiste à donner la description de la fenêtre:
La seule option nécessaire pour le moment, cest le centrage de la fenêtre à lécran. Dans le navigateur de projet les deux classes sont ajoutés.
Analyser les instructions.
Nous allons maintenant construire la fenêtre à laide de lassistant de conception de JBuilder. Cet assistant est appelé à laide de longlet Conception (il faut bien sur demander lassistant pour la fenêtre).
Associez maintenant un gestionnaire de disposition de type FlowLayout et posez les contrôles Swing pour aboutir au résultat suivant :
Pour la construction dinterfaces plus complexes, les gestionnaires de disposition sont insuffisants. Leur rusticité est compensée par un recours aux panneaux (JPanel).
Créer une fenêtre similaire à la fenêtre suivante en utilisant différents panneaux et gestionnaires de disposition :
A faire
Ajouter un label spécifiant combien de places sont libres dans le parking ainsi quun bouton pour quitter le programme.
Déterminer une représentation du parking simple (les places avec leurs véhicules).
Ce quil faut retenir
La distinction conteneur/composant ;
La disposition relative des composants dans les conteneurs ;
La conception de fenêtre avec JBuilder.
Vos notes
TP n°5 : Gérer des événements
Lobjectif de ce TP est daborder la dynamique des interfaces utilisateurs. Dans le TP précédent, nous avons montré comment définir des fenêtres et des composants. Les interfaces sont pour linstant statiques : il faut spécifier les actions devant être exécutées lorsque lutilisateur effectuera certaines commandes. Ces commandes sont appelés des événements.
La gestion des événements
La gestion des événements sappuie sur un modèle de délégation des événements. Les sources des événements sont les composants Swing ou awt :
Un événement est propagé dune source à un contrôleur.
Le gestionnaire sassure de la création et de la propagation de lévénement : seul le contrôleur reste à implémenter. Une interface, cest-à-dire un gabarit, est prédéfini dans JAVA pour tous les types de contrôleur.
Pour utiliser le gestionnaire dévénements il faut utiliser le paquetage java.awt.event.*.
Le contrôleur de la fenêtre
La classe WindowAdapter est une implémentation prédéfinie de linterface WindowListener. Pour utiliser ce dernier comme base :
public class maClasseControleurDeFenetre extends WindowAdapter
Pour associer le contrôleur à la fenêtre :
NomObjetControleur = new maClasseControleurDeFenetre() ;
MaFenetre.addWindowListener(nomObjetControleur) ;
Exemple de contrôleur :
public class maClasseControleur extends WindowAdapter {
// levenement fermeture declenche larret du
// programme.
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
Le contrôleur des contrôles
Les contrôles doivent eux aussi être associé à des événements. Ceux-ci prennent en charge la demande dune action, comme le changement dune valeur par exemple. Les contrôleurs type prédéfinis sont ActionEvent, TextEvent, ItemEvent. Ils sont décrits à laide dinterface et doivent donc être implémentés.
public class monControleur implements ActionListener
Pour associer un contrôleur monControleur à un bouton monBouton :
monBouton .addActionListener(monControleur) ;
Dans une classe implémentant un contrôleur de commande (pour les boutons par exemple), il faut ensuite décrire la méthode donnant les instructions à exécuter : celle-ci a comme nom actionPerformed :
public class btnQuitterControleur implements ActionListener {
/* action a executer avec le bouton quitter
il faut arreter le programme */
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
question de méthode
Dans un programme orienté-objet, pour des considérations de conception et de maintenance, il faut limiter les objets à un seul rôle : il ne faut pas confondre, par exemple : un traitement et la représentation de ce traitement.
Si nous reprenons des travaux effectués précédemment sur les parkings et linterface utilisateur pour les parkings, nous devons retrouver cette dichotomie :
création / définition dun objet Parking,
création / définition dune interface utilisateur sappliquant à cet objet,
Linterface permet denvoyer des messages à lobjet Parking pour ranger ou enlever des voitures.
Autrement dit, la gestion des événements doit se limiter à trois grandes opérations :
récupérer les données fournies par lutilisateur grâce à linterface,
transmettre ces données aux objets « application » (éventuellement reformatées) sous la forme denvoi de message,
transmettre à lutilisateur le compte-rendu transmis par lappel des méthodes, ce compte-rendu est transmis grâce à linterface.
Exercice
Lobjectif de lexercice est dassocier linterface définie dans le TP précédent à lobjet Parking. Lapplication comprendra trois classes : PrgParking, WinParking, Parking. La première des trois classes contient la fonction main qui :
Crée un objet Parking p.
Crée une fenêtre f, instance de la classe parking. La fenêtre est une représentation du parking p. Celui-ci est donc transmis en paramètre de création de la fenêtre.
Affichage de la fenêtre f.
Concernant la classe winParking, il faut maintenant définir la gestion des événements. La création des contrôleurs peut être faite à partir de JBuilder :
JBuilder propose un nom de méthode par défaut et génère son gabarit. Il suffit alors de compléter les instructions. Ainsi pour le bouton ranger qui se nomme btnRanger, le gabarit est le suivant :
void btnRanger_actionPerformed(ActionEvent e) {
}
Compléter les gestionnaires dévénements : les instructions exécutées par un bouton sont :
mise à jour du parking (retrait, enlever) ou demande dinformation (nb. véhicules);
affichage dun compte-rendu à lopérateur par une boite de dialogue dinformation (méthode de classe JOptionPane.showMessageDialog(
)).
A faire
1. Créer les interfaces utilisateurs pour les deux types de parkings de ferry.
2. Coupler une interface utilisateur à la classe des grands parkings.
Ce quil faut retenir
La séparation application / représentation de lapplication.
La notion dévénements,
La notion de contrôleur dévénements,
Un composant « actif » a au moins un contrôle.
Vos notes
TP n°6 : Héritage et interface
Lobjectif de ce TP est de mettre en pratique les notions dhéritage et de classes abstraites.
Héritage
Lhéritage consiste à spécifier quune classe est similaire à une autre classe. En indiquant quune classe hérite dune autre classe, vous obtenez accès à toutes les données et méthodes membres de la classe ancêtre.
Lhéritage sert donc à étendre des classes, soit en Java :
Class VoituresCarburant extends Voiture {
}
Une seconde visite du parking
Voici une description des parkings simples et parking de ferry mettant en uvre les concepts dhéritage.
public class parking {
/* les donnees sont declarees Protected
car elles doivent etre visibles des
sous-classes
*/
protected static int NBMAXPLACES = 5;
protected String[] Places;
public parking() {
int i;
Places = new String[NBMAXPLACES];
for (i = 0; i < NBMAXPLACES; i++)
Places[i] = "";
}
public int getNbPlaces() {
int i, nbplaces;
nbplaces = 0;
for(i = 0; i < NBMAXPLACES; i++) {
if(Places[i].equals(""))
nbplaces = nbplaces + 1;
}
return nbplaces;
}
public boolean rangerVoiture(String numVoiture) {
int i, noplace;
boolean trouvePlace;
// quid si on range deux fois la meme voiture.
trouvePlace = false;
noplace = 0;
for(i = 0;(trouvePlace == false) && (i < NBMAXPLACES); i++) {
if(Places[i].equals("")) {
noplace = i;
trouvePlace = true;
}
}
if(trouvePlace == true)
Places[noplace] = numVoiture;
return trouvePlace;
}
public boolean enleverVoiture(String numVoiture) {
int i, noplace;
boolean trouveVoiture;
trouveVoiture = false;
noplace = 0;
for(i = 0; i < NBMAXPLACES; i++) {
if(Places[i].equals(numVoiture)) {
noplace = i;
trouveVoiture = true;
}
}
// liberation de la place
if(trouveVoiture == true)
Places[noplace] = "";
return trouveVoiture;
}
}/* la classe parkingAvantArriere est une classe derivee de parking.
*/
public class parkingAvantArriere extends parking {
protected int position;
/* specifie l'emplacement de la prochaine voiture a ajouter.
la premiere place face a la porte avant est en position zero. La place pres de la porte arriere est en NBMAXPLACES - 1
c'est-a-dire la derniere place du tableau. l'information est de type protogee car elle est reutilisee dans les classes parentes.
*/
public parkingAvantArriere() {
/* appel du constructeur de la classe parente
c'est-a-dire parking
*/
super();
position = NBMAXPLACES - 1;
}
/* la classe getNbPlaces n'est pas
implementee : elle est heritee de parking
la methode parkingPlein() est une methode
auxiliaire pour ajouter des voitures. elle n'est donc visible que de la classe (declaration en "private").
*/
private boolean parkingPlein() {
// le parking est plein si la 1ere place face
// a la porte avant est occupee.
return (!Places[0].equals(""));
}
public boolean rangerVoiture(String numVoiture) {
if(parkingPlein() == false) {
Places[position] = numVoiture;
position--;
return(true);
} else
return(false);
}
/* le retrait de voiture n'exige plus de recevoir en parametres le numero de la voiture:
la voiture qui sort est celle qui est devant la porte.
la methode renvoie non plus un booleen pour indiquer si la voiture a pu etre sortie mais une chaine contenant le numero de la voiture qui vient d'etre enlevee. Si la voiture ne peut être enlevee, la valeur null est alors retournee.
lorsque la voiture est retiree du parking : toutes les voitures avancent pour se mettre pres de la porte arriere : la place est ainsi liberee cote porte avant.
*/
public String enleverVoiture() {
String voiture;
int i;
voiture = Places[NBMAXPLACES - 1];
/* toutes les voitures avancent d'une place :
elles prennent la place de la suivante
sauf la derniere qui laisse une place libre.
*/
for(i = NBMAXPLACES - 1; i > position + 1; i--)
Places[i] = Places[i - 1];
Places[position + 1] = "";
// la premiere place libre est maintenant plus pres de
// la porte arriere.
position++;
if(voiture.equals(""))
return null;
else
return voiture;
}
}
Classes abstraites
Dans une classe, les données et les entêtes des méthodes donnent la spécification de la classe. Ces informations sont les informations visibles depuis lextérieur. Une classe abstraite a pour objet de donner non pas une implémentation de la classe mais de décrire simplement sa spécification. Les classes abstraites contiennent des méthodes abstraites. Toutes les méthodes ne sont pas forcément abstraites dabs une classe abstraite.
Les classes et/ou les méthodes abstraites permettent de représenter des notions génériques. Considérons par exemple, une classe représentant des clients. Ces clients sont des clients douteux ou des clients « neutres » ou, enfin, des bons clients.
EMBED Word.Picture.8
Limplémentation du calcul de la ristourne ne peut être décrit avec le client générique. Elle doit être concrétisée avec la description des sous-classes.
La définition de la classe client est elle la suivante :
public abstract class Client {
public abstract void ristourne() ;
}
Interface
Une interface est une classe abstraite où toutes les méthodes sont abstraites et où les seules données spécifiées sont des constantes.
Tout comme pour les classes abstraites, les interfaces ne peuvent être instanciées. La définition de classes interfaces héritant de classes interfaces est possible. Une classe interface permet de spécifier les méthodes devant être implémentée par toute classe issue de la classe interface.
Reprenons notre exemple précédent et considérons que nous considérions la classe client comme une classe interface. Nous obtenons alors pour la définition de la classe client et la description des classes héritées :
public interface Client {
public abstract void ristourne() ;
}
public class ClientDouteux implements Client {
public void ristourne() {
}
}
Toute classe ne peut héritée que dune seule classe. Toutefois elle peut implémenter simultanément plusieurs interfaces.
public maFenetre extends Jframe implements windowListener
implements mouseListener
implements keyListener {
}
Exercice
Lobjectif de cet exercice est décrire un programme rassemblant un ensemble de classes se combinant entre elles par héritage et/ou implémentant une ou plusieurs interfaces.
Il sagit de représenter des séjours hôteliers et des locations de voitures. Une location de voiture consiste à louer un véhicule dune catégorie c pendant n jours. A cette catégorie c correspond un niveau de confort et un prix par jour. Il est dusage quun véhicule loué soit ramené au lieu où a été pris le véhicule. Toutefois il existe un autre type de location de voiture : les locations où le véhicule est rendu dans un lieu différent du lieu de départ. Dans ce cas le prix est fixé non seulement en fonction du nombre de jours et de la catégorie du véhicule mais aussi en fonction de la distance entre les points de départ et darrivée.
Un séjour hôtelier peut être effectué dans un « bed & breakfast », hôtel, club,
Selon le type « dhôtel » et les accords avec lagence de voyage la règle pour calculer le prix du séjour hôtelier varie (à la nuit, forfait,
).
Un autoTour est une location de voiture sans remise de véhicule dans un lieu darrivée distinct combinée à un séjour à lhôtel. Le nombre de jours est déjà fixé. Le prix du séjour à lhôtel est fixé par un prix forfaitaire.
Dans chaque classe, vous définirez le(s) constructeur(s) ainsi quune méthode pour obtenir le prix du service (location, séjour, autotour).
Ce quil faut retenir
Méthodes et données héritées,
Spécification partielle ou totale de classes : classes abstraites et interface. Combinaisons héritage et implémentation dinterface.
Vos notes
TP n° 7 : Vecteurs et listes
Lobjectif de ce TP est de manipuler des structures de données de type liste. Ces structures de données sont des structures avancées. Elles permettent de stocker des séquences dobjet. Ces objets ne nécessitent pas dêtre de même nature :
listeObjets = (client1, fournisseur2, produit12)
Un vecteur est une liste. Tout comme pour un tableau, les éléments sont ordonnés et indexés. Les similitudes sarretent là. Un vecteur na pas de taille prédéfinie. Elle peut donc évoluer contrairement à celle dun tableau et permettre ainsi de gérer des ensembles dobjets dont le nombre nest pas préalablement fixé.
Un vecteur ne peut contenir que des objets, les types primitifs ne sont pas admis . Puisque toutes les classes dérivent de la classe Object, tout type dobjet peut être stocké dans le vecteur.
Le premier élément dun vecteur est en position 0. La classe des vecteurs est dans le paquetage
java.util.*
Description dun vecteur
Création dun vecteur
Vector()
Vector(int taille) : n contient une taille initiale.
Lorsque le vecteur est rempli, celui-ci est automatiquement augmenté.
Quelques méthodes
Nom méthodeRôleObject firstElement()Obtenir le premier élément du vecteurObject lastElement()Obtenir le dernier élément de la liste.Object elementAt(int i)Obtenir lélément rangé à la ième place.boolean contains(Object o)Vérifier que lobjet o en dans le vecteur.int indexOf(Object o)Rechercher la première occurrence de lobjet o dans le vecteur et retourner sa position.int lastIndexOf(Object o)Rechercher la dernière occurrence de lobjet o dans le vecteur et retourner sa position.void addElement(Object o)Ajouter un objet o à la fin du vecteur.void insertElementAt(Object o, int i)Insérer lobjet o dans le vecteur à la place i. Tous les éléments suivants ont leur position incrementée dun.Void setElementAt(Object o, int i)Lélément de la ième place est assignée à la valeur o.void removeElementAt(int i)Retirer lobjet assigné à la place i du vecteur.boolean removeElement(Object o)Retirer la première occurrence de lobjet o du vecteur. La méthode renvoie true si lopération a été effectuée.void removeAllElements()Retirer tous les éléments du vecteur.int size()La méthode retourne le nombre déléments dans le vecteur.boolean isEmpty()Vrai si le vecteur est vide
Concordance de types et transtypage
Les objets stockés peuvent être de nimporte quelle classe. Toutefois, le seul type renvoyé par les méthodes de la classe vecteur sont des objets. Il faut donc connaître la classe « réelle » de lobjet pour que celui soit correctement utilisé. Ceci est effectuer en « transtypant » lobjet.
Exemple :
String chaine, chaineBis ;
Vector v ;
Object o ;
V = new Vector() ;
chaine = "bonjour" ;
v.addElement(chaine) ; // ajout dun objet String
o = v.elementAt(0) ; // o est un objet
chaineBis = (String)v.elementAt(0) ; // lobjet est converti en String
Notons que linstruction
chaineBis = v.elementAt(0) ;
produit une erreur car chaineBis est de la classe String alors que lélément renvoyé est de type Object.
Exercice
Il sagit de représenter un système daide pour des déplacements en transport en commun afin de se rendre dans des lieux publics. Les principaux objets sont :
les lignes de bus : elles sont représentées sous la forme dune liste darrêts. Lensemble des lignes, représentable aussi sous la forme dune liste, forme le réseau.
Un ensemble de lieux publics. Un lieu public est décrit par son nom (mairie, piscine municipale,
) et par larrêt dautobus le plus proche.
Il vous est demandé dimplémenter des classes représentant ces différents concepts. Vous nhésiterez pas à définir les classes de type listes avec des liens dhéritage avec la classe des vecteurs. Vous prendrez soin de redéfinir les méthodes dinsertion et daccès aux éléments pour éviter les conversions de type. La méthode dajout de lieux publics devra conserver un ordre alphabétique sur les noms de lieux. Votre application doit permettre de compléter des lignes de bus (ajouter un arrêt entre deux arrêts).
Votre application doit permettre dindiquer, pour un lieu public, la ligne le desservant. Elle doit permettre de connaître le départ et terminus dune ligne.
Ce quil faut retenir
La représentation des données avec des listes, structures de données de haut niveau ,
Transtypage.
Vos notes
TP n°8 : Larchitecture modèle Vue Contrôleur
L'architecture modèle Vue Contrôleur est un moyen de séparer le cur d'une application avec sa représentation. Il s'agit d'une extension des concepts qui nous ont conduits à séparer la gestion des données dans un ensemble dobjets modèle d'une part, et le comportement de l'interface utilisateur dans un ou plusieurs objets vue d'autre part.
L'architecture modèle Vue Contrôleur sépare encore davantage l'affichage des données en réduisant au minimum le couplage application / représentation. Ceci est effectué en diminuant le plus possible la dépendance par rapport aux types de données dans lobjet application.
Fonctionnement
Supposons que lapplication doive présenter un ensemble de données dans une liste. La technique usuelle est :
de transmettre les données à un composant liste de base,
dassocier un gestionnaire de contrôle (contrôleur) à la liste.
Nous devinons quil y a une forte dépendance des données vis-à-vis de la présentation. Pour éviter cet écueil, nous associons un élément intermédiaire : un « modèle » des données. Les différentes étapes sont maintenant :
construire un modèle de données,
dassocier ce modèle de données à la liste, cest-à-dire à la vue sur les données,
dassocier un contrôleur à la liste.
Pour chaque valeur que la liste doit afficher, elle interroge le modèle (1). Le modèle interroge alors lensemble de données sources (2), obtient les données (3) et les transmet à la liste (4). La liste affiche alors la valeur :
EMBED Word.Picture.8
Cette technique permet de pouvoir prendre en compte de manière beaucoup plus aisée les ensembles de valeurs dynamique. Elle permet de voir différemment les données : on ne transmet plus les données à la vue mais on définit un moyen daccès à celles-ci. Qui plus est maintenant le modèle est le seul élément à connaître la représentation interne des informations.
Cette architecture ne peut être mise en place quavec la bibliothèque Swing et ne sadresse, évidemment, quaux composants gérant des volumes de données qui peuvent être importants. Cest-à-dire :
Les listes, les tableaux, les « combos » et les composants textes
Les classes modèles sont des classes abstraites. Elles sont abstraites car elles nécessitent de définir les méthodes dialoguant avec lensemble de données.
Exemple : implémentation dun modèle pour une liste de données. Dans un premier temps, nous définissons une classe représentant un modèle de données. Cette classe hérite de la classe abstraite des modèles de données pour les listes. Seules deux méthodes nécessitent dêtre implantées : la méthode déterminant le nombre déléments dans la liste et la méthode permettant dobtenir le ième élément à afficher dans la liste.
Supposons que nous décrivions un modèle de la liste des voitures. Le modèle du parking reçoit le parking en paramètre et accède ensuite au parking.
class MyListModel extends AbstractListModel {
private Parking leParking ;
public MyListModel(Parking p) {
leParking = p ;
}
public int getSize() {
return leParking.getNbPlaces() ;
}
public Object getElementAt(int index) {
return leParking.obtenirVoiture(index);
}
}
Dans second temps, nous créons un modèle et nous appliquons le modèle à la liste. Le modèle est appliqué en le transmettant en paramêtre de construction de la liste :
MyListModel monModele ;
Jlist monComposantListe ;
monModele= new MyListModel(unParking) ;
monComposantListe = new JList(monModele) ;
Présenter des données dans des tables
Le composant Swing JTable permette dafficher un tableau de données. Ce tableau peut être soit simplement affiché, mais peut aussi être modifié. Le modèle joue donc un double rôle : Il donne un moyen pour accéder aux données pour les présenter mais il sassure aussi, lorsquil y a modification des données dans la vue, de la synchronisation entre la source de données et sa présentation.
La représentation de données non homogènes est tout à fait possible : une première colonne présente des données textuelles, la seconde une valeur numérique, etc
Afin de pouvoir définir des tables et des modèles associés, il faut importer le paquetage :
javax.swing.table.*
Les items présentés dans la table sont référencés par deux valeurs : ligne et colonne. Ces valeurs sont des valeurs entières. La première méthode à définir est celle offrant laccès aux données :
getValueAt(int ligne, int colonne)
Exemple : Supposons que les données à présenter soient des couples (nomLogiciel, nomEditeur( et que ceux-ci soient stockés dans deux tableaux portant les noms nomLogiciel et nomEditeur. La méthode est la suivante :
Object getValueAt(int ligne, int colonne) {
if (ligne==0)
return nomLogiciel[ligne] ;
else
return nomEditeur[ligne] ;
}
Pour éviter les débordements, il faut donc indiquer à la vue le nombre de lignes et de colonnes. Pour ceci, il faut implanter deux nouvelles méthodes : getRownCount() et getColumnCount(). Si nous poursuivons notre exemple, nous obtenons :
int getRowCount() {
return Array.getLength(nomLogiciel) ;
}
int getColumnCount() {
return 2 ;
}
Pour parfaire laffichage, il faut définir lentête des colonnes du tableau. La méthode est getColumnName(int noColonne). Lentête est représenté à laide dun composant intermédiaire appelé JtableHeader.
Dans notre exemple, nous obtenons :
String getColumnName (int noColonne) {
if (noColonne ==0)
return "Nom du Logiciel" ;
else
return "Editeur" ;
}
Lensemble des méthodes définies dans le modèle permettent de contrôler son affichage. Le dernier point consiste à définir si la table peut être éditer ou non. Le contrôle des mises à jour est autorisé avec la méthode isCellEditable(int ligne, int colonne). Cette méthode renvoie une valeur booléenne indiquant si la modification est autorisée. Dans notre exemple, si nous supposons que le nom de léditeur est modifiable mais pas le nom du produit, nous obtenons :
boolean isCellEditable(int ligne, int noColonne) {
if (noColonne ==0)
return false ;
else
return true ;
}
Le dernier point consiste à synchroniser la mise à jour faite dans la table avec les données. Ceci est effectué avec la méthode setValueAt(Object nouvelleValeur, int ligne, int colonne). Lobjet transmis contient la nouvelle valeur à répercuter dans les données. Dans notre exemple nous devons prendre en compte les modifications des noms des éditeurs
void setValueAt(Object nouvelleValeur, int ligne, int colonne) {
nomEditeur[ligne] = (String)nouvelleValeur ;
}
Notre modèle est maintenant complet. Pour laffichage de la liste, il est dusage dutiliser un panneau permettant les défilements verticaux et horizontaux (barres de défilement). Les panneaux de ce type sont appelés des JScrollPane. Le panneau sassure de la synchronisation entre le défilement demandé par lutilisateur et le rafraîchissement des informations affichées. Dans notre exemple, nous obtenons :
JScrollPane panneauTable ;
JTable maTable ;
monModele = new maClasseModele() ;
maTable = new JTable(monModele) ;
panneauTable = new JScrollPane(maTable) ;
maFenetre.getContentPane().add(panneauTable,BorderLayout.CENTER) ;
Description des composants Listes et Tables
Les Listes
Cette section complète la description des composants JList décrits dans le chapitre 5.
Constructeurs
JList(ListModel modele) : les données qui doivent être présentées à lutilisateur sont transmises avec un modèle modele.
Quelques méthodes
Nom méthodeRôlevoid setModel(ListModel modele)Modifier le modèle de données de la liste.ListModel getModel()Obtenir lobjet modèle de données utilisé par la liste.
Les modèles de données « Liste »
Les modèles de données pour les listes se décomposent en deux classes : linterface ListModel et la classe abstraite AbstractListModel qui implémente une partie de linterface ListModel.
Linterface ListModel
Cette interface spécifie principalement les méthodes suivantes :
Nom méthodeRôleObject getElementAt(int i)Obtenir lélément i du modèle de données.int getSize()Retourner le nombre déléments dans la liste.
La classe abstraite AbstractListModel et la classe DefaultListModel
La classe AbstractListModel est la classe de base pour la définition des modèles de données listes. Elle offre des services de bas niveaux. La classe DefaultListModel est une implémentation « générique » dun modèle de données liste. Elle permet davoir une représentation de la liste en tant que pseudo-vecteur.
Constructeurs
DefaultListModel() : construit un modèle de liste « générique ».
Quelques méthodes
Nom méthodeRôleObject firstElement()Obtenir le premier élément de la liste.Object lastElement()Obtenir le dernier élément de la liste.Object elementAt(int i)Obtenir lélément rangé à la ième place.boolean contains(Object o)Vérifier que lobjet o en dans la liste.int indexOf(Object o)Rechercher la première occurrence de lobjet o dans la liste et retourner sa position.int lastIndexOf(Object o)Rechercher la dernière occurrence de lobjet o dans la liste et retourner sa position.void addElement(Object o)Ajouter un objet o à la fin de la liste.void insertElementAt(Object o, int i)Insérer lobjet o dans la liste à la place i. Tous les éléments suivants ont leur position incrementée dun.void setElementAt(Object o, int i)Lélément de la ième place est assignée à la valeur o.void removeElementAt(int i)Retirer lobjet assigné à la place i de la liste.Les Tables
Cette section présente la description du composant JTable. Nous ne décrivons pas les composants associés permettant la gestion de lentête (JTableHeader), de la présentation des cellules (TableCellRenderer), la présentation des colonnes (TableColumn).
Constructeurs
JTable() : construit une table par défaut. Celle-ci est créée avec un modèle de donnée par défaut, un modèle de colonnes par défaut et un modèle de sélection par défaut.
JTable(Object[][] lesDonnees, Object[] entetes) : construit une table dont les données sont stockées dans la matrice lesDonnees et les entêtes de colonnes sont décrits dans le tableau entetes.
JTable(Vector lesDonnees, Vector entetes) : construit une table dont les données sont stockées dans la vecteur de vecteurs lesDonnees et les entêtes de colonnes sont décrits dans le vecteur entetes.
JTable(TableModel modeleDonnees) : construit une table dont les données sont décrites dans le modèle de données modeleDonnees.
Quelques méthodes
Nom méthodeRôlevoid clearSelection()Dé-sélectionner toutes les lignes et colonnes.boolean editCellAt(int i, int j)Permet de redéfinir léditeur de cellule. Renvoie faux si un problème a eu lieu a lédition.Class getColumnClass(int col)Retourner la classe de la colonne ayant la position col.String getColumnName(int col)Retourner le nom de la colonne ayant la position col.TableModel getModel()Obtenir le modèle de données de la table.int getRowCount()Nombre de lignes dans la table.int getSelectedRow()Retourner lindice de la première ligne sélectionnée.int getSelectedCount()Retourner le nombre de lignes sélectionnées.int[] getSelectedRows()Retourner les indices des lignes sélectionnées.boolean getShowHorizontalLines()Vrai si les lignes doivent être dessinées dans la vue.boolean getShowVerticalLines()Vrai si les colonnes doivent être dessinées dans la vue.Object getValueAt(int i, int j)Retourner lélément en ligne i et colonne j.boolean isCellEditable(int i, int j)Vrai si la cellule peut être éditer.boolean isCellSelected(int i, int j)Vrai si la cellule est sélectionnée.void selectAll()Sélectionner toutes les cellules.void setModel(TableModel m)Assigner le modèle de données m à la table.void setValueAt(Object o, int i, int j)Lélément o devient la nouvelle valeur de la cellule en en ligne i et colonne j.
Les modèles de données « Table »
Les modèles de données pour les tableaux se décomposent en deux classes : linterface TableModel et la classe abstraite AbstractTableModel qui implémente une partie de linterface TableModel.
Linterface TableModel
Cette interface spécifie principalement les méthodes suivantes :
Nom méthodeRôleClass getColumnClass(int j)Obtenir la classe des éléments en colonne j.int getColumnCount()Retourner le nombre de colonnes.String getColumnName(int j)Obtenir le nom de la colonne j.int getRowCount()Obtenir le nombre de lignes.Object getValueAt(int i, int j)Obtenir lélément en ligne i et colonne j.boolean isCellEditable(int i, int j)Vrai si la cellule est modifiable.void setValueAt(Object o, int i, int j)La valeur de lobjet en cellule i, j est assignée à o.
La classe abstraite AbstractTableModel et la classe DefaultTableModel
La classe AbstractTableModel est la classe de base pour la définition des modèles de données pour les tableaux. Elle offre des services de bas niveaux pour la gestion des évènments dans la liste ; la classe implémente de manière basique les méthodes suivantes :
getColumnClass, getColumnName, isCellEditable (fixé à non), setValueAt.
La classe DefaultTableModel est une implémentation « générique » dun modèle de données de type tableau. Elle offre une représentation des données sous la forme de vecteurs de vecteurs et permet davoir un modèle de base offrant la plupart des services courants.
Constructeurs
DefaultTableModel() : construit un modèle de données « générique » sans lignes ni colonnes.
DefaultTableModel(int nbLignes, int nbCols) : construit un modèle de données de nbLignes et nbCols. Toutes les cellules sont initialisées à null.
DefaultTableModel (Object[][] lesDonnees, Object[] entetes) : construit un modèle de données dont les données sont stockées dans la matrice lesDonnees et les entêtes de colonnes sont décrits dans le tableau entetes.
DefaultTableModel (Vector lesDonnees, Vector entetes) : construit un modèle de données dont les données sont stockées dans la vecteur de vecteurs lesDonnees et les entêtes de colonnes sont décrits dans le vecteur entetes.
Quelques méthodes
Nom méthodeRôlevoid addColumn(Object nomCol, Vector donneesCol)Ajouter une colonne au modèle. Cette colonne a pour nom nomCol et les données sont spécifiées dans un vecteur donneesCol.void addRow(Vector laLigne)Ajouter une ligne au modèle. La ligne est ajoutée à la fin et est spécifiée avec un vecteur.int getColumnCount()Retourner le nombre de colonnes.String getColumnName(int j)Obtenir le nom de la colonne j.Vector getDataVector()Retourne un vecteur de vecteur contenant lensemble des données du modèle de données.int getRowCount()Obtenir le nombre de lignes.Object getValueAt(int i, int j)Obtenir lélément en ligne i et colonne j.void insertRow(int ligne Vector laLigne)Ajouter une ligne au modèle. La ligne est ajoutée à la ligne ligne et est décrite avec un vecteur.Boolean isCellEditable(int i, int j)Vrai si la cellule est modifiable (par défaut tout est à faux).void removeRow(int ligne)Supprimer la ligne ligne du modèle.void setColumnIdentifiers(Vector nomCols)Remplacer les identifiants des colonnes.void setDataVector(Vector nouvellesDonnees, Vector nomCols)Remplacer lensemble des données par les données indiquant dans le vecteur de vecteur. Les noms des colonnes sont aussi modifiés.void setValueAt(Object o, int i, int j)La valeur de lobjet en cellule i, j est assignée à o.
Exercice
Le but de cet exercice est de concevoir un ensemble de classes reproduisant larchitecture modèle, vue, contrôleur.
Lapplication doit permettre de représenter des données représentant des ventes automobiles dun garage :
MéganeSafraneTwingoJanvier8421Février2717Mars11518Total2116 =SUM(AUDESSUS) 56
Les données doivent être représentées de manière autonome. Vous prendrez soin de définir des classes permettant un extension aisée à la fois des mois et des modèles de voitures.
Vous devez définir un modèle de données pour afficher les données dans une table Swing. Les totaux sont des valeurs calculées et non prédéfinies.
Vous supposerez que les données ne sont pas modifiables.
A faire
Modifier le programme pour permettre la mise à jour des valeurs numériques de base. Les libellés ne sont pas modifiables. Les totaux ne sont pas modifiables et la modification dune valeur doit déclencher une mise à jour du total correspondant.
Limitez la modification en permettant la saisie de valeurs correctes uniquement (valeur entière positive ou nulle).
Ce quil faut retenir
Principe de fonctionnement de larchitecture : il sagit de définir un moyen daccès aux données devant être présentées.
Son application dans la manipulation de données tabulaires. Comment la vue interroge le modèle et comment le modèle interroge la source de données.
Le travail de synchronisation entre la source et la vue effectuée par le modèle lorsquil y a modification des données.
Vos Notes
TP n°9 : Hashtables
Une table de hachage est une structure de données permettant deffectuer des accès « rapides » à des informations. Le plus souvent, les données sont représentables sous la forme :
Clef ( valeurs
Ce principe est par exemple usuel dans la manipulation de tables en bases de données. Les objets stockés dans une table de hachage doivent donc pouvoir être identifiés. Les données sont stockées dans la table et sont transmis sous la forme de couple ObjetClef, objetValeur. La table de hachage utilise lobjet clef pour définir une clef de hachage. Cette clef permettra ensuite un accès direct aux informations car elle permet de localiser lobjet valeur dans la table.
La classe table de hachage est dans le paquetage :
java.util.*
La classe des tables de hachage sappelle Hashtable.
La table de hachage sappuie sur deux méthodes devant être définies dans la classe des objets clefs. La méthode hashCode et equals. La méthode hashCode est la méthode permettant de calculer la clef de hachage. Notons que la classe Object ou bien encore String ont cette méthode. La méthode equals est une méthode permettant de comparer deux objets :
egal = personne.equals(individu) ;
Cette méthode est implantée dans les classes Object, String ainsi que dans de nombreuses autres classes. Par défaut, deux objets distincts ne sont pas égaux. Il faut parfois redéfinir la méthode. Par exemple, deux objets livres sont identiques si leurs identifiants sont égaux.
Description de la classe HashTable
Cette section présente la description du composant Hashtable.
Constructeurs
Hashtable () : construit une table vide.
Quelques méthodes
Nom méthodeRôlevoid clear()Oter tous les éléments de la table.boolean containsKey(Object clef)Vrai si lobjet ayant comme clef clef est dans la table.boolean containsValue(Object valeur)Vrai si la table de hachage peut trouver au moins une clef associée à lobjet valeur.Enumeration elements()Ensemble des valeurs contenues dans la table retourné sous la forme dune énumération.Object get(Object clef)Renvoyer lobjet valeur associé à clef.boolean isEmpty()Vrai si la table est vide.Enumeration keys()Ensemble des clefs contenues dans la table retourné sous la forme dune énumération.void put(Object clef, Object valeur) Insérer lobjet valeur dans la table, lidentifiant de lobjet est clef.Object remove(Object clef)Retirer lobjet ayant pour identifiant clef de la table. La valeur renvoyé est la valeur associé à la clef.int size()Nombre de clefs dans la table.
Exemple :
Hashtable maTable ;
maTable = new Hashtable() ;
livre = new Roman(
) ;recueil = new Recueil(
) ;illustre = new BandeDessinee(
) ;
maTable.put(livre.getNoISBN(),livre) ;maTable.put(recueil.getNoISBN(),recueil) ;maTable.put(illustre.getNoISBN(),illustre) ;
Pour parcourir lensemble de la table de hachage, il faut tout dabord disposer de la liste des clefs pour ensuite accéder à tous les objets de la table. Laccès seffectue avec la méthode keys(). Cette méthode retourne une énumération (Enumeration).
Une énumération est une interface pour accéder aux éléments de manière séquentielle : elle propose deux méthodes
Une méthode pour accéder à un élément et passer au suivant (nextElement)
Une méthode pour vérifier quil y ait des éléments dans la liste (hasMoreElement)
Par exemple, pour parcourir la table de hachage
for (Enumeration e = maTable.keys() ;
e.hasMoreElements() ;) {
System.out.println((Ouvrage)maTable.get(e.nextElement()).getNomTitre()));
}
Description de linterface Enumeration
Cette section présente la description de linterface Enumeration. Cette interface permet daccéder à des séquences dobjets sans se préoccuper du format interne des données et de lensemble des données. On peut aussi bien demander une énumération à une table de hachage quà un vecteur par exemple. Elle permet de parcourir une séquence sans considérer la structure de la séquence.
Les méthodes
Nom méthodeRôleboolean hasMoreElements()Vrai sil y a encore des éléments dans lénumération.Object nextElement()Retourne lélément suivant.
Exercice
Il sagit de représenter une mini base documentaire cinématographique. Nous nous limitons à présenter un répertoire de réalisateurs et pour chacun des réalisateurs leur filmographie.
Exemple :
Réalisateur : Sergio Leone, Italien, parfois crédité sous le nom « Bob Roberson »
Filmographie :
Il était une fois dans louest (1969)
Pour une poignée de dollars (1965)
Il était une fois en Amérique (1984)
Pour un réalisateur, nous avons les informations suivantes :
Nom, prénom, nationalité, nom auxiliaire et prénom auxiliaire.
Nous supposerons quil ny a pas deux réalisateurs avec le même nom et prénom. Un second nom de crédit désigne le même réalisateur. Pour un film, les informations manipulées sont le titre du film et lannée de réalisation. Nous avons une structure de données semblable à :
Réalisateur ( Filmographie.
Construire une application permettant de stocker la base filmographique à laide dune table de hachage. Dans un premier temps, vous vous limiterez à définir une méthode pour insérer la filmographie dun réalisateur ainsi que sa fiche descriptive.
Vous étendrez ce travail en implantant une méthode permettant de complèter la filmographie dun metteur en scène : on « informe » la base que nous souhaitons ajouter la fiche suivante à notre base :
Nom, prénom, film, année (le nom et le prénom peuvent être auxiliaires).
A faire
Compléter le programme en ajoutant un interface graphique. Cette interface combine deux listes : une première liste où sont présentés les réalisateurs et une seconde liste asservie à la première et présentant la filmographie du réalisateur sélectionné. Vous implanterez cette interface en vous conformant à larchitecture modèle-vue-contrôleur.
Ce quil faut retenir
Laccès rapide aux données avec des tables de hachage.
Le structure abstraite Enumeration.
Vos Notes
TP n° 10 : Arbres, récursivité
Les arbres permettent de représenter des données structurées de manière hiérarchique. Lorganisation des documents en dossiers et sous-dossiers en est un bon exemple. Les données sont organisées selon une relation de parenté. La relation de parenté associe des nuds parents à des nuds fils. Un nud contient une donnée.
Chaque nud parent peut avoir un ou plusieurs fils, le nombre de fils nétant défini préalablement. Citons par exemple, un diagramme dhéritage entre classes. Une autre hypothèse consiste à fixer préalablement le nombre de fils. Si le nombre de fils est fixé à n, on parlera alors darbres n-aires. Citons par exemple, un arbre de décision.
Dans ce chapitre, nous nous focalisons uniquement sur les arbres binaires. Les arbres binaires sont des arbres ou chaque parent a au plus deux fils.
Lune des utilisations les plus usuelles des arbres en informatique concerne la représentation de données ordonnées. Lorsquon utilise un arbre binaire pour représenter des données triées, le nud parent représente une valeur médiane (relativement aux deux fils). Le fils gauche représente une valeur « plus petite » que le parent et le nud fils droit représente une valeur « plus grande » que le nud parent.
Plus généralement, les fils gauche et droit jouent eux-mêmes le rôle de parents et ont donc eux aussi des fils droit et gauche. On parlera alors de sous-arbre et sous-arbre gauche. Si nous revenons au problème de tri des données, nous avons toutes les valeurs du sous-arbre gauche inférieure à la valeur du nud parent et toutes les valeurs du sous-arbre droit sont des valeurs supérieures au nud parent.
Si, nous représentons la séquence de données suivante
Haddock, Tournesol, Tintin, Dupond, Milou, Dupont
dans un arbre binaire, nous obtenons (le choix de lélément central est arbitraire)
EMBED OrgPlusWOPX.4
Spécification dun arbre
Comme nous lavons évoqué précédemment, un arbre est composé
Un nud parent
Un sous-arbre gauche (éventuellement)
Un sous-arbre droit (éventuellement)
Les sous-arbres gauche et droit sont en fait des arbres. Autrement dit un arbre est une structure dont la définition fait appel à elle-même. Cest une structure de données récursives. Intuitivement nous obtenons :
class Arbre {
private ClasseDonnee donnee ;
private Arbre sousArbreGauche ;
private Arbre sousArbreDroit ;
}
Sur cette donnée, nous allons définir des méthodes :
Des méthodes pour insérer des éléments dans larbre.
Des méthodes pour accéder aux nuds de larbre.
Quand nous créons un arbre, nous créons tout dabord un le nud parent puis ensuite les nuds droit ou gauche si besoin. Nous en déduisons le constructeur : il initialise la donnée et prépare les nuds fils.
public Arbre(ClasseDonnee d) {
donnee = d ;sousArbreGauche = null ;sousArbreDroit = null ;
}
Sachant créer un arbre nous pouvons maintenant détailler les méthodes. Comme nous lavons préciser, nous devons définir une méthode, ou plusieurs, méthode(s) pour insérer un éléments dans larbre. Cette élément va être inséré à gauche ou à droite. Pour insérer un élément à gauche, il faut tout dabord vérifier que celui est vide pour ensuite créer un sous-arbre. Le raisonnement est identique pour le sous-arbre droit. Autrement dit, nous avons quatre méthodes à notre disposition :
abstract boolean insererDonnee(ClasseDonnee donnee) ;
abstract boolean estVideSousArbreGauche() ;
abstract boolean estVideSousArbreDroit() ;
abstract void creerSousArbreGauche(ClasseDonnee donnee) ;
abstract void creerSousArbreDroit(ClasseDonnee donnee) ;
Supposons maintenant que sous-arbre gauche et le sous-arbre droit soient définis. Dans ce cas, nous devons essayer dinsérer de créer un sous-sous-arbre, cest-à-dire créer un sous-arbre dans le sous-arbre gauche ou créer un sous-arbre dans le sous-arbre droit. Autrement dit, la méthode pour insérer les données suit la trame suivante :
SI estVideSousArbreGauche() = vrai
CreerSousArbreGauche(donnee)
SINON
SI estVideSousArbreDroit() = vrai
CreerSousArbreDroit(donnee)
SINON
sousArbreGauche.insererDonnee(donnee) ou
sousArbreDroit.insererDonnee(donnee)
FIN SI
FIN SI
Dans la troisième éventualité, il faut choisir où va se faire linsertion. Le choix représente la politique de construction de larbre.
Dans le contexte où larbre doit être ordonné, nous obtenons comme algorithme :
SI donnee < this.donnee
SI estVideSousArbreGauche() = vrai
CreerSousArbreGauche(donnee)
SINON
sousArbreGauche.insererDonnee(donnee)
FIN SI
FIN SI
SI donnee > this.donnee
SI estVideSousArbreDroit() = vrai
CreerSousArbreDroit(donnee)
SINON
sousArbreDroit.insererDonnee(donnee)
FIN SI
FIN SI
Exercice
Créer un mini-répertoire contenant une liste de personnes. Chaque personne a un nom et un prénom. Le répertoire est représenté sous une forme arborescente. Larbre permettra ainsi de conserver un ordre permanent et dobtenir un accès rapide aux informations.
Vous définirez une méthode permettant de savoir si un élément est présent dans larbre.
Vous définirez une méthode pour parcourir tous les éléments de larbre (ceci permettra une vérification aisée de la bonne exécution de linsertion des éléments dans larbre).
A faire
Compléter le programme en ajoutant une méthode pour ôter un élément de larbre.
Compléter le programme en y ajoutant une interface graphique. Vous pouvez utiliser à cet effet le composant Swing JTree. Ce composant permet de représenter visuellement des arbres (exemple : arborescence de documents). Larchitecture modèle-vue-contrôleur sappliquant à ce composant, il est conseillé de créer un modèle (classes TreeModel et DefaultTreeModel).
Couplage dun vecteur et dun arbre : les données sont stockées dans le vecteur (sans tri particulier) et larbre contient uniquement les clefs et index des éléments du vecteur. Comment coupler ces deux ensembles de données ?
Ce quil faut retenir
La structure récursive des arbres.
Le couplage entre des structures de données évoluées et sa visualisation (cf. à faire).
Vos Notes
Quelques Références
Le site de référence de Sun :
HYPERLINK http://java.sun.com/docs/books/tutorial/ http://java.sun.com/docs/books/tutorial/
Un cours en français :
HYPERLINK http://www.inf.enst.fr/~charon/coursJava/index.html http://www.inf.enst.fr/~charon/coursJava/index.html
et un autre :
HYPERLINK http://www.eteks.com/ http://www.eteks.com/
un ouvrage en ligne assez complet (plus de 1000 pages et en anglais) :
HYPERLINK "http://www.mindview.net/Books/TIJ/" http://www.mindview.net/Books/TIJ/
un site de référence en anglais contenant de nombreux programmes et renseignements (en anglais) :
HYPERLINK "http://www.gamelan.com/"http://www.gamelan.com/
La notion de paquetage fera lobjet dune section plus détaillée dans un chapitre ultérieur.
Les sous-classes et les notions dhéritage seront aussi détaillées dans un chapitre ultérieur.
Cf. ci-après.
Excepté si le type est « emballé » dans un objet correspond à sa classe : classe Integer, Float, Boolean,
Les vecteurs et tableaux sont des structures à accès séquentiels.
PAGE 1
( Page PAGE 17
( Page PAGE 1
PAGE 1
( Page PAGE 63
( Page PAGE 64
EMBED Word.Picture.8
Client Dupond
Toulouse
01.01.01.01.01
liste des commandes
Commande 2
Ligne 1
Ligne 2
Commande 1
Ligne 1
Ligne 2
Article 1
Quantité (20)
Article 2
Quantité (4)
Les composants du projet (classes et documentation)
La description du projet
0..*
Option de fermeture de la console
Valeur affichée par le programme
1..*
1..1
Nom de la classe fenêtre
Nom de la classe Programme
Informations complémentaires
Titre de la classe fenêtre
Léditeur de propriétés
La fenêtre WinParking à définir
Panneau dentête (GridLayout)
Panneau total (FlowLayout)
Panneau détail contenant deux panneaux
Choix de lévénement
Onglet proposant les événements possibles
Voitures
VoituresCarburant
VoituresElectriques
Diesel
SansPlomb
1..*
1..1
EMBED Word.Picture.8
EMBED Word.Picture.8
1..*
0..*
1..*
noCde : String
Commande
telephone : String
ville : String
nom : String
Client
Article
qte : Integer
LigneCommande