TP5 Java

Transcription

TP5 Java
-1-
Programmation Objet et langage Java
TP5 : AFFICHEUR DEFILANT
PRESENTATION DU THEME
Dans de nombreuses circonstances, à l'usine comme dans les lieux publics
il est utile d'afficher une information visible de loin. Suivant l'importance et
les enjeux, l'affichage va utiliser du matériel plus ou moins sophistiqué.
Dans ce TP, notre objectif est de simuler en java un afficheur
simple (sans LED) ainsi son l'IHM de commande
mise à la disposition du responsable.
Journal Défilant
Choisir
l’information à
diffuser
Notre diagramme des cas d'utilisation simplifié sera donc :
Information à
diffuser
Démarrer/Arrêter
le défilement
Afficheur défilant
Responsable
Régler la vitesse
de défilement
PRINCIPE DE FONCTIONNEMENT DE L’AFFICHEUR
L’afficheur défilant se compose d’une fenêtre de
type boite de dialogue contenant l’affichage (classe
Afficheur) et d’une interface de pilotage
composé d’une fenêtre héritant de la classe Frame
(classe PiloteAfficheur). La classe principale
est JournalDefilant. Cette classe lance
l’application.
L’interface de pilotage permet de :
 spécifier le fichier contenant le texte à afficher,
 démarrer ou arrêter le défilement de
l’affichage,
 régler la vitesse de défilement à l’aide d’une barre de défilement,
 fermer l’application à l’aide du bouton
.
Une fois le fichier contenant le texte à afficher spécifié, le texte affiché est rechargé depuis ce fichier à chaque nouveau
départ de défilement pour permettre une mise à jour du texte de façon dynamique.
TEXTE A AFFICHER
Le texte à afficher est situé dans la première ligne d’un fichier d’extension .txt.
Exemple : Supposons que la première ligne du fichier contient le célèbre vers de Verlaine :
Les sanglots longs des violons...bercent mon cœur d’une langueur monotone.
La taille de la zone d’affichage étant généralement inférieure à la taille du texte à afficher, l’afficheur fera défiler le texte
à la façon d’un journal lumineux. Exemple l’afficheur affiche ici le texte en rouge :
Les sanglots longs des violons....monotone
1. L’affichage débute en faisant entrer le texte par la droite:
Les sanglots longs des violons de l’automne....monotone
2. La fin du défilement est obtenue lorsque la dernière lettre quitte l’affichage :
Les sanglots longs des violons de l’automne....monotone
Puis le processus redémarre en 1
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
-2-
Programmation Objet et langage Java
DIAGRAMME DES CLASSES
DE NIVEAU CONCEPTION
Pour faciliter la programmation objet, il est utile de concevoir la solution d'abord sous forme d'un diagramme des classes
mises en jeu. Les liens sémantiques entre les classes sont résumés sous forme d'un simple verbe car l'objectif de ce
diagramme est avant tout d'aider le programmeur à comprendre l'architecture du programme et de naviguer plus
facilement dans le code java résultant :
Le BufferedReader est
local à la méthode
readFile().
Frame
Le Programme principal
Journal
Défilant
PiloteAfficheur
Timer
modifie
période
est écouté par
Afficheur
commande
Affiche
min,max vitesse
3
Scrollbar
Dialog
Button
Trouve fichier
du message
Label
Lit la 1ère ligne du fichier
du message
FileDialog
est écouté par est écouté par
Affiche dans
2
BufferedReader
Extrait les octets
Anonyme1
Anonyme3
Anonyme2
FileReader
Lit les blocs de caractères
AdjustmentListener
ActionListener
File
Les écouteurs anonymes peuvent accéder aux variables de PiloteAfficheur donc à tous les
composants de celui-ci. Ces associations trop nombreuses ne sont pas représentées ici.
DIAGRAMME D'OBJETS
Pour préparer la phase de codage, il faut détailler le rôle des 3 boutons et des 2 étiquettes. Mais c'est surtout le rôle
primordial des 5 écouteurs qu'il est nécessaire d'expliciter à travers leurs liens sémantiques vers les différents objets de
l'application. Un objet est désigné sous la forme : "nom_objet : non_classe" ou " : nom_classe" si l'objet est anonyme
par exemple en java new XXX() ou bien le nom de l'objet n'est pas important.
On peut aussi écrire "nom_objet : " si le nom de sa classe n'a pas d'importance mais ce n'est pas le cas dans ce TP.
Comme les écouteurs sont des "objets anonymes" appartenant à des "classes anonymes dérivées de XXXListener",
nous utilisons abusivement une forme pratique pour l'être humain : anonymeNN : XxxListener
afficheur:Afficheur
Le BufferedReader est local à la méthode readFile().
Le Programme principal
Affiche dans
: JournalDéfilant
: PiloteAfficheur
labelTextDefilant:Label
affiche min vitesse
scrollbarVitesse :
Scrollbar
est écouté
par
labelMin:Label
affiche max vitesse
timer : Timer
buttonStart:
Button
buttonStop:
Button
est écouté par
est écouté
par
obtient
valeur
modifie
période
Trouve fichier
du message
buttonFichier:
Button
labelMax:Label
lit la 1ère ligne du fichier
du message
est écouté par
fileDialog:FileDialog
démarre
est écouté par
anonyme1 :
AdjustmentListener
arrête
anonyme21 :
ActionListener
active
active
anonyme22 :
ActionListener
bfr:BufferedReader
lire le fichier
obtient
nom répertoire
+ nom fichier
rend visible
anonyme23 : ActionListener
anonyme3:
ActionListener
affiche le nom
du fichier
comme titre
Extrait les octets
:FileReader
Lit les blocs de caractères
:File
affiche le message décalé en fonction du temps
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
-3-
Programmation Objet et langage Java
DIAGRAMMES DE SEQUENCE CORRESPONDANT AUX CAS D'UTILISATION NOMINAUX.
Un cas d'utilisation est nominal quand aucune erreur habituelle ne survient (fichier inconnu, erreur lecteur fichier, erreur
dans la transmission électronique de l'information, etc).
Diagramme de séquence associé au CU « Choisir l’information à diffuser »
buttonFichier : Button
cliquer
anonyme23 :
ActionListener
actionPerformed()
fileDialog :FileDialog
rendre visible
obtient nom répertoire
obtient nom fichier
construit le nom
du fichier
Afficheur : Afficheur
affiche le nom du fichier dans la barre de titre
: PiloteAfficheur
lire le fichier
instancie un BufferReader bfr
pour lire le fichier
lit la 1ère ligne
ferme le BufferReader bfr
buttonStart : Button
activer
buttonStop : Button
activer
Diagramme de séquence associé au CU « Régler vitesse de défilement »
scrollbarVitesse : Scrollbar
change valeur
anonyme1 :
AdjustmentListener
timer : Timer
adjustmentValueChanged()
donne la valeur courante
change la période
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
-4-
Programmation Objet et langage Java
Diagramme de séquence associé au CU « Démarrer le défilement »
buttonStart : Button
anonyme21 :
ActionListener
timer : Timer
cliquer
actionPerformed()
démarrer
ref
Tic Horloge
Diagramme de séquence associé à l’événement « Tic Horloge »
timer : Timer
anonyme3 :
ActionListener
tic
actionPerformed()
extraire la sous-chaine visible du message
en fonction de la position courante
afficheur:Afficheur
Affiche la sous-chaine
Incremente « circulairement »
la position courante (modulo la « bonne taille »)
opt
[ position courante = 0 ]
: PiloteAfficheur
lire le fichier du message
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
-5-
Programmation Objet et langage Java
Diagramme de séquence associé au CU « Arrêter le défilement »
buttonStop : Button
anonyme22 :
ActionListener
timer : Timer
cliquer
actionPerformed()
arrêter
NOTES ET CONTRAINTES SUR L'AFFICHAGE DU TEXTE
Contrairement à un afficheur électronique dont les caractères peuvent être éteints, l’afficheur est ici constitué d’un label
devant obligatoirement contenir des caractères. On utilisera les caractères « _ » invisibles dans un label si sa hauteur est
ajustée de façon à cacher ce caractère. Le label sera initialisé avec les caractères « _ » ce qui correspond à un afficheur
éteint.
Nota : on ne peut pas utiliser le caractère space car il provoque un traitement particulier dans un label.
Pour faire débuter l’affichage avec la première lettre du texte et faire terminer l’affichage par la dernière lettre du texte, on
pré fixe et on post fixe le texte avec la chaine de caractères contenue dans le label de l’afficheur éteint.
REALISATION DU DEFILEMENT
DETERMINATION DE LA ZONE DE TEXTE A AFFICHER
Pour réaliser le défilement du texte dans la fenêtre, il faut extraire du texte la portion correspondant à celle qui apparaitra
sur le label.
Supposons que le label affiche la portion de texte suivante : « ts longs des violo »
lineLength
Les sanglots
ts longs des violo
violons de l’automne....monotone
pos
displayTextLength
pos+displayTextLength




lineLength() est la taille totale du texte pré fixée et post fixée avec les caractères « _ » contenu dans label de
l’afficheur éteint. Cette quantité est calculée après avoir lue la ligne à afficher.
pos est la position de départ du premier caractère affiché. Cette quantité est calculée à chaque défilement.
displayTextLength est la taille de la zone d’affichage. Cette quantité déterminée une fois pour toute dans le
constructeur du pilote.
pos + displayTextLength donne la position du dernier caractère à afficher.
La portion de texte à afficher (donc à écrire sur le label) est extrait de la ligne à afficher par :
Portion_de_Texte_à_afficher = line.substring(pos, pos + displayTextLength) ;
 En incrémentant pos, le texte défile sur l’afficheur.
Attention : pos doit rester dans l’intervalle [0..(line.length() – displayTextLength)[ ce qui peut être
réalisé à l’aide d’une opération modulo : pos = pos %
(line.length() – displayTextLength).
ANIMATION DU TEXTE
La mise à jour de la position du texte dans l’afficheur est réalisée dans l’écouteur d’un timer.
private Timer createTimer ()
{
ActionListener action = new ActionListener ()
{
// Position courante dans la chaine à afficher. Initialisé à 0
int pos = 0;
// Ecouteur du timer. Appelé par défaut toutes les MIN_TIME ms
public void actionPerformed (ActionEvent event)
{
// Mettre à jour l'afficheur avec la portion de texte à afficher
// Incrémenter la position courante (pos)
// S’assurer que pos est dans un intervalle valide
// Si pos == 0 alors relire le fichier contenant le texte à afficher
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
Programmation Objet et langage Java
-6-
}
};
return new Timer (MIN_TIME, action);
}
ATTRIBUTS DE LA CLASSE PILOTEAFFICHEUR
// Valeur maximale et minimale par défaut de la barre de défilement et barre de défilement
private final int MIN_TIME = 100;
private final int MAX_TIME = 500;
private Scrollbar scrollbarVitesse = null;
// Mettre à jour l'attribut nom avec votre nom
private String nom = "Corrigé";
// Boutons start et stop
private Button buttonStart = null;
private Button buttonStop = null;
// Bouton permettant de spécifier un fichier
private Button buttonFichier = null;
// Labels placés aux extrémités supérieures de la barre de défilement
private Label labelMin = null;
private Label labelMax = null;
// Ligne à affichée extraite du fichier
private String line = null;
// Contrôle FileDialog permettant de spécifier le fichier à lire
private FileDialog fileDialog = null;
// L'afficheur
private Afficheur afficheur = null;
// Le Timer
private Timer timer = null;
// Taille de l'afficheur
private int displayTextLength = 0;
// Texte présent dans l'afficheur éteint
private String lineBlank = null;
// Fichier à lire
private String file = null;
TRAVAIL DEMANDE
Nota : si à l’exécution de l’application l’erreur « nul pointer » s’affiche dans la console, c’est que vous n’avez pas
initialisé un attribut de type objet (généralement masqué cet attribut en le re-déclarant localement).



Créer un projet TP5.
Récupérer les fichiers java sur le site de cours (lien éléments fournis). Décompresser l’archive et ...
Ajouter les fichiers suivants au projet dans le répertoire src et mettre à jour le projet :
JournalDefilant.java
Afficheur.java
PiloteAfficheur.java
1. Compléter le constructeur
2. Compléter la méthode getScrollbarVitesse()
3. Compléter la méthode getButtonStart()
4. Compléter la méthode getButtonStop()
5. Compléter la méthode getButtonFichier()
6. Compléter la méthode readFile()
7. Compléter la méthode getScrollbarVitesse()
8. Compléter le « timer »
9. Compléter le fichier JournalDefilant.java
Tester le bon fonctionnement de votre application.
10. On veut afficher dans l'IHM du responsable, à chaque "tic Horloge", la valeur de la position courante.
Comme il n'y a pas d'objet disponible, nous afficherons la valeur décimale dans la zone titre de la fenêtre
du PiloteAfficheur grâce à la méthode "setTitle". Dans l'écouteur de Timer, il est possible d'accéder aux
méthodes de l'objet conteneur de 2 façons :
- soit directement "nom_fonction(param…);" quand il n'y a pas de conflit de nom entre les méthodes
de la classe "écouteur" (ici Timer) et celle de la classe "conteneur" (ici PiloteAfficheur).
- soit indirectement "Nom_Classe_Conteneur.this.nom_fonction(param…);" quand il y a conflit
de nom entre "nom_fonction " de la classe "écouteur" et celle de la classe "conteneur".
Afficher la valeur de la position courante en testant les 2 façons expliquées précédemment.
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
Programmation Objet et langage Java
-7-
11. Créer un fichier jar exécutable de l’application
12. Bonus : simplifier l’IHM en remplaçant les deux boutons start et stop par un seul bouton remplissant la
même fonction que les boutons prétendants. Créer un fichier jar exécutable de l’application.
NOTA : les écouteurs sont tous définis dans une classe anonyme. Leur squelette peut être généré par eclipse à
l’aide de WindowBuilder (mode design).
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
-8-
Programmation Objet et langage Java
ANNEXE : CODE FOURNI
/**
* Constructeur du pilote de l'afficheur
*/
public PiloteAfficheur()
{
super();
initialize();
// Instancier la classe Afficheur et mémoriser sa référence dans l'attribut afficheur
// Rendre visible l'objet afficheur
// Instancier l’attribut fileDialog de classe FileDialog :
// type LOAD et titrer ce contrôle avec "Fichier ?" (voir cours)
// Créér le Timer
timer = createTimer();
// Lire le texte contenu dans l'afficheur (label labelTextDefilant)
// et le mémoriser dans l'attribut lineBlank)
// Mémoriser la taille de l'afficheur (longueur de lineBlank ) dans l'attribut displayTextLength
}
/**
* This method initializes scrollbarVitesse
*
* @return java.awt.Scrollbar
*/
private Scrollbar getScrollbarVitesse()
{
if (scrollbarVitesse == null)
{
scrollbarVitesse = new Scrollbar();
scrollbarVitesse.setBounds(new Rectangle(14, 138, 238, 22));
// Initialiser la valeur minimale que peut retourner l’objet scrollbarVitesse avec MIN_TIME
// Initialiser la valeur minimale que peut retourner l’objet scrollbarVitesse avec MAX_TIME
// Définir l'orientation de la barre de défilement avec Scrollbar.HORIZONTAL
// Abonner et définir l’écouteur de la barre de défilement (utiliser WindowBuilder)
// Dans l’écouteur, règler le timer avec la valeur donnée par la position de la barre de défilement
}
return scrollbarVitesse;
}
/**
* This method initializes buttonStart
*
* @return java.awt.Button
*/
private Button getButtonStart()
{
if (buttonStart == null)
{
buttonStart = new Button();
buttonStart.setBounds(new Rectangle(14, 79, 105, 32));
// Désactiver le bouton
// Ecrire "Démarrer" sur la label du bouton
// Abonner et définir l’écouteur du bouton (utiliser WindowBuilder)
// Dans l’écouteur : démarrer le timer
}
return buttonStart;
}
/**
* This method initializes buttonStop
*
* @return java.awt.Button
*/
private Button getButtonStop()
{
if (buttonStop == null)
{
buttonStop = new Button();
buttonStop.setBounds(new Rectangle(145, 78, 105, 30));
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
Programmation Objet et langage Java
// Désactiver le bouton
// Ecrire "Stop" sur la label du bouton
// Abonner et définir l’écouteur du bouton (utiliser WindowBuilder)
// Dans l’écouteur : arrêter le timer
}
return buttonStop;
}
/**
* This method initializes buttonFichier
*
* @return java.awt.Button
*/
private Button getButtonFichier()
{
if (buttonFichier == null)
{
buttonFichier = new Button();
buttonFichier.setBounds(new Rectangle(14, 37, 238, 30));
buttonFichier.setLabel("Fichier");
buttonFichier.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent e)
{
// Rendre visible le contrôle fileDialog (il a été instancié dans le constructeur)
// A l’aide des méthodes fournies par le contrôle fileDialog,
//
concaténer dans l’attribut file de type String :
//
le répertoire et le nom du fichier choisis.
// Afficher le nom du fichier sur la barre de titre l'afficheur
// Lire le fichier
readFile();
// Activer les boutons buttonStart et buttonStop
}
});
}
return buttonFichier;
}
/**
* readFile lit la première ligne du fichier spécifié par l’attribut file
* readFile doit capturer les exceptions FileNotFoundException et IOException
*/
private void readFile()
{
// Capturer les exceptions
// Instancier l'objet bfr pour qu'il pointe sur le fichier spécifier par l’attribut file.
// Lire uniquement la première ligne du fichier
// Encadrer cette ligne par la chaine lineBlank
// Fermer le fichier
// Traiter les erreurs
//
FileNotFoundException
//
Mettre à jour la barre de titre avec le message "Fichier non trouvé !"
//
//
IOException
Mettre à jour la barre de titre avec le message ""Erreur de lecture"
}
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
-9-
Programmation Objet et langage Java
/**
* This method initializes this
* Ne pas modifier
* @return void
*/
private void initialize()
{
labelMax = new Label();
labelMax.setBounds(new Rectangle(216, 116, 34, 21));
// Incrire dans le label labelMax avec la valeur spécifiée par MAX_TIME (en secondes)
labelMin = new Label();
labelMin.setBounds(new Rectangle(16, 114, 37, 23));
// Incrire dans le label labelMin avec la valeur spécifiée par MAX_MIN (en secondes)
this.setLayout(null);
this.setSize(265, 179);
this.setTitle(nom + ": Pilote afficheur défilant");
this.setLocation(new Point(100, 100));
this.add(getScrollbarVitesse(), null);
this.add(getButtonStart(), null);
this.add(getButtonStop(), null);
this.add(getButtonFichier(), null);
this.add(labelMin, null);
this.add(labelMax, null);
this.addWindowListener(new java.awt.event.WindowAdapter()
{
public void windowClosing(java.awt.event.WindowEvent e)
{
System.exit(0);
}
});
}
// Fonction timer, abonnement et écouteur
private Timer createTimer ()
{
ActionListener action = new ActionListener ()
{
// Position courante dans la chaine à afficher. Initialisé à 0
int pos = 0;
// Ecouteur du timer. Appelé par défaut toutes les 100 ms
public void actionPerformed (ActionEvent event)
{
// Cette séquence provoque le défilement du texte dans l’afficheur
// Calculer la nouvelle position courante du début du texte dans l'afficheur
// Ne pas oublier de maintenir pos dans un intervalle acceptable (voir sujet)
// Si le pos == 0, relire le fichier
}
};
return new Timer (MIN_TIME, action);
}
}
//
@jve:decl-index=0:visual-constraint="7,25"
Daniel Tschirhart & Pierre Sosinski. Edition du 12/12/2012, mise à jour 12/12/12 (TP5NewV5.12.docx).
-10-

Documents pareils