1. Transparents Java, P.Durif 1
G´n´ralit´s
e e e
Programmation d’IHM avec Une IHM permet ` un ˆtre humain
a e
d’interagir avec un syst`me (informatique).
e
Java Swing Il y a trois aspects qu’il faut expliciter :
– Le Mod`le est le syst`me manipul´ et doit
e e e
Philippe Durif conserver son autonomie (une BD par exemple)
13 novembre 2007 – La Vue (graphique ou textuelle) que donne
l’IHM du Mod`lee
– Le Contrˆle de ce que montre la vue ou de
o
l’´tat du mod`le via des boutons, menus ou des
e e
commandes textuelles propos´s par la vue.
e
Cela donne le classique mod`le MVC.
e
La chose la plus importante est probablement que
le mod`le (M) soit compl`tement ind´pendant de
e e e
toutes IHM (VC) permettant de le manipuler.
Dans ce cas il est possible d’avoir plusieurs IHM
diff´rentes sur un mˆme mod`le.
e e e
Un administrateur syst`me pourra voir la liste des
e
comptes et y ajouter de nouveaux comptes, alors
qu’un utilisateur ne pourra que l’observer.
0-0
Transparents Java, P.Durif 2 Transparents Java, P.Durif 3
Exemples d’IHM Exemple d’IHM graphique
IHM mat´rielle Distributeur de boissons
e
mod`le : l’eau, les produits lyophilis´s, la
e e
m´canique de production d’une boisson,
e Sous Windows on a aussi plusieurs vues possibles
... du mˆme mod`le syst`me de fichiers : le Poste
e e e
de Travail et l’Explorateur Windows.
vue : l’afficheur
contrˆle : les boutons, la fente pour ins´rer
o e
les pi`ces de monnaie, . . .
e
Exp´rience : ouvrez simultan´ment un Poste de
e e
IHM informatique en mode texte Dans les Travail et un Explorateur Windows, puis
environnements Unix on dispose g´n´ralement
e e modifiez le mod`le via une de ces deux vues
e
de plusieurs vues sur le mod`le syst`me
e e (cr´ez un r´pertoire par exemple). Miracle ! la
e e
Unix : sh, bash, csh, tcsh, ksh, . . . modification du mod`le est r´percut´e dans les
e e e
deux vues, ce qui montre bien l’unicit´ du mod`le.
e e
Qu’est-ce qui joue le rˆle de contrˆleur sous
o o
bash ?
2. Transparents Java, P.Durif 4 Transparents Java, P.Durif 5
Principe d’IHM Dispositifs d’IHM
L’utilisateur ne per¸oit et n’agit sur le mod`le
c e Physiques vue contrˆle
o
que par l’interm´diaire de la vue.
e ´cran
e X
manette retour d’effort X
Exemple o` le mod`le est une base de donn´es,
u e e
avec deux vues. clavier led X
souris X
...
decideur vue graphe vue liste administrateur
Logiques vue contrˆle
o
bouton X X
zone de texte X X
modele ascenseur X X
BDD
label X
...
Les fl`ches
e indiquent la possibilit´ d’agir
e Les dispositifs logiques sont g´n´ralement
e e
et de percevoir. d´sign´s de fa¸on g´n´rique par le mot widget
e e c e e
Les fl`ches
e indiquent la possibilit´ de
e (pour window gadget), Windows les appelle des
percevoir. contrˆles et Swing des JComponent.
o
Transparents Java, P.Durif 6 Transparents Java, P.Durif 7
Les paquetages d’ihm du JDK AWT et Swing
javax.swing nouvelle architecture AWT 1.0 : est obsol`te, traitement des
e
(JDK1.2) qui remplace partiellement AWT. ´v´nements effectu´e par les composants
e e e
graphiques eux-mˆmes.
e
java.awt les choses non obsol`tes :
e
AWT 1.1 : le traitement des ´v´nements est confi´
e e e
– Container racine des widgets Swing,
a des EventListener, les composants sont des
`
– les gestionnaires de mise en page
beans qui permettent de mettre en place des outils
(LayoutManager),
de programmation visuelle d’ihm.
– la gestion des ´v´nements (AWTEvent).
e e
Swing 1.2 : versions am´lior´e des widgets AWT
e e
java.awt.event et javax.swing.event
et nouveaux widgets, introduction du mod`lee
pour les types ´v´nements et gestionnaires
e e
MVC, composants l´gers c’est a dire non associ´s
e ` e
d’´v´nements.
e e
a une fenˆtre native opaque, gestion du Look and
` e
Pour ´viter les confusions entre les noms des
e Feel.
classes Swing at AWT, Swing ajoute un J en Swing n’est pas ind´pendant d’AWT. Par
e
d´but de nom. Par exemple JPanel de Swing est
e exemple, Swing utilise l’architecture de traitement
le successeur du Panel d’AWT. d’´v´nements (EventListener) et les
e e
gestionnaires de mise en page (LayoutManager)
AWT est l’ancˆtre de Swing.
e
d’AWT.
3. Transparents Java, P.Durif 8 Transparents Java, P.Durif 9
Deux sortes de widgets Anatomie d’une IHM Java
Il y a principalement deux sortes de widgets
Une ihm est une hi´rarchie de widgets
e
widgets atomiques , ils disposent de : (Component) dont la racine est le JPanel de :
– une repr´sentation graphique a l’´cran,
e ` e
– la possibilit´ de r´agir a des ´v´nements qui
e e ` e e – une JFrame qui est la fenˆtre principale d’une
e
sont g´n´ralement cons´quences des actions
e e e application
de l’utilisateur, fournissant ainsi a ce
`
– une JApplet destin´e a ˆtre t´l´charg´e et dont
e `e ee e
dernier la possibilit´ d’exprimer des
e
une instance sera ex´cut´e sur le poste client
e e
commandes.
(par exemple, par un navigateur Web).
Exemple : JButton, JLabel, JTextField et
JList en Swing.
Les nœuds internes sont des JPanel ou Box.
widgets compos´s de sous-widgets
e
structurent le code et la pr´sentation visuelle :
e Les feuilles sont des widgets atomiques.
– hi´rarchie de widgets : JPanel et Box en
e
Swing, Exercice : tentez de dessiner la hi´rarchie d’une
e
– gestion de la mise en page graphique de ihm que vous utilisez.
leurs widgets enfants grˆce aux
a
LayoutManager. Pour un exemple voir page 16.
Transparents Java, P.Durif 10 Transparents Java, P.Durif 11
L’aspect visuel en Swing Hi´rarchie partielle de Swing
e
Tous les widgets Swing h´ritent de
e
java.awt.Container.
– widgets atomiques : JButton , JTextField ,
JLabel , JList .
java.awt Container LayoutManager
– widgets compos´s : JPanel ,
e
– JScrollPane : pour voir un widget trop
grand dans une fenˆtre munie d’ascenseurs (un
e JComponent JScrollPane
JList ou un JTextArea par exemple).
javax.swing
– JFrame et JApplet : attention a bien utiliser
`
getContentPane() pour ajouter des AbstractButton JTextComponent
sous-widgets ou modifier le gestionnaire de mise
en page, ou encore plus simple :
setContentPane(). JButton JTextField
– MenuElement : interface impl´ment´e par les
e e
diff´rents composants de menu : JMenuBar,
e JFileChooser JList
JPopupMenu, JMenu. Nouveau : les JFrame et
les JApplet peuvent avoir une barre de menu JLabel Box JPanel
(setJMenuBar()).
Les LayoutManager d’AWT sont utilisables.
4. Transparents Java, P.Durif 12 Transparents Java, P.Durif 13
Principales m´thodes des widgets Swing
e Gestionnaires de mise en page
JButton (String text)
Ce sont des classes qui implante l’interface
addActionListener(ActionListener)
LayoutManager et qui font la mise en page des
removeActionListener(ActionListener) widgets d’un Container.
JList voir plus loin page 39
Dans AWT :
JTextField (int columns) – FlowLayout les widgets sont rang´se
String getText (), setText (String) lin´airement de gauche a droite.
e `
setEditable (boolean) – GridLayout une grille deux dimensions dont on
fixe le nombre de lignes et de colonnes lors de
JLabel (String/Icon)
l’instanciation.
String getText (), setText (String)
– BorderLayout d´finit cinq zones que l’on
e
JFrame (String title) d´signe lors des ajouts de widget par la
e
setJMenuBar(JMenuBar mb) m´thode add avec les constantes
e
void setContentPane(Container) BorderLayout.NORTH, SOUTH, EAST, WEST,
CENTER.
Container getContentPane()
Dans Swing :
void pack (), void setVisible (boolean)
– BoxLayout un peu comme FlowLayout mais
JPanel (LayoutManager layout) peuvent ˆtre horizontaux ou verticaux.
e
Component add (Component comp) Il y en a bien d’autres !
Transparents Java, P.Durif 14 Transparents Java, P.Durif 15
Exemples Exemple 1 : Coucou
Avec les gestionnaires suivants : On veut manipuler le mod`le Compteur via une
e
JPanel p = new JPanel IHM :
(new FlowLayout (FlowLayout.CENTER)) ; class Compteur {
ou private int v = 0 ;
public void incr () { v++;}
JPanel p = new JPanel (new GridLayout (2, 4));
public int val () { return v; }
ou }
JPanel p = new JPanel () ;
L’IHM doit permettre de :
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
1. voir la valeur courante d’un Compteur (aspect
la gestion de l’emplacement du prochain widget
vue),
ajout´ est implicite :
e
2. d’incr´menter sa valeur (aspect contrˆle).
e o
p.add (new JTextField ()) ;
p.add (new JButton ("Sauver")) ; Dans cette premi`re version on ne verra que la
e
Gestion explicite de l’emplacement du prochain partie MV de MVC.
widget ajout´ :
e
JPanel p = new JPanel (new BorderLayout ()) ;
p.add(new JTextField (), BorderLayout.CENTER);
p.add(new JButton("Sauver"),BorderLayout.SOUTH);
5. Transparents Java, P.Durif 16 Transparents Java, P.Durif 17
Architecture de la vue coucou Exemple 1 : le main()
La structure de la vue est une hi´rarchie stricte :
e Dans un premier temps on ne g`re pas les
e
´v´nements.
e e
un mˆme widget ne peut ˆtre affich´ a plus d’un
e e e`
endroit.
L’application cr´e une fenˆtre (JFrame) dont le
e e
panel racine est IhmQuit :
JFrame
class AppliCoucou1 {
setContentPane()
public static void main (String arg []) {
getContentPane()
javax.swing.JFrame f =
JPanel IhmQuit BorderLayout new javax.swing.JFrame ("Vue Coucou") ;
f.setContentPane
(new IhmQuit
(new IhmCoucou(new Compteur ()))) ;
JPanel IhmCoucou JButton
f.pack () ;
modele f.setVisible (true) ;
}
Compteur JButton JLabel }
Transparents Java, P.Durif 18 Transparents Java, P.Durif 19
Exemple 1 : IhmQuit Exemple 1 : IhmCoucou
class IhmCoucou extends javax.swing.JPanel {
class IhmQuit
private final Compteur c ;
extends javax.swing.JPanel { private final javax.swing.JLabel l =
new javax.swing.JLabel () ;
public IhmQuit (javax.swing.JPanel jp) {
// FlowLayout par defaut public IhmCoucou (Compteur c) {
super (new java.awt.BorderLayout ()) ; // FlowLayout par defaut
add (jp, java.awt.BorderLayout.CENTER) ; this.c = c ;
javax.swing.JButton b = javax.swing.JButton b =
new javax.swing.JButton ("Quitter") ; new javax.swing.JButton ("Coucou") ;
add (b) ;
add (b, java.awt.BorderLayout.SOUTH) ;
add (l) ;
}
maj () ;
}
}
private void maj () {
Remarque : l.setText ("nombre de Coucous : " + c.val()) ;
– IhmQuit accepte tout JPanel en param`tre,
e }
– on a choisi le LayoutManager BorderLayout. }
6. Transparents Java, P.Durif 20 Transparents Java, P.Durif 21
La gestion des ´v´nements
e e Fonctionnement g´n´ral
e e
C’est le C de MVC.
1. suite a une action de l’utilisateur sur un
`
widget, ce widget g´n`re un ´v´nement
e e e e
AWTEvent . Exemples : ActionEvent,
Elle permet de programmer ce qui doit ˆtre fait
e
WindowEvent, KeyEvent, MouseEvent
en r´ponse aux actions de l’utilisateur.
e
2. ensuite, le widget fait traiter une copie de cet
´v´nement par chacun des listeners
e e
Elle est identique en AWT 1.1 et en Swing avec
EventListener qui lui sont connect´s et qui
e
quelques types d’´v´n´ments suppl´mentaires
e e e e
sont capables de traiter ce type d’´v´nement.
e e
pour Swing.
Par exemple, un ActionListener traitera
uniquement les ActionEvent et un
WindowListener les WindowEvent. Plus
La gestion des ´v´nements se programme en
e e g´n´ralement, un XxxListener traite
e e
implantant les interfaces listener souhait´es, puis
e uniquement les XxxEvent.
en en connectant des instances aux diff´rents
e
widgets. Le traitement d’un ´v´nement est fait en appelant
e e
une des m´thodes du listener correspondant.
e
Transparents Java, P.Durif 22 Transparents Java, P.Durif 23
Un sch´ma
e Architecture partielle Event/Listener
Voici dans quel ordre se d´roulent les choses :
e Il y a une bijection entre les types d’´v´nement et
e e
les types de listener d´finis par le JDK.
e
1 widget 2 event HAUT NIVEAU AWTEvent
action
mes listeners 4/3 clone 3/4 ActionListener TextListener ItemListener
ActionEvent TextEvent ItemEvent
listener listener listener
1 2 3
BAS NIVEAU ComponentEvent
mes listeners WindowListener
widget InputEvent WindowEvent
KeyListener MouseListener abstrait
On remarque qu’un mˆme listener peut ˆtre
e e KeyEvent MouseEvent concret
connect´ a plusieurs widgets.
e`
interface
Les listeners sont d´clench´s dans un seul thread,
e e
donc de fa¸on s´quentielle. En revanche on ne sait
c e ´ e
Ev´nements de haut niveau → application.
pas dans quel ordre ils seront d´clench´s.
e e ´ e
Ev´nements de bas niveau → Swing/AWT.
7. Transparents Java, P.Durif 24 Transparents Java, P.Durif 25
Listener ` une seule m´thode
a e Listener ` plus d’une m´thode
a e
Par exemple le listener ActionListener dispose
Un listener peut proposer plus d’une m´thode
e
de l’unique m´thode :
e
pour traiter un ´v´nement.
e e
actionPerformed (ActionEvent evt)
C’est cette m´thode qui sera appel´e lorsque le
e e
Le choix de la m´thode appel´e d´pend alors de la
e e e
widget auquel est connect´ le listener g´n´rera un
e e e
nature pr´cise de l’´v´nement.
e e e
ActionEvent.
Voici un ActionListener permettant de quitter
l’application : Par exemple, int´ressons-nous a un widget auquel
e `
class Quitter implements est connect´ un KeyListener :
e
java.awt.event.ActionListener { 1. quand on enfonce la touche a du clavier, les
public void actionPerformed m´thodes keyPressed() puis keyTyped()
e
(java.awt.event.ActionEvent event) { sont appel´es,
e
// D’abord sauver le mod`le, puis :
e
2. quand on relˆche la touche, c’est
a
System.exit (0) ;
keyReleased() qui est appel´e.
e
}
}
Transparents Java, P.Durif 26 Transparents Java, P.Durif 27
Les adapters Quelques m´thodes d’´v´nement
e e e
Pour la plupart des listeners qui ont plus d’une Pour ´crire le code d’une m´thode de listener il
e e
m´thode, le JDK fournit une impl´mentation par
e e est parfois insuffisant de connaˆ le type
ıtre
d´faut dont les m´thodes ne font rien. On appelle
e e d’´v´nement. On peut alors interroger
e e
ces classes des adapters. Par exemple, l’´v´nement lui-mˆme pour obtenir des
e e e
KeyListener dispose de l’adapter KeyAdapter et informations.
WindowListener de l’adapter WindowAdapter. Voici par exemple les informations qu’on peut
Ces adapters facilitent la vie du programmeur, obtenir aupr`s de tout ´v´nement (AWTEvent) et
e e e
mais l’expose a des erreurs de programmation
` aupr`s d’un ´v´nement souris (MouseEvent) :
e e e
difficiles a localiser.
` AWTEvent
Une erreur typique consiste a surcharger une
` getSource() renvoie le Component qui a
m´thode d´finie par l’adapter au lieu de la
e e g´n´r´ cet ´v´nement
e ee e e
red´finir car on s’est tromp´ sur le type du
e e MouseEvent
param`tre formel (l’exemple d’erreur classique est
e getX(), getY() position relative a getSource()
`
de surcharger la m´thode equals au lieu de la
e isPopupTrigger() touche de droite sous Linux
red´finir).
e
Une autre erreur consiste a mal orthographier le
`
nom de la m´thode cens´e ˆtre red´finie.
e e e e
£
¢Solution : L’annotation @Override de Java5 ¡
8. Transparents Java, P.Durif 28 Transparents Java, P.Durif 29
Connexion d’un listener Exemple de Connexion
On connecte un listener a un widget quand on
` Pour que le bouton quitter permette de quitter
veut que quelque chose se passe quand ce widget l’application, on impl´mente l’interface
e
g´n`re un ´v´nement.
e e e e ActionListener par la classe Quitter et on en
connecte une instance au bouton avec la m´thode
e
Pour connecter un listener de type Xxx a un
`
addActionListener() :
widget, on utilise la m´thode addXxxListener()
e
de ce dernier.
class Quitter implements
Il y a une bijection entre les types d’´v´nements,
e e java.awt.event.ActionListener {
les listeners et les m´thodes de connexion, par
e public void actionPerformed
exemple : (java.awt.event.ActionEvent event) {
// D’abord sauver le mod`le, puis :
e
´v´nement
e e listener m´thode de
e System.out.println ("See you soon") ;
connexion System.exit (0) ;
ActionEvent ActionListener addActionListener()
}
WindowEvent WindowListener addWindowListener()
}
KeyEvent KeyListener addKeyListener()
MouseEvent MouseListener addMouseListener()
JButton b = new JButton ("Quitter") ;
et plus g´n´ralement
e e
b.addActionListener (new Quitter ()) ;
XxxEvent XxxListener addXxxListener()
Transparents Java, P.Durif 30 Transparents Java, P.Durif 31
Quels ´v´nements pour quels
e e Exemple 2
widget ?
Reprenons l’application de l’exemple 1 pour y
Tous les widgets ne g´n`rent pas forc´ment tous
e e e int´grer la gestion d’´v´nements :
e e e
les ´v´nements possibles.
e e
class AppliCoucou2 {
public static void main (String arg []) {
javax.swing.JFrame f =
new javax.swing.JFrame ("Vue Coucou");
Un widget sait g´n´rer et traiter un ´v´nement
e e e e final Quitter quit =
XxxEvent s’il dispose directement ou par h´ritage
e new controleur.Quitter () ;
de la m´thode addXxxListener().
e f.addWindowListener (quit) ;
f.setContentPane
(new IhmQuit
(new IhmCoucou(new Compteur()), quit));
f.pack () ; // ou f.setSize (250, 100) ;
Exercice : retrouver tous les ´v´nements qu’un
e e f.setVisible (true) ;
JButton sait g´n´rer.
e e }
}
On remarque que le constructeur IhmQuit() est
maintenant param´tr´ par un Quitter.
e e
9. Transparents Java, P.Durif 32 Transparents Java, P.Durif 33
Exemple 2 : le listener Quitter Exemple 2 : IhmQuit
Le mˆme listener permet de quitter l’application
e
soit via les menus de la fenˆtre, soit via un
e class IhmQuit extends javax.swing.JPanel {
bouton. Il impl´mente donc les deux interfaces :
e public IhmQuit
(javax.swing.JPanel jp,
package controleur ;
controleur.Quitter quit)
public class Quitter {
extends java.awt.event.WindowAdapter super (new java.awt.BorderLayout ()) ;
implements java.awt.event.ActionListener {
add (jp, java.awt.BorderLayout.CENTER) ;
@Override public void windowClosing
(java.awt.event.WindowEvent w) { javax.swing.JButton b =
System.exit (0) ; new javax.swing.JButton ("Quitter") ;
} b.addActionListener (quit) ;
public void actionPerformed add (b, java.awt.BorderLayout.SOUTH) ;
(java.awt.event.ActionEvent e) { }
System.exit (0) ; }
}
} Remarque : le mˆme listener Quitter est
e
Noter l’extension de l’adapter WindowAdapter et connect´ sur la JFrame et sur le JButton.
e
l’utilisation de l’annotation @Override.
Transparents Java, P.Durif 34 Transparents Java, P.Durif 35
Exemple 2 : IhmCoucou Conception Technique
On suppose les import effectu´s
e
class IhmCoucou extends JPanel {
Le mod`le devrait ˆtre un objet observable
e e
private final Compteur c ;
(java.util.Observable) et la vue un
private final JLabel l = new JLabel () ;
public IhmCoucou (Compteur c) { observateur du mod`le (java.util.Observer).
e
this.c = c ; Un observer sera averti des changements d’´tat du
e
JButton b = new JButton ("Coucou") ; mod`le et pourra ainsi mettre a jour son
e `
b.addActionListener
affichage, ainsi les modifications faites via une
(new controleur.Incr (this, c)) ;
IHM seront visibles dans toutes les autres IHM
add (b) ; add (l) ; maj () ;
}
observant le mˆme mod`le.
e e
private void maj () {
l.setText ("nombre de Coucous : " + c.val()); L’IHM devrait ˆtre une sous-classe de JPanel
e
} } }
dont le constructeur est param´tr´ par une
e e
package controleur ;
instance du mod`le.
e
public class Incr implements ActionListener {
private IhmCoucou vue ; private Compteur c ;
public Incr (IhmCoucou vue, Compteur c) { En principe, pour la JFrame (ou la JApplet) il
this.vue = vue ; this.c = c ; n’y a plus qu’` fixer son panel racine, h´riter de
a e
}
JFrame ne paraˆ pas indispensable.
ıt
public void actionPerformed (ActionEvent e) {
c.incr () ; vue.maj () ; } }
10. Transparents Java, P.Durif 36 Transparents Java, P.Durif 37
Les menus Exemple de barre de menu Swing
En AWT les ´l´ments de menu n’´taient pas des
ee e
widgets (ou Component) !
File Edit
Heureusement, en Swing, l’architecture des menus
JMenuBar
est int´gr´e dans la hi´rarchie JComponent :
e e e
Charger Couper
JComponent Sauver Copier JMenuItem
JMenu Coller
MenuElement AbstractButton Options
JMenu
n n
JMenuBar JPopupMenu JMenuItem JMenu
JFrame ou JApplet
n JMenu
La m´thode setJMenuBar (JMenuBar) permet de
e
fixer la barre de menu d’une JFrame et d’une
Fig. 1 – Hi´rarchie des MenuElement : JMenuBar,
e JApplet.
JMenu et JPopupMenu sont des conteneurs. JMenu permet de cr´er des menus hi´rarchiques.
e e
Transparents Java, P.Durif 38 Transparents Java, P.Durif 39
Le widget liste Liste Swing :JList
L’avantage d´terminant des JList est qu’elles
e
Rˆle d’une liste : pr´senter sous forme synth´tique
o e e int`grent le mod`le dans leur fonctionnement, ce
e e
une liste d’´l´ments du mod`le (par exemple des
ee e qui all`ge ´norm´ment le travail du programmeur
e e e
fontes de caract`res, des ´tudiants, des fichiers,
e e (par rapport aux List d’AWT).
...) dans laquelle on peut choisir un ou plusieurs Le widget JList Swing est param´trable par :
e
´l´ments.
ee – ListModel le mod`le qui stocke les ´l´ments
e ee
visualis´s dans la JList. Ces ´l´ments peuvent
e ee
La repr´sentation graphique de chaque ´l´ment
e ee ˆtre de n’importe quel type r´f´rence. Lorsque
e ee
(chaˆ de caract`res, image, . . .) doit permettre
ıne e ce mod`le est modifi´ (ajout, suppression ou
e e
d’identifier de fa¸on non ambigu¨ chacun des
c e modification d’´l´ments), il doit en informer la
ee
´l´ments du mod`le.
ee e JList en appelant une des m´thodes
e
fireXxx(). La modification de la visualisation
La probl´matique principale li´e a l’utilisation de
e e ` de la liste sera alors faite automatiquement.
liste est la mise en correspondance entre les En Java5, ListModel et JList ne sont pas
´l´ments du mod`le et leurs
ee e g´n´riques !
e e
repr´sentations graphiques : quand un
e – ListCellRenderer l’objet qui impl´mente la
e
utilisateur clique sur une repr´sentation
e mani`re d’afficher chaque ´l´ment du
e ee
graphique, ce n’est pas cette derni`re qu’il veut
e ListModel.
manipuler, mais l’´l´ment qu’elle identifie.
ee – ListSelectionModel l’objet qui stocke l’´tat
e
courant de la s´lection dans la JList.
e
11. Transparents Java, P.Durif 40 Transparents Java, P.Durif 41
Architecture des JList Swing Personnalisation d’une JList
Personnaliser le ListModel (indispensable) :
n 1. sp´cialiser la classe AbstractListModel pour
e
ListDataListener cr´er un nouveau ListModel,
e
AbstractListModel DefaultListCellRenderer 2. utiliser le constructeur JList(ListModel) ou
la m´thode setModel().
e
Personnaliser le ListCellRenderer (pas rare) :
ListModel ListCellRenderer
1. sp´cialiser DefaultListCellRenderer pour
e
1 1 adapter son comportement. Ce dernier utilise
la m´thode toString() des objets du
e
JList
ListModel pour les visualiser.
1 2. utiliser la m´thode setCellRenderer() de la
e
ListSelectionModel JList.
Personnaliser le ListSelectionModel (rare) :
1. le d´faut semble convenir la plupart du
e
DefaultListSelectionModel temps, mais on peut sp´cialiser
e
n DefaultListSelectionModel
ListSelectionListener 2. utiliser la m´thode setSelectionModel() de
e
la JList.
Transparents Java, P.Durif 42 Transparents Java, P.Durif 43
Personnalisation d’une JList Changements d’´tats du mod`le
e e
Les ListDataListener connect´s au mod`le
e e
(addListDataListener()) lui permettent de
signaler ses changements d’´tat.
e
interface ListDataListener {
void intervalAdded(ListDataEvent e) ;
void intervalRemoved(ListDataEvent e) ;
Enfin, au niveau de la JList on peut utiliser
void contentsChanged(ListDataEvent e) ; }
setSelectionMode(int) pour obtenir un des
trois comportement suivant : AbstractListModel propose trois m´thodes void
e
pour d´clencher ces listeners :
e
SINGLE_SELECTION un ´l´ment s´lectionn´ au
ee e e
fireIntervalAdded (Object src, int x0, int x1)
plus
fireIntervalRemoved(Object src, int x0, int x1)
SINGLE_INTERVAL_SELECTION un intervalle fireContentsChanged(Object src, int x0, int x1)
d’´l´ments s´lectionn´s au plus
ee e e
src est le ListModel et x0, x1 les indices de la zone.
MULTIPLE_INTERVAL_SELECTION plusieurs x0=5, x1=11 ⇒ intervalle [5, 11]
intervalles d’´l´ments s´lectionn´s
ee e e Attention :
x0=5, x1=4 ⇒ intervalle [4, 5] non vide
' $
Une JList attache automatiquement des
ListDataListener a son mod`le, ce qui garan-
` e
tit que la ou les vues JList seront toujours a jour.
`
& %
JList int`gre le mod`le observateur/observ´.
e e e
12. Transparents Java, P.Durif 44 Transparents Java, P.Durif 45
Attention Contrˆle de la s´lection
o e
Plusieurs listeners du mˆme type peuvent ˆtre
e e Les ListSelectionListener connect´s au e
connect´s a un mˆme objet source.
e ` e ListSelectionModel ou a la JList seront
`
appel´s a chaque fois que l’utilisateur modifie la
e `
Quand l’´v´nement correspondant a ces listeners
e e ` s´lection de la JList.
e
est produit par l’objet source, ils sont tous
ex´cut´s.
e e interface ListSelectionListener {
void valueChanged (ListSelectionEvent e) ;
Java garantit que ces listeners seront ex´cut´s
e e
}
dans un seul thread, c’est a dire s´quentiellement.
` e
L’´v´nement ListSelectionEvent ne donne pas
e e
En revanche on ne sait rien de l’ordre dans
d’information pr´cise sur le nouvel ´tat de la
e e
lequel ces listeners seront ex´cut´s.
e e
s´lection : le listener devra interroger l’´metteur
e e
Autrement dit, si le bon fonctionnement de l’un
de cet ´v´nement ou bien simplement la JList
e e
de ces listeners d´pend du fait qu’un autre de ces
e
avec par exemple :
listener ait d´j` ´t´ ex´cut´, on peut dire que
eaee e e
l’application contient une erreur.
public int getMinSelectionIndex ()
Si vous connectez vos propres ListDataListener public int[] getSelectedIndices ()
a votre mod`le, prenez bien garde qu’ils ne
` e public Object getSelectedValue ()
public Object[] getSelectedValues ()
d´pendent pas de l’´tat de la JList ! ! !
e e
Transparents Java, P.Durif 46 Transparents Java, P.Durif 47
Exemple : liste d’´tudiant
e Le mod`le promotion (ListModel)
e
class Promotion extends AbstractListModel {
Supposons qu’on veuille afficher une promotion
private java.util.ListEtudiant l =
d’Etudiant
new java.util.ArrayListEtudiant () ;
public Etudiant get (int i) {
return l.get (i) ; }
// Pour l’interface ListModel
public int getSize () {
return l.size () ; }
interface Etudiant { public Object getElementAt (int index) {
public String nom () ; return get (index) ; }
public int moyenne () ; // M´thodes sp´cifiques du mod`le
e e e
public void ajouter (int note) ; public void ajouter (Etudiant e) {
} final int index = l.size () ;
l.add (e) ;
fireIntervalAdded (this, index, index) ;
// Appelle la m´thode intervalAdded() de
e
// chacun des ListDataListener connect´s
e
// a ce ListModel.
`
} }
13. Transparents Java, P.Durif 48 Transparents Java, P.Durif 49
La JList sur une promotion Diagramme d’une instance de
JList Etudiant
class JList_Etudiant extends Les objets listener sont dans un double cadre :
javax.swing.JList {
public JList_Etudiant (Promotion p) {
super (p) ;
setCellRenderer(new EtudiantRenderer()) ;
DoubleClic
setSelectionMode
(javax.swing.
ListSelectionModel.SINGLE_SELECTION) ; Promotion EtudiantRenderer
getSelectionModel()
.addListSelectionListener
(new NouvelleSelection ()) ; JList_Etudiant
this.addMouseListener
(new DoubleClic (this)) ;
DefaultListSelectionModel
}
} NouvelleSelection
Transparents Java, P.Durif 50 Transparents Java, P.Durif 51
Le ListCellRenderer d’´tudiant
e Le contrˆleur NouvelleSelection
o
class EtudiantRenderer extends
En principe on ne devrait pas avoir a ´crire un tel
`e
javax.swing.DefaultListCellRenderer {
listener : une interface classique pr´sente d’une
e
part la liste et d’autre part des boutons
public java.awt.Component
permettant chacun d’effectuer une action sur les
getListCellRendererComponent
´l´ments actuellement s´lectionn´s, par exemple :
ee e e
(javax.swing.JList list,
´diter, supprimer, . . .
e
Object value,
int index,
boolean isSelected, On imprime un message a chaque changement de
`
boolean cellHasFocus) { s´lection effectu´e par l’utilisateur :
e e
Etudiant e = (Etudiant) value ;
return super.getListCellRendererComponent class NouvelleSelection implements
(list, javax.swing.event.ListSelectionListener {
e.nom () + : + e.moyenne (), public void valueChanged
index, (javax.swing.event.ListSelectionEvent e) {
isSelected, if (! e.getValueIsAdjusting()) {
cellHasFocus System.out.println(S´lection modifi´e);
e e
) ; }
} }
} }
14. Transparents Java, P.Durif 52 Transparents Java, P.Durif 53
Le contrˆleur DoubleClic
o Inhibition des widgets
On veut qu’un double clic avec le bouton gauche de la Une bonne IHM doit guider l’utilisateur : en
souris provoque l’impression dans la console de particulier si certaines actions n’ont pas de sens a
`
l’´l´ment de liste ainsi s´lectionn´ :
ee e e un moment donn´, on doit pouvoir empˆcher
e e
class DoubleClic l’utilisateur de s’en servir.
extends java.awt.event.MouseAdapter {
private JList_Etudiant l ;
public DoubleClic (JList_Etudiant l) { Par exemple, si sous xemacs, le fichier ´dit´ n’a
e e
this.l = l ; } pas ´t´ modifi´ depuis sa derni`re sauvegarde
ee e e
@Override public void mouseClicked alors l’action Save du menu File est inhib´e.
e
(java.awt.event.MouseEvent e) {
if ((e.getModifiers() ==
java.awt.event.InputEvent.BUTTON1_MASK
Regardez vos IHM pr´f´r´es pour voir si elles ont
eee
) e.getClickCount() == 2) {
ce comportement.
final int I=l.locationToIndex(e.getPoint());
if (I != - 1)
System.out.println
(((Promotion) l.getModel()).get(I).nom()); AWT et donc Swing permettent cette inhibition
} } } avec la m´thode setEnabled(boolean)
e
disponible sur tous les widgets.
On remarque avec quelle facilit´ on retrouve l’´tudiant
e e
concern´ par le double-clic (locationToIndex()).
e
Transparents Java, P.Durif 54 Transparents Java, P.Durif 55
Notion de focus clavier focus clavier et JDK 1.4
Le widget qui a le focus (ou point de mire) est
celui qui recevra tous les ´v´nements clavier,
e e
mˆme s’il n’est pas sous la souris.
e
Le JDK 1.4 d´finit un fonctionnement par d´faut
e e
du focus qui devrait ˆtre satisfaisant dans la
e
Au plus un widget, parmi toutes les fenˆtres de
e plupart des cas, il est cependant possible de le
l’application, peut avoir le focus a un moment
` personnaliser simplement grˆce aux m´thodes :
a e
donn´.
e Container.setFocusTraversalKeys()
Container.getFocusTraversalPolicy()
ContainerOrderFocusTraversalPolicy.
En g´n´ral on d´place le focus sur un autre widget
e e e setImplicitDownCycleTraversal(boolean)
– soit par un clic de la souris,
– soit avec la touche tabulation avant pour
avancer sur le prochain widget.
– soit avec la touche tabulation arri`re pour
e Une personnalisation plus pouss´e peut-ˆtre
e e
reculer sur le widget pr´c´dent.
e e obtenue au prix d’une bonne compr´hension du
e
m´canisme de gestion du focus.
e
Une bonne gestion du focus est certainement un
´l´ment d´terminant de l’ergonomie d’une IHM.
ee e
15. Transparents Java, P.Durif 56 Transparents Java, P.Durif 57
javax.swing.Action javax.swing.JScrollPane
C’est une sp´cialisation de ActionListener tr`s
e e On peut mettre un widget, trop grand pour ˆtre
e
pratique quand on veut : compl`tement visible, dans un JScrollPane.
e
– qu’un mˆme listener avec le mˆme intitul´ soit
e e e
accessible de plusieurs mani`res dans l’IHM,
e
– pouvoir d´sactiver/r´activer ce listener de fa¸on
e e c
centralis´e (m´thode setEnabled(boolean)).
e e
On dispose alors d’ascenseurs verticaux et
On peut ajouter une mˆme Action dans un
e horizontaux permettant de faire d´filer le widget.
e
JMenu, un JPopupMenu ou une JToolBar avec
add(Action).
Ceci cr´era automatiquement le JMenuItem ou le
e
JButton correspondant.
Exemple :
JScrollPane scroll =
new JScrollPane (new JList_Etudiant (...)) ;
La classe javax.swing.AbstractAction est une
impl´mentation de Action qui peut facilement
e
ˆtre ´tendue.
e e
Transparents Java, P.Durif 58 Transparents Java, P.Durif 59
javax.swing.JDialog Modalit´ du JDialog
e
Comme son nom l’indique, un JDialog est une En modal (comportement s´quentiel de
e
fenˆtre secondaire permettant a l’utilisateur de
e ` l’utilisateur), n´cessaire quand la r´ponse au
e e
saisir des donn´es, r´pondre a une question, . . ..
e e ` dialogue est indispensable a la suite du
`
d´roulement de l’application. Il faut : cr´er le
e e
dialogue en indiquant qu’il est modal ensuite, a `
chaque fois qu’on rend visible le dialogue,
Un JDialog d´pend toujours d’une fenˆtre qu’on
e e
l’application principale est bloqu´e jusqu’` ce que
e a
appelle son propri´taire (owner).
e
le dialogue soit rendu invisible (voir la m´thode
e
setVisible(boolean) h´rit´e de
e e
java.awt.Component).
Le JDialog subira les mˆmes actions que sa
e
fenˆtre propri´taire, par exemple, si le propri´taire
e e e En non modal (comportement parall`le dee
est iconis´, le JDialog disparaˆ
e ıtra pour l’utilisateur), quand le dialogue contient toujours
r´apparaˆ d`s que son propri´taire sera agrandi.
e ıtre e e une valeur que le programme principal peut
consulter a tout moment (par exemple le dialogue
`
de choix de la couleur du crayon dans un logiciel
de dessin est souvent non modal)
La sp´cificit´ primordiale d’un JDialog est d’ˆtre
e e e
ou non modal. Un JFileChooser est un dialogue tout prˆt pour
e
s´lectionner un fichier.
e
void setFileFilter (FileFilter filter)
16. Transparents Java, P.Durif 60 Transparents Java, P.Durif 61
Composition du JDialog Programmation bas niveau
Pour composer un JDialog on peut utiliser,
Comment un widget est dessin´
e
comme pour les JFrame et les JApplet :
En AWT, c’est la m´thode paint(Graphics) qui
e
fait tout le travail.
– sa m´thode getContentPane() qui renvoie son
e En Swing, la m´thode publique paint(Graphics)
e
panel racine, on peut ensuite y mettre ce que appelle successivement les trois m´thodes
e
l’on veut. protected :
1. paintComponent (Graphics)
2. paintBorder (Graphics)
3. paintChildren (Graphics)
– sa m´thode setContentPane() pour fixer
e
brutalement son panel racine.
Pour modifier l’apparence d’un widget Swing, il
suffit d’en h´riter et de red´finir la m´thode
e e e
paintComponent (Graphics).
Transparents Java, P.Durif 62 Transparents Java, P.Durif 63
java.awt.Graphics Application : BoutonCroix
Tout widget dispose d’un contexte graphique On veut un bouton qui affiche une croix quand il
mat´rialis´ par un objet de type Graphics.
e e est enfonc´. Pour cela on h´rite de JButton et on
e e
red´finit paintComponent() :
e
import java.awt.* ;
On peut demander son Graphics a un widget
` class BX extends javax.swing.JButton {
avec la m´thode : getGraphics().
e public BX (String text) { super (text) ; }
protected void paintComponent (Graphics g) {
if (getModel ().isPressed ()) {
Un Graphics contient les informations de base Rectangle R = g.getClipBounds();
permettant le dessin du widget a l’´cran : l’origine
` e Point O = R.getLocation() ;
de la zone de dessin, sa fenˆtre de d´coupage
e e g.clearRect(O.x, O.y, R.width, R.height);
(clipping), la couleur du crayon, la fonte de g.drawLine(O.x, O.y,
caract`res, . . .
e O.x+R.width, O.y+R.height);
g.drawLine(O.x, O.y+R.height,
O.x+R.width, O.y);
Quelques m´thodes de Graphics : drawLine(),
e } else {
drawString(), setColor(), . . . super.paintComponent (g) ;
}
} }