VII. Chapitre 8▲
VII-A. Application commande de vélos▲
On dispose déjà des classes EcranCommande et TropDeVelosException. Utilisez la fonction rechercher/remplacer de l'éditeur, pour "retirer" tous les accents dans les deux classes.
La classe EcranCommande doit être complétée :
- pour y déclarer les composants (variables de classe) et les construire (dans le constructeur) ;
- pour vérifier, dans la méthode actionPerformed(), que la quantité commandée ne dépasse pas la quantité disponible.
VII-A-1. Nouvelle version de TropDeVelosException▲
Mais avant cela, il faut d'abord remarquer que l'on a besoin d'un constructeur prenant un paramètre de type String, dans la classe TropDeVelosException. Pourquoi ? À cause de la ligne suivante de la classe EcranCommande (cherchez dans la méthode verifierCommande()) :
throw
new
TropDeVelosException (
"Impossible de livrer "
+
quantite +
" velos du modele "
+
modeleVelo +
" en une fois."
);
On remarque que:
- c'est un appel au constructeur de la classe TropDeVelosException. En effet, on utilise le mot-clé new ;
- le paramètre passé est une chaine de caractères (obtenue par une concaténation : pour rappel, une chaine construite avec un mélange de chaines et de types primitifs. Et ce grâce à l'opérateur "+"). Or ce constructeur n'existe pas encore dans la classe TropDeVelosException.
De plus, la classe mère Exception de TropDeVelosException dispose d'un constructeur acceptant un String.
Voici donc une nouvelle version de la classe TropDeVelosException :
VII-A-2. Correction d'une légère anomalie dans le code original de EcranCommande▲
Dans la classe EcranCommande, méthode actionPerformed(), cette ligne comporte encore deux légères erreurs :
commandeVelos.verifierCommande
(
modeleChoisi, quantiteChoisie);
En effet :
=> la méthode verfierCommande est déjà présente dans la classe EcranCommande. Aussi on n'a pas besoin d'appeler :
commandeVelos.verifierCommande
(
modeleChoisi, quantiteChoisie);
mais on peut tout simplement se contenter de :
verifierCommande
(
modeleChoisi, quantiteChoisie);
=> le deuxième paramètre de la méthode verifierCommande devant être un int, ce n'est pas la valeur de quantiteChoisie (String) qui doit être passée, mais le paramètre quantite (int).
On corrige donc par la simple ligne :
verifierCommande
(
modeleChoisi, quantite);
VII-A-3. EcranCommande sera une fenêtre Swing▲
Il nous est demandé de réaliser une application Swing. On peut faire hériter la classe EcranCommande de javax.swing.JFrame et procéder à quelques réglages (modification du constructeur sans arguments) :
N'oubliez pas que la définition des interfaces implémentées vient après la définition de l'éventuelle classe mère. Donc, lorsque l'on déclare une classe, on précise toujours d'abord la classe mère (par le mot-clé extends) avant les interfaces implémentées (par le mot-clé implements).
VII-A-4. Déclaration et construction des composants de la classe EcranCommande▲
On devine aisément, d'après le code EcranCommande, quels sont les composants à déclarer :
- un JTextField nommé champTexteModele et donc également un JLabel identifiant le champ ;
- un JTextField nommé champTexteQuantite et donc un JLabel l'identifiant ;
- un JTextField nommé champTexteConfirmationCommande et donc un JLabel l'identifiant.
Mais il faudra également créer un bouton permettant à l'utilisateur de soumettre sa commande.
On ajoutera l'ensemble de ces composants à un JPanel, qui sera intégré à la fenêtre. Pour agencer les composants, j'ai choisi un GridLayout de quatre lignes par deux colonnes ; avec un espacement de cinq pixels entre les composants (en largeur : troisième paramètre du constructeur et en hauteur : quatrième paramètre du constructeur).
Enfin, il faut donner au bouton son écouteur d'évènements : on peut lui attribuer l'instance courante de EcranCommande, à savoir this. La classe EcranCommande implémente déjà l'interface ActionListener et sa méthode ActionPerformed est déjà prévue pour exécuter le code de validation/annulation de commande.
VII-A-5. Vérification de la commande et la nouvelle classe ModeleVelo▲
La méthode verifierCommande est incomplète : elle se contente de renvoyer une exception TropDeVelosException, sans même vérifier si la commande est valable.
À chaque commande, il faut vérifier :
- si le modèle existe ;
- si la quantité commandée pour ce modèle n'excède pas la quantité maximale autorisée.
Pour procéder, on peut créer une classe ModeleVelo. Elle servira à nous renseigner à la fois sur le nom et la quantité maximale d'un modèle :
public
class
ModeleVelo {
String model;
int
quantiteMaximumCommandable;
public
ModeleVelo
(
String model, int
quantiteMaximumCommandable) {
this
.model =
model;
this
.quantiteMaximumCommandable =
quantiteMaximumCommandable;
}
}
On crée alors un tableau de type ModeleVelo (eh oui, vous en avez le droit car maintenant ModeleVelo est un type reconnu pour votre programme.) dans la classe EcranCommande :
ModeleVelo modelesDisponibles[] =
{
new
ModeleVelo
(
"BikeMike 500"
, 5
),
new
ModeleVelo
(
"RideAMax 130"
, 2
),
new
ModeleVelo
(
"BigRace 200"
, 8
),
new
ModeleVelo
(
"TrickyCourt 820"
, 7
),
new
ModeleVelo
(
"MaxiRide 20"
, 3
),
new
ModeleVelo
(
"RidersHeaven 760"
, 9
),
}
;
Cette construction vous semble bizarre ? Pourtant elle est correcte : souvenez-vous que vous n'êtes pas obligés de conserver une référence sur l'objet créé avec new. Ici le tableau, dont on a conservé une référence, s'en chargera pour nous.
Pour tester si un modèle fait partie de la liste, il suffira donc d'exécuter une boucle for (ou for each) sur tout le tableau :
String modeleRecherche =
"BikeMike 500"
;
for
(
ModeleVelo modeleCourant : modelesDisponibles){
if
(
modeleRecherche.equals
(
modeleCourant.modele)){
/*
* Faire ce que l'on veut faire avec modeleCourant :
* c'est l'objet ModeleVelo correspondant au nom
* de modele recherche.
*/
}
}
Enfin, il ne faut pas oublier d'ajouter une méthode main(). On y créera une instance d'EcranCommande et on l'affichera.
VII-A-6. Code complet de la classe EcranCommande▲
Voici un aperçu de la nouvelle interface :
Si le modèle de vélo entré n'est pas reconnu, le champ "Commande confirmée ?" indique "Le modèle de vélo n'existe pas.".
Si le modèle de vélo entré est reconnu et la quantité commandée acceptable, l'interface renvoie le message : "Votre commande est prête.".
Toutefois, si la commande excède la limite autorisée pour le modèle, un message d'erreur sera affiché. Un message du genre : " Impossible de livrer six vélos du modèle BikeMike 500 en une seule commande. ".
VII-B. Exercices pour les petits malins : liste déroulante▲
VII-B-1. Construire l'objet JComboBox▲
Il y a plusieurs manières pour initialiser et remplir un JComboBox. On peut utiliser le constructeur par défaut et ensuite, remplir la liste en ajoutant les éléments un par un.
Mais il y a un moyen de réutiliser, presque directement, le tableau de ModeleVelo que nous avons employé précédemment. Pour cela j'utilise le constructeur :
JComboBox
(
ComboBoxModel aModel)
Ce constructeur va nous permettre de lui passer un DefaultComboBoxModel. Cette dernière classe nous permet simplement d'initialiser la liste avec un tableau d'Object (c'est-à-dire avec toute classe existante, car toute classe hérite de Object). Voici son constructeur :
DefaultComboBoxModel
(
Object[] items)
Pour créer et initialiser notre liste en même temps, il nous suffira donc d'écrire :
new
JComboBox
(
new
DefaultComboBoxModel
(
modelesDisponibles));
VII-B-2. La méthode toString() de tout objet et nouvelle version de la classe ModeleVelo▲
Toute classe hérite de la classe Object. Et la classe Object définit un certain nombre de méthodes, qui peuvent donc être surchargées (souvenez-vous de la méthode dire() créée dans la classe Poisson du chapitre 3 : elle surcharge celle de la classe AnimalFamilier).
Parmi elles, la méthode toString(), destinée à donner une description de l'objet en question. Si pour certaines classes cette méthode donne une indication précise sur la valeur de l'objet (et éventuellement sa classe), cela ne sera pas le cas pour la majorité. Au contraire, on obtiendra quelque chose contenant beaucoup de caractères étranges.
Et quand le JComboBox stocke des objets (et non de simples types primitifs), il se base sur le texte renvoyé par la méthode toString() de ces objets. C'est pourquoi vous obtiendrez un texte bizarre en lieu et place des différentes possibilités de la liste, si vous lancez l'application.
Néanmoins, on a la possibilité, si on le désire, de remplacer cette description rébarbative, par une chaine beaucoup plus élégante. Pour cela, il suffit de surcharger la méthode toString().
Vous l'aurez certainement compris, nous allons surcharger la méthode toString() de la classe ModeleVelo afin qu'elle renvoie le modèle du vélo.
public
class
NouveauModeleVelo {
String modele;
int
quantiteMaximumCommandable;
public
NouveauModeleVelo
(
String modele, int
quantiteMaximumCommandable) {
this
.modele =
modele;
this
.quantiteMaximumCommandable =
quantiteMaximumCommandable;
}
public
String toString
(
){
return
modele;
}
}
C'est aussi simple que cela.
Maintenant il faut savoir comment réagir quand l'utilisateur change l'élément sélectionné dans la liste.
VII-B-3. L'interface ItemListener et la nouvelle version de EcranCommande▲
L'interface ItemListener est l'interface à utiliser pour tout objet devant être informé quand la sélection d'un JComboBox est modifiée. Elle ne comporte qu'une méthode de signature :
void
itemStateChanged
(
ItemEvent e)
On obtient alors un objet ItemEvent, qui nous renseigne sur différents aspects de l'évènement. Notamment sur l'objet qui a été sélectionné. Pour cela on fera appel à la méthode getItem() de la classe ItemEvent :
Object getItem
(
)
On obtient une instance de Object, un cast sera donc nécessaire.
On peut donc :
- créer une variable de classe qui servira à renseigner sur le dernier modèle sélectionné : modeleCourant. On l'initialisera avec le modèle qui sera affiché au lancement de l'application : c'est-à-dire le 1er modèle de la liste ;
- mettre à jour cette variable dans l'écouteur de type ItemListener ;
- définir la classe EcranCommande elle-même comme écouteur de type ItemListener.
Évidemment, il y a encore de petits ajustements à faire dans EcranCommande :
- dans la méthode actionPerformed(), la variable modeleChoisi ne sert plus ;
- on n'a plus besoin de la version verifierCommande() à deux paramètres : mais on peut la surcharger avec une version ne prenant que la quantité demandée.
Ce qui nous donne donc :
Voici un aperçu de la nouvelle interface (le comportement reste le même).
VII-C. Synthèse▲
Les exercices de ce chapitre vous ont permis :
- de construire votre propre exception, en héritant de la classe Exception ;
- de créer un tableau contenant vos propres objets ;
- de construire une liste déroulante, la remplir et réagir quand l'utilisateur en change l'élément choisit ;
- de profiter du potentiel offert par la méthode toString(), en la redéfinissant.