MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Cours 5 : IHM, MVC
Vincent Guigue
UPMC - LIP6
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Architecture actuelle
◦ Informations stockées dans une image
◦ Création de l’image : - Soit dans le main - Soit dans la Simulation
◦ Modification de l’image : - Dans la simulation
◦ Sauvegarde de l’image : - Dans le main
+drive(Commande c): void Voiture <<INT>>
Circuit <<INT>>
- Strategy strategy Simulation Commande
Utilise
Strategy <<INT>>
Génère
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Vers un système indépendant
◦ On veut un système indépendant
- Pouvoir le brancher ou le débrancher facilement, sans intervenir dans le code de la simulation
- Pouvoir changer de système de visualisation
◦ Il existe un modèle standard (assez lourd) pour gérer cette situation : MVC Model View Controller
- Pour chaque élément (voiture, circuit,...), un objet vue est créé.
- Une vue générique est élément capable de gérer la vue d’un objet (cf slide suivant)
- Lorsque le modèle change il informe le Controller (évènement)
- Le Controller met à jour les informations d’affichage
credit : wikipedia
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Proposition de base
◦ Information toujours stockées dans une image
◦ On travaille sur un système de branchement universel depuis le main
- On pourra brancher un autre système plus tard
◦ Modèle physique :
- Aucune référence à l’affichage
- Modèle autonome : peut fonctionner sans affichage
◦ Visualisation
- Branchement depuis le main
Modèle physique
Voiture
Vue
Observer de Voiture Branchement dans le main
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Observer
◦ Le code sera développé dans un nouveau package : li260.view.observeurs
◦ VoitureObserveur sait afficher la voiture dans l’image
◦ Le système d’affichage est découplé du modèle : on peut le débrancher ou en mettre un autre... Depuis le main
Voiture <<INT>> Circuit <<INT>>
Strategy <<INT>>
...
Simulation Commande
+ print(BufferedImage im): voidObserveur <<INT>>
+ print(BufferedImage im): void - Voiture vVoitureObserveur - ArrayList<Observeur> liste
- BufferedImage im Controleur
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Observer : cahier des charges
◦ Support = image
◦ Fonction = sauver des informations
Cahier des charges associé :
un objet est Observer s’il est capable de sauver des informations dans une image.
Exemple : l’observer de voiture sauve la position de la voiture en changeant la couleur d’un pixel.
1 p u b l i c i n t e r f a c e O b s e r v e r {
2 p u b l i c v o i d p r i n t ( B u f f e r e d I m a g e im ) ;
3 }
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Oberver : implémentation
1 p u b l i c c l a s s V o i t u r e O b s e r v e r imp leme nts O b s e r v e r {
2 p r i v a t e V o i t u r e v o i t u r e ;
3 p r i v a t e C o l o r c o l o r = C o l o r . y e l l o w ;
4 p r i v a t e C o l o r c o l o r D e r a p e = C o l o r . r e d ;
5
6 p u b l i c V o i t u r e O b s e r v e r ( V o i t u r e v o i t u r e ) {t h i s. v o i t u r e = v o i t u r e ; }
7
8 p r i v a t e i n t g e t X ( ) {r e t u r n (i n t) v o i t u r e . g e t P o s i t i o n ( ) . g e tX ( ) ; }
9
10 p r i v a t e i n t g e t Y ( ) {r e t u r n (i n t) v o i t u r e . g e t P o s i t i o n ( ) . g e t Y ( ) ; }
11
12 p u b l i c C o l o r g e t C o l o r ( ) {
13 i f( v o i t u r e . g e t D e r a p a g e ( ) ) r e t u r n c o l o r D e r a p e ;
14 r e t u r n c o l o r ;
15 }
16
17 p u b l i c v o i d p r i n t ( B u f f e r e d I m a g e im ) {
18 im . setRGB ( g e t X ( ) , g e t Y ( ) , g e t C o l o r ( ) . getRGB ( ) ) ;
19 }
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Usage
Usage type depuis le main :
1
2 C i r c u i t c = C i r c u i t F a c t o r y . b u i l d ( . . . ) ; // s i méthode b u i l d s t a t i c
3 V o i t u r e v = V o i t u r e F a c t o r y . b u i l d ( c ) ; // s i méthode b u i l d s t a t i c
4
5 S t r a t e g y s t r = new S t r a t e g y ( c , v , . . . ) ;
6
7 V o i t u r e O b s e r v e r v o b s = new V o i t u r e O b s e r v e r ( v ) ;
8 C o n t r o l e u r c o n t r = new C o n t r o l e u r ( c ) ;
9 c o n t r . add ( v o b s ) ;
◦ Bcp d’abstraction
◦ Possibilité de retirer très facilement l’observation (en laissant
le modèle fonctionner)
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Usage (2)
◦ EVOLUTIVITE :
- Si on veut changer la représentation de la voiture, c’est facile
· Exemple : changer la couleur de la trace
- Changer la représentation ne modifie pas la simulation - Changer la simulation ne modifie pas la représentation
◦ LIMITE :
- Les observeurs forment un ensemble cohérent avec le controleur : il faut les faire évoluer ensemble
- Il faut encore gérer la dynamique : les observers doivent être
appeler régulièrement !
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Principe général
Evènement vs programmation linéaire
Différents éléments réagissent les uns par rapport aux autres : ils émettent des événements et écoutent ce qui se passe autour d’eux.
Principe : chaque composant doit être indépendant, le main fait le lien entre certains émetteurs et certains récepteurs.
Exemple :
1
La voiture bouge, la simulation (physique) doit envoyer un signal : update
2
Si la vue est branchée, elle reçoit le message et procède à une
mise à jour
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Emetteur/récepteur
◦ Émetteur : la Simulation émet un évènement lorsqu’une mise à jour de l’affichage est nécessaire
- L’émission revient à un appel de méthode dans le récepteur - L’émetteur doit connaître/stocker les récepteurs pour pouvoir
leur envoyer le message
- Les récepteurs doivent répondre à un cahier des charges : on doit être sur que la méthode de réception est implémentée...
◦ Récepteur : le Controleur recoit le message à travers un appel à la méthode manageUpdate(). Il met à jour l’image.
- L’observeur fait le tampon entre la simulation et l’affichage, c’est le garant de l’indépendance
Cahiers des charges ⇒ utilisation d’interfaces
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Définition des interfaces
◦ Emetteur :
1 p u b l i c i n t e r f a c e U p d a t e E v e n t S e n d e r {
2 p u b l i c v o i d add ( U p d a t e E v e n t L i s t e n e r l i s t e n e r ) ;
3 p u b l i c v o i d u p d a t e ( ) ;
4 }
1
Recevoir des écouteurs
2
Leur envoyer un message
◦ Récepteur :
1 p u b l i c i n t e r f a c e U p d a t e E v e n t L i s t e n e r {
2 p u b l i c v o i d manageUpdate ( ) ;
3 }
1
Réagir en cas de message
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Emetteur/récepteur UML
+ update() : void
+ add(UpdateEventListener l): void ...
- ArrayList< UpdateEventListener> list ...
Simulation
+ print(BufferedImage im): void Observeur <<INT>>
+ manageUpdate(): void ...
- ArrayList<Observeur> liste - BufferedImage im
Controleur + void update()
+ void add(UpdateEventListener l) UpdateEventSender <<INT>>
+ void manageUpdate() UpdateEventListener <<INT>>
...
Dans le main :
1 C i r c u i t F a c t o r y c f a c = new C i r c u i t F a c t o r y F r o m F i l e ( f i l e n a m e ) ;
2 C i r c u i t t r a c k = c f a c . b u i l d ( ) ; // s i méthode non s t a t i c
3 V o i t u r e F a c t o r y v F a c = new F e r r a r i F a c t o r y ( t r a c k ) ;
4 V o i t u r e v = v F a c . b u i l d ( ) ; // s i méthode non s t a t i c
5 ( . . . ) // s t r a t e g i e s
6 C o n t r o l e u r ihm = new C o n t r o l e u r ( t r a c k ) ;
7 ihm . add (new V o i t u r e O b s e r v e u r ( v ) ) ;
8 s i m u . add ( ihm ) ;
9 s i m u . p l a y ( )
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Séquence de communication
ACTE 0 :
◦ Le main fait le lien entre Vue(=Controleur dans cette modélisation) et Modèle physique
(ligne 8 transparent précédent) ACTE 1 : Emission/Diffusion
◦ La simulation décide d’envoyer un message appel à void update()
1 p u b l i c v o i d u p d a t e ( ) {
2 f o r( U p d a t e E v e n t L i s t e n e r
3 l i s t e n e r : l i s t e n e r s )
4 l i s t e n e r . manageUpdate ( ) ;
5 }
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Séquence de communication (2)
ACTE 2 : Reception
Les méthodes manageUpdate() des récepteurs sont invoquées ACTE 3 : Mise à jour de la vue
◦ Le controleur/vue a un attribut ArrayList<Observer>
liste
1 p u b l i c v o i d manageUpdate ( ) {
2 f o r( O b s e r v e u r I m a g e o : l i s t e )
3 o . p r i n t ( i m a g e ) ;
4 }
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Evolutivité
Dans les cours à venir, nous étudierons :
◦ Bibliothèque SWING (interface graphique JAVA)
◦ Introduction à la 3D
Nouvelle notion : affichage temps réel (ou au moins dynamique)...
Bonne nouvelle :
L’architecture prévue est capable de gérer cela !
Rafraichissement de l’affichage lors des notifications de
changements...
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Limites
◦ Communication unidirectionnelle : - Controleur ⇒ Vue OK
- Vue ⇒ Controleur KO !
◦ A-t-on besoin d’une telle communication ? Dans quel(s) cas ?
- Mode pause, rectification de stratégie en direct...
◦ Comment coder ?
- Créer un PauseEvent : le contrôleur est émetteur, le modèle récepteur...
- Pas très générique... Mais facile et propre.
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Limites
◦ Communication unidirectionnelle : - Controleur ⇒ Vue OK
- Vue ⇒ Controleur KO !
◦ A-t-on besoin d’une telle communication ? Dans quel(s) cas ? - Mode pause, rectification de stratégie en direct...
◦ Comment coder ?
- Créer un PauseEvent : le contrôleur est émetteur, le modèle récepteur...
- Pas très générique... Mais facile et propre.
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Limites
◦ Communication unidirectionnelle : - Controleur ⇒ Vue OK
- Vue ⇒ Controleur KO !
◦ A-t-on besoin d’une telle communication ? Dans quel(s) cas ? - Mode pause, rectification de stratégie en direct...
◦ Comment coder ?
- Créer un PauseEvent : le contrôleur est émetteur, le modèle récepteur...
- Pas très générique... Mais facile et propre.
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
1
MVC - observer
2
MVC - évènements
3
SWING
4
Dialogue avancé
5
Personnalisation
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
SWING : la librairie JAVA pour les IHM
◦ Surcouche de AWT (Abstract Window Toolkit)
◦ Swing, une librairie qui permet de créer tous les éléments classiques des interfaces : Fenêtre, boutons, listes...
◦ Gestion propre des évènements et de la communication entre les différents composants
Dans ce cours :
◦ Mots clés de base pour aller dans la doc
◦ Que se passe-t-il quand on clique ?
◦ Comment réactualiser l’affichage du projet ?
◦ ...
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Idée générale
Imbrication des composants :
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Niveau supérieur : la fenêtre
◦ Composant JFrame
◦ Création d’une fenêtre :
1 JFrame f e n e t r e = new JFrame (" S i m u l a t i o n ␣ L I 2 6 0 ␣ ! ") ;
◦ Tous les composants de base (dont JFrame) sont des conteneurs : on ajoute les éléments dans le conteneur.
1 f e n e t r e . add (new J P a n e l ( ) ) ;
◦ La taille du composant JFrame sera définie automatiquement par les composants ajoutés
Normalement, pas besoin de plus d’options ? Sinon, cf la
javadoc !
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Layout : philosophie de remplissage
Stratégie de remplissage 6= composant
N’importe quel conteneur peut être associé à n’importe quelle stratégie de remplissage...
Quelques exemples :
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Layout : les possibilités principales
◦ Gestionnaire par défault : java.awt.FlowLayout
- Agencement de gauche à droite, de haut en bas, utilise la taille préférée des sous-composants
◦ Gestionnaire à bords : java.awt.BorderLayout
- Agencement de 5 sous-composants : Nord, Sud, Est, Ouest et Centre
◦ Gestionnaire à grille : java.awt.GridLayout
- Agencement dans une grille N × M avec une taille partagée
par tous les sous-composants
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Layout : syntaxe dans le détail Sur un exemple type :
1 p u b l i c c l a s s T e s t {
2 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
3 J b u t t o n [ ] b o u t o n ;
4 b o u t o n = new J B u t t o n [ nb ] ;
5 f o r(i n t i =0; i <nb ; i ++)
6 b o u t o n [ i ] = new J B u t t o n (" Bouton "+( i + 1 ) ) ;
7
8 JFrame f e n e t r e = new JFrame ("mon␣ t e s t ") ;
9 f e n e t r e . s e t S i z e ( 3 2 0 , 2 0 0 ) ;
10
11 // c h o i x l a y o u t
12 ( . . . )
13
14 // a j o u t d e s b o u t o n s
15 ( . . . )
16
17 // a c t i v a t i o n s t a n d a r d
18 f e n e t r e . s e t V i s i b l e (t r u e) ;
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Layout : syntaxe dans le détail (2)
1 // c h o i x l a y o u t
2 C o n t a i n e r c o n t e n e u r P r i n c i p a l = f e n e t r e . g e t C o n t e n t P a n e ( ) ;
3 c o n t e n e u r P r i n c i p a l . s e t L a y o u t (new F l o w L a y o u t ( ) ) ;
4
5 // a j o u t d e s b o u t o n s
6 f o r(i n t i =0; i <nb ; i ++)
7 c o n t e n e u r P r i n c i p a l . add ( b o u t o n [ i ] ) ;
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Layout : syntaxe dans le détail (3)
1 // c h o i x l a y o u t
2 C o n t a i n e r c o n t e n e u r P r i n c i p a l = f e n e t r e . g e t C o n t e n t P a n e ( ) ;
3 c o n t e n e u r P r i n c i p a l . s e t L a y o u t (new B o r d e r L a y o u t ( ) ) ;
4
5 // a j o u t d e s b o u t o n s
6 c o n t e n e u r P r i n c i p a l . add ( b o u t o n [ 0 ] , B o r d e r L a y o u t .NORTH ) ;
7 c o n t e n e u r P r i n c i p a l . add ( b o u t o n [ 1 ] , B o r d e r L a y o u t . EAST ) ;
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Layout : syntaxe dans le détail (4)
1 // c h o i x l a y o u t
2 C o n t a i n e r c o n t e n e u r P r i n c i p a l = f e n e t r e . g e t C o n t e n t P a n e ( ) ;
3 c o n t e n e u r P r i n c i p a l . s e t L a y o u t (new G r i d L a y o u t ( ) ) ;
4
5 // a j o u t d e s b o u t o n s
6 f o r(i n t i =0; i <nb ; i ++)
7 c o n t e n e u r P r i n c i p a l . add ( b o u t o n [ i ] ) ;
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Astuce : les boites Obtenir des dispositions complexes :
◦ Gestionnaire à boîtes : javax.swing.Box
◦ agencement à l’horizontale ou verticale très flexible
◦ possibilités d’insérer des ressorts (dites «glue» terme mal
choisi)
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Astuce : les boites (2) Obtenir des dispositions complexes :
1 C o n t a i n e r c o n t e n e u r P r i n c i p a l = f e n e t r e . g e t C o n t e n t P a n e ( ) ;
2 Box v b o x = Box.createVerticalBox() ; // méthode s t a t i q u e
3 c o n t e n e u r P r i n c i p a l . add ( v b o x ) ;
4 Box hbox = Box.createHorizontalBox() ;
5 v b o x . add ( hbox ) ;
6 f o r(i n t i =0; i <5; i ++)
7 hbox . add ( b o u t o n [ i ] ) ;
8 f o r(i n t i =5; i <nb ; i ++)
9 v b o x . add ( b o u t o n [ i ] ) ;
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Astuce : les boites (32) Obtenir des dispositions complexes :
1 C o n t a i n e r c o n t e n e u r P r i n c i p a l = f e n e t r e . g e t C o n t e n t P a n e ( ) ;
2 Box v b o x = Box . c r e a t e V e r t i c a l B o x ( ) ; // méthode s t a t i q u e
3 c o n t e n e u r P r i n c i p a l . add ( v b o x ) ;
4 Box hbox = Box . c r e a t e H o r i z o n t a l B o x ( ) ; v b o x . add ( hbox ) ;
5 f o r(i n t i =0; i <4; i ++) hbox . add ( b o u t o n [ i ] ) ;
6 hbox . add (Box.createHorizontalGlue()) ; hbox . add ( b o u t o n [ 4 ] ) ;
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Bibliothèque de composants
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Bibliothèque de composants
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Bibliothèque de composants
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Cas d’étude
1 p u b l i c c l a s s C o n v e r t V i e w e x t e n d s JFrame {
2 p r i v a t e J L a b e l p r i x L b l ;
3 p r i v a t e J T e x t F i e l d p r i x T x t ;
4 p r i v a t e J L a b e l t a u x L b l ;
5 p r i v a t e J T e x t F i e l d t a u x T x t ;
6 p r i v a t e J L a b e l c o n v e r s i o n L b l ;
7 p r i v a t e J B u t t o n c o n v e r t i r B t n ;
8 p r i v a t e J B u t t o n q u i t t e r B t n ;
9
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Dialogue des composants : évènements
◦ Lorsque l’on clique sur un bouton, le bouton envoie un événement
◦ Il faut écouter ces évènements pour agir en conséquence.
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Gestion des évènements SWING Créer un objet qui écoute :
◦ Les évènements Button : ActionListener
◦ Les évènements Souris : MouseListener
1 p u b l i c c l a s s C o n t r o l e u r impleme nts A c t i o n L i s t e n e r , M o u s e L i s t e n e r {
2 p u b l i c v o i d m o u s e C l i c k e d ( MouseEvent e ) {} // mouse
3 p u b l i c v o i d m o u s e E n t e r e d ( MouseEvent e ) {} // mouse
4 p u b l i c v o i d m o u s e E x i t e d ( MouseEvent e ) {} // mouse
5 p u b l i c v o i d m o u s e P r e s s e d ( MouseEvent e ) {} // mouse
6 p u b l i c v o i d m o u s e R e l e a s e d ( MouseEvent e ) {} // mouse
7 p u b l i c v o i d a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) {} // b o u t o n
8 }
Appel et usage :
1 J B u t t o n c o n v e r t = new J B u t t o n (" C o n v e r t i r ") ;
2 J P a n e l p a n e l = new J P a n e l ( ) ;
3 C o n t r o l e u r c = new C o n t r o l e u r ( ) ; c o n v e r t . a d d A c t i o n L i s t e n e r ( c ) ;
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Gestion des évènements SWING (2)
◦ On est automatiquement dirigé vers la méthode de gestion des évènements
- On vérifie l’origine de l’évènement
- Les informations relatives à l’évènements sont disponibles
◦ On effectue l’opération adéquat
1 p u b l i c v o i d a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) {
2 i f( e . getActionCommand ( ) . e q u a l s (" C o n v e r t i r ") ) {
3 [ . . . ]
4 }
5 }
6 p u b l i c v o i d m o u s e P r e s s e d ( MouseEvent e ) {
7 i f( e . g e t B u t t o n ()==1) [ . . . ]
8 e l s e i f( e . g e t B u t t o n ()==2) [ . . . ]
9
10 // u s a g e
11 d o u b l e x = e . g e t X ( ) ; d o u b l e y = e . g e t Y ( ) ;
12 }
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Gestion des évènements SWING (3)
Interaction entre le Controleur et les composants SWING
1
Controleur possède les composants comme attributs : Pas très propre
- Controleur et Vue ne sont plus indépendants dans ce cas
2
Construction d’évènements spécifiques
- Le contrôleur envoie un évènement à la vue avec les informations utiles...
- Propre mais assez lourd
1 p u b l i c v o i d a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) {
2 i f( e . getActionCommand ( ) . e q u a l s (" C o n v e r t i r ") ) {
3 // r é c u p é r a t i o n d ’ un champ
4 // m i s e à j o u r d ’ un a u t r e champ
5 }
}
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Solution 1
◦ Création d’un objet Jeu regroupant tous les éléments du modèle
◦ Création d’un objet InterfaceGr connaissant tous les éléments de la vue
Gestion simple... Et peu évolutive
A chaque action, le contrôleur répond en modifiant directement les éléments concernés :
l’ensemble du contrôleur est développé spécifiquement à une version de l’application.
◦ Est suffisant pour LI260 ? Probablement...
1 p u b l i c c l a s s C o n t r o l e u r impleme nts A c t i o n L i s t e n e r {
2 p r i v a t e J e u j e u ;
3 p r i v a t e I n t e r f a c e G r p a n e l ;
4
5 . . .
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Solution 1 (sur l’exemple précédent)
1 // main
2 J B u t t o n c o n v e r t = new J B u t t o n (" C o n v e r t i r ") ;
3 J B u t t o n q u i t = new J B u t t o n (" Q u i t t e r ") ;
4 J T e x t F i e l d p r i x = new J T e x t F i e l d ( ) ;
5 J T e x t F i e l d t a u x = new J T e x t F i e l d ( ) ;
6 J L a b e l r e s u l t = new J L a b e l ( ) ;
7 [ . . . ] // C h o i x L a y o u t
8 [ . . . ] // A j o u t d e s c o m p o s a n t s d a n s un J P a n e l , d a n s une JFrame
9
10 // c o n n a i s s a n c e d e s c o m p o s a n t s
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Solution 1 (sur l’exemple précédent)
1 // Dans l e C o n t r o l e u r
2 p r i v a t e J T e x t F i e l d p r i x ;
3 p r i v a t e J T e x t F i e l d t a u x ;
4 p r i v a t e J L a b e l r e s u l t ;
5 [ . . . ] // c o n s t r u c t e u r . . .
6
7 p u b l i c v o i d a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) {
8 i f( e . getActionCommand ( ) . e q u a l s (" C o n v e r t i r ") ) {
9 d o u b l e d _ p r i x = D o u b l e . v a l u e O f ( p r i x . g e t T e x t ( ) ) ;
10 d o u b l e d_taux = D o u b l e . v a l u e O f ( t a u x . g e t T e x t ( ) ) ;
11
12 r e s u l t . s e t T e x t ( d _ p r i x∗d_taux ) ;
13 }
14 }
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Solution 2
Le contrôleur connait une vue abstraite (= cahier des charges=interface)
+ void sendEvent(EventMAJVue e) - Vue vue
Controleur
+ void maj(EventMAJVue e) Vue <<INT>>
+ void maj(EventMAJVue e) - ArrayList<Observer> liste
VueImpl Ordonne une MAJ
- informations diverses...
EventMAJVue Utilisent pour la communication d'informations
Exemple : Ordre = mise à jour de la position de la voiture
◦ La vue est indépendante pour gérer l’ordre...
◦ Une modification de la vue n’implique pas de modification du
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
1
MVC - observer
2
MVC - évènements
3
SWING
4
Dialogue avancé
5
Personnalisation
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Proposition actuelle
◦ Utilisation des composants existants
◦ Développement d’un contrôleur pour la gestion des évènements
- Réception des évènements standard des composants - Mise à jour des composants via leur méthodes setXXX
◦ Limites : pas de possibilité d’interagir avec le coeur d’un composant
- Exemple : pas de composant tableau noir avec des possibilités de dessin
◦ Solution : la surcharge des composants existants
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Surcharge de composants
Proposition de vue pour le projet :
1 p u b l i c c l a s s IHMSwing e x t e n d s J P a n e l
2 impleme nts U p d a t e E v e n t L i s t e n e r {
3 p r i v a t e A r r a y L i s t <ObserverSWING> l i s t ;
4
5 [ . . . ] // c o n s t r u c t e u r
6
7 // g e s t i o n d e s é v è n e m e n t s s t a n d a r d
8 p u b l i c v o i d manageUpdate ( ) {
9 r e p a i n t ( ) ; // f o n c t i o n s p é c i f i q u e d e s c o m p o s a n t s SWING
10 }
11
12 // s u r c h a r g e de l a méthode d ’ a f f i c h a g e du c o m p o s a n t
13 p u b l i c v o i d p a i n t ( G r a p h i c s g ) {
14 s u p e r. p a i n t ( g ) ;
15 [ . . . ] // c o d e à a j o u t e r p o u r d e s s i n e r c e que l ’ on v e u t
16 }
17 }
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Surcharge du JPanel : méthode paint
1
Appel à rafraichir (venant d’autres éléments du programme, du système...)
2
La JFrame notifie tous ses éléments (transmission en profondeur dans l’arbre)
3
Le JPanel fait alors appel à sa méthode standard public void paint(Graphics g)
La méthode transmet un pointeur permettant de dessiner :
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
ObserverSWING
Maintenant que le fonctionnement de SWING est clarifié, vous devez concevoir des Observer adéquats...
Les observers reçoivent le pointeur Graphics et se dessinent eux mêmes...
1 p u b l i c i n t e r f a c e ObserverSWING {
2 p u b l i c v o i d p r i n t ( G r a p h i c s g ) ;
3 }
NB : l’affichage est entièrement fait à chaque appel, il faut donc
tout dessiner (Circuit, Voiture...). Rien n’est persistent.
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
ObserverSWING : exemple
Implémentation basique pour la voiture :
1 p u b l i c c l a s s V o i t u r e O b s e r v e r imp leme nts ObserverSWING {
2 p r i v a t e V o i t u r e v o i t u r e ;
3 p r i v a t e C o l o r c o l o r = C o l o r . y e l l o w ;
4
5 p u b l i c V o i t u r e O b s e r v e u r ( V o i t u r e v o i t u r e ) {
6 t h i s. v o i t u r e = v o i t u r e ;
7 }
8
9 p u b l i c i n t g e t X ( ) { r e t u r n (i n t) v o i t u r e . g e t P o s i t i o n ( ) . g e t X ( ) ; }
10
11 p u b l i c i n t g e t Y ( ) { r e t u r n (i n t) v o i t u r e . g e t P o s i t i o n ( ) . g e t Y ( ) ; }
12
13 p u b l i c v o i d p r i n t ( G r a p h i c s g ) {
14 g . s e t C o l o r ( c o l o r ) ;
15 g . d r a w R e c t ( g e t X ( ) , g et Y ( ) , 2 , 2 ) ;
16 }
}
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
CircuitObserver et affichage d’image
L’affichage d’une image est trivial une fois étudiée la javadoc de Graphics :
1 // d a n s C i r c u i t O b s e r v e r
2
3 p r i v a t e Image t r a c k I m ;
4 [ . . . ] // c o n s t r u c t e u r
5
6 p u b l i c v o i d p r i n t ( G r a p h i c s g ) {
7 g . d r a w I m a g e ( t r a c k I m , 0 , 0 , n u l l) ;
8 }
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Depuis le main
1 JFrame f e n = new JFrame ( ) ;
2 IHMSwing ihm = new IHMSwing ( ) ;
3
4 ihm . add (new C i r c u i t O b s e r v e u r ( t r a c k ) ) ;
5 ihm . add (new V o i t u r e O b s e r v e u r ( v ) ) ;
6 ihm . add (new T r a j e c t o i r e O b s e r v e u r ( v ) ) ;
7 ihm . add (new R a d a r O b s e r v e u r ( s t r a t e g y . g e t R a d a r ( ) , v ) ) ;
8
9 s i m u . add ( ihm ) ; // p o s s i b i l i t é de m e t t r e p l u s i e u r s o b s
10
11 ihm . s e t P r e f e r r e d S i z e (new D i m e n s i o n ( 7 6 8 , 1 0 2 4 ) ) ;
12 f e n . s e t C o n t e n t P a n e ( ihm ) ;
13 f e n . s e t V i s i b l e (t r u e) ;
14 f e n . p a c k ( ) ;
15
16 s i m u . p l a y ( ) ;
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Quelques astuces utiles
◦ Quitter le programme proprement - En fermant la fenêtre JFrame
1 JFrame wind ows = new JFrame ( ) ;
2 win dows . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT_ON_CLOSE ) ;
- Suite à un clic sur Quitter
1 S y s t e m . e x i t ( 0 ) ;
◦ Bug de gestion de la taille des JTextField
1 J t e x t F i e l d t e x t F i e l d = new J t e x t F i e l d ( 4 0 ) ; // 40 c a r a c t è r e s
2 t e x t F i e l d . s e t M a x i m u m S i z e ( t e x t F i e l d . g e t P r e f e r r e d S i z e ( ) ) ;
MVC - observer MVC - évènements SWING Dialogue avancé Personnalisation
Quelques astuces utiles (2) Gestion du rafraîchissement des JPanel : Plusieurs problèmes se posent :
◦ courses trop rapides
◦ affichage qui se met à jour seulement à la fin de la course
1 p u b l i c v o i d manageUpdate ( ) {
2 t r y { // p o u r l e s c o u r s e s t r o p r a p i d e s
3 T h r e a d . s l e e p ( 1 ) ;
4 } c a t c h ( I n t e r r u p t e d E x c e p t i o n e ) {
5 e . p r i n t S t a c k T r a c e ( ) ;
6 }
7 // Pour que l ’ a f f i c h a g e s u i v e c o r r e c t e m e n t
8 S w i n g U t i l i t i e s . i n v o k e L a t e r (new R u n n a b l e ( ) {
9 p u b l i c v o i d r u n ( ) {
10 r e p a i n t ( ) ;
11 }
12 } ) ;