implémentation d’ihm en java plan avec swing · implémentation d’ihm en java avec swing...
TRANSCRIPT
Implémentation d’IHM en Java avec Swing
Thierry DuvalISTIC / IRISA - [email protected]
GLI
Master 2 Informatique GL, Mitic et Miage
2
Plan
! L’API Swing : Java Foundation Class
! Instancier et organiser des composants graphiques
!Gérer les événements en provenance de l’utilisateur
!Gérer les événements logiciels (cf Java Beans)
! Créer ses propres composants graphiques
! Le « Drag’n Drop » AWT en Java avec Swing
3
Les composants d’IHM des JFC
! Java Foundation Class (JFC) :" nouvel ensemble de composants d'interfaces graphiques, surnommé Swing
" extérieur au JDK 1.1 (package à ajouter)• encore parfois nécessaire de rajouter ce package dans les navigateurs HTML utilisant de vieilles machines virtuelles Java pour des raisons de compatibilité avec de vieux plugins…
" compris dans le JDK depuis la version 1.2" hérite d'AWT
• en particulier pour être capable d’accéder aux ressources graphiques des machines…
" 17 packages dont javax.swing… pour le moment
4
Les JFC (1/2)
! Ensemble de classes écrites suivant le modèle JavaBeans
! Composants d’interfaces « légers » (100 % Java)" sauf pour le dessin effectif des composants…
! Look and Feel programmable :" modèles fournis (Win32, Motif, Mac, Metal)" modèles personnalisables...
! Classes pour déficients (accessibility)" support pour développer des technologies d’assistance" interfaces « alternatives » (braille, …)
5
Les JFC (2/2)
! Architecture MVC :" Vue et Contrôleur sont dans les composants" Modèle associé dans un composant qui implémente l’interface adéquate
" le modèle peut être dérivé ou remplacé…
! Conteneurs avec ascenseurs
! Composants de haut niveau (JList, JTree, JTable)
! Transfert de données (clipboard, drag and drop)
!Graphiques, traitement d’images (API 2D)6
Swing : les trois parties
! Ensemble de composants d’IHM héritant de JComponent
" JButton, JFrame, JTable, ...
! Un ensemble de classes support" ButtonGroup, ImageIcon, DefaultButtonModel, ...
! Un ensemble d’interfaces implémentées par les modèles des composants et les classes support" Icon, ButtonModel, ...
7
Swing (jdk 1.6) : 17 paquetages
! javax.swing! javax.swing.border! javax.swing.colorchooser! javax.swing.event! javax.swing.filechooser! javax.swing.plaf (.basic, .metal, .multi, .synth)! javax.swing.table! javax.swing.text (.html, .html.parser, .rtf)! javax.swing.tree! javax.swing.undo
8
Swing : caractéristiques
! Pluggable Look & Feel
! Extensibilité
! Capture des événements clavier
! Personnalisation des bordures de composants
! Tool tips
! Autoscrolling
! Accessibility support
! Localisation support
9
Les différents types de composants
! Containers de plus haut niveau
! Containers généraux
! Containers spécialisés
! Composants interactifs basiques
! Afficheurs non interactifs
! Afficheurs éditables de données structurées
10
Containers de plus haut niveau
! Ils ne peuvent être « contenus »! IL en faut au moins un par application :
" JApplet
" JFrame
!On peut en utiliser d’autres en plus :" JDialog
" JOptionPane
11
Containers généraux
! Pour regrouper des composants, classique…" JPanel
" JScrollPane
" JSplitPane
" JTabbedPane
" JToolBar
12
Containers spécialisés
! Pour des utilisations particulières…" JInternalFrame
" JDesktopPane
" JLayeredPane
" JRootPane
13
Composants interactifs basiques (1/2)
! Ceux qu’on utilise « tout le temps » !" JButton
" JCheckBox
" JRadioButton
" JMenuItem
" JCheckBoxMenuItem
" JRadioButtonMenuItem
" JToggleButton
" JComboBox
" JList
" JSlider
14
Composants interactifs basiques (2/2)
! Suite…" JTextField
" JPasswordField
" JMenuBar
" JPopupMenu
15
Afficheurs non interactifs
! Pour informer…" JLabel
" JProgressBar
" JToolTip
16
Editeurs de données structurées
! Il faudrait les inventer s’ils n’existaient pas…" JColorChooser
" JFileChooser
" JTable
" JTextArea
" JTree
17
Swing : les composants d’IHM (1/5)
18
Swing : les composants d’IHM (2/5)
# JApplet# JButton# JCheckBox# JCheckBoxMenuItem# JColorChooser# JComponent# JDesktopIcon
# JDesktopPane# JDialog# JFileChooser# JFrame# JInternalFrame# JLabel# JLayeredPane
19
Swing : les composants d’IHM (3/5)
# JList# JMenu# JMenuBar# JMenuItem# JOptionPane# JPanel# JPasswordField
# JPopUpMenu# JProgressBar# JRadioButton# JRadioButtonMenu# JMenuItem# JScrollBar# JScrollPane
20
Swing : les composants d’IHM (4/5)
# JSeparator# JSlider# JSplitPane# JTabbedPane# JTable# JTextArea# JTextPane# JToggleButton
# JToolBar# JTextPane# JToggleButton# JToolTip# JTree# JViewport# JWindow
21
Swing : les composants d’IHM (5/5)
! « Le répertoire du jdk »/demo/jfc/CodePointIM! « Le répertoire du jdk »/demo/jfc/FileChooserDemo! « Le répertoire du jdk »/demo/jfc/Font2DTest! « Le répertoire du jdk »/demo/jfc/Java2D! « Le répertoire du jdk »/demo/jfc/MetalWorks! « Le répertoire du jdk »/demo/jfc/Notepad! « Le répertoire du jdk »/demo/jfc/SampleTree! « Le répertoire du jdk »/demo/jfc/Stylepad! « Le répertoire du jdk »/demo/jfc/SwingApplet! « Le répertoire du jdk »/demo/jfc/SwingSet2! « Le répertoire du jdk »/demo/jfc/SwingSet3! « Le répertoire du jdk »/demo/jfc/TableExample
22
SwingSet2 (1/5)
23
SwingSet2 (2/5)
24
SwingSet2 (3/5)
25
SwingSet2 (4/5)
26
SwingSet2 (5/5)
27
Java2D (1/3)
28
Java2D (2/3)
29
Java2D (3/3)
30
Instanciation et organisation
! Composants logiciels d'interfaces
!Organisation (graphique) des composants
!Gestion de quelques événements
31
Faire une application interactive
! Pour une véritable application (pas une JApplet),placer les composants de dialogue dans une instance de JFrame ou d’une classe dérivée de JFrame :" utiliser un listener à l’écoute des événements susceptibles d’arriver à cette fenêtre principale :• en particulier pour terminer l’application…
" lui ajouter des sous-composants graphiques ...• add (BorderLayout.NORTH, new UnBouton ())
" lui donner une taille :• pack () ou bien setSize (largeur, hauteur)
" lui demander de montrer son contenu :• setVisible (true) // anciennement : show ()
32
Le container de départ : JFrame
! Héritage :" java.lang.Object" java.awt.Component" java.awt.Container" java.awt.Window" java.awt.Frame" javax.swing.JFrame
! Fenêtre de plus haut niveau avec titre et bord
! Est associé par défaut à un BorderLayout…
33
JFrame
import java.awt.Color;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class MyVeryFirstJFrame extends JFrame {
private static final long serialVersionUID = 1L;
class Fermeur extends WindowAdapter {public void windowClosing (WindowEvent e) {
System.exit (0) ;}
}
public MyVeryFirstJFrame () {super ("My Very First JFrame") ;addWindowListener (new Fermeur ()) ;getContentPane ().setBackground (Color.cyan) ;setSize (800, 600) ;setVisible (true) ;
}
public static void main (String argvs []) {new MyVeryFirstJFrame () ;
}
}34
Positionnement : BorderLayout
! Héritage :" java.lang.Object" java.awt.BorderLayout
!Gestionnaire de positionnement à 5 zones :" BorderLayout.NORTH" BorderLayout.SOUTH" BorderLayout.EAST" BorderLayout.WEST" BorderLayout.CENTER
35
JFrame et BorderLayout (1/2)
import java.awt.BorderLayout;import javax.swing.JButton;import javax.swing.JFrame;
public class MyFirstJFrame extends JFrame {
private static final long serialVersionUID = 1L;
public MyFirstJFrame () {super ("My First JFrame") ;addWindowListener (new Fermeur ()) ;getContentPane ().add (BorderLayout.NORTH, new JButton ("North")) ;getContentPane ().add (BorderLayout.SOUTH, new JButton ("South")) ;getContentPane ().add (BorderLayout.EAST, new JButton ("East")) ;getContentPane ().add (BorderLayout.WEST, new JButton ("West")) ;getContentPane ().add (BorderLayout.CENTER, new JButton ("Center")) ;pack () ;setVisible (true) ;
}
public static void main (String argvs []) {new MyFirstJFrame () ;
}
} 36
JFrame et BorderLayout (2/2)
import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;
class Fermeur extends WindowAdapter {
public void windowClosing (WindowEvent e) {System.exit (0) ;
}
}
37
Positionnement : GridLayout
! Héritage :" java.lang.Object" java.awt.GridLayout
!Gestionnaire de positionnement en lignes et colonnes
! Toutes les « cases » sont de taille identique
38
JFrame et GridLayout v1
import java.awt.GridLayout;import javax.swing.JButton;import javax.swing.JFrame;
public class MyJFrameWithGridLayout extends JFrame {
private static final long serialVersionUID = 1L;
public MyJFrameWithGridLayout () {super ("JFrame With GridLayout") ;addWindowListener (new Fermeur ()) ;// rangement en 3 lignes de 2 colonnessetLayout (new GridLayout (3,2)) ;add (new JButton ("1")) ; add (new JButton ("2")) ;add (new JButton ("3")) ; add (new JButton ("4")) ;add (new JButton ("5")) ; add (new JButton ("6")) ;pack () ;setVisible (true) ;
}
public static void main (String argvs []) {new MyJFrameWithGridLayout () ;
}
}
39
JFrame et GridLayout v2
import java.awt.GridLayout;import javax.swing.JButton;import javax.swing.JFrame;
public class MyJFrameWithGridLayout extends JFrame {
private static final long serialVersionUID = 1L;
public MyJFrameWithGridLayout () {super ("JFrame With GridLayout") ;addWindowListener (new Fermeur ()) ;// rangement en 3 lignes de 2 colonnessetLayout (new GridLayout (3,2)) ;add (new JButton ("1")) ; add (new JButton ("2")) ;add (new JButton ("3")) ; add (new JButton ("4")) ;add (new JButton ("5")) ; add (new JButton ("6")) ;setSize (300, 450) ;setVisible (true) ;
}
public static void main (String argvs []) {new MyJFrameWithGridLayout () ;
}
}40
Positionnement : GridBagLayout
!Gestionnaire de positionnement souple :" fait des alignements horizontaux et verticaux" maintient une grille rectangulaire et dynamique de cellules" les contenus ne sont pas forcément de la même taille :
• un composant peut occuper plusieurs cases de la grille
! Chaque composant géré par un GridBagLayout estassocié à une instance de GridBagConstraints quiprécise comment le composant doit être placé dans sa zone d’affichage
41
GridBagConstraints (1/6)
!GridBagConstraints.gridx, GridBagConstraints.gridy" précisent la cellule associée au coin haut gauche de la zone d’affichage du composant
" gridx = 0, gridy = 0 pour la cellule le plus en haut à gauche" utiliser GridBagConstraints.RELATIVE (la valeur par défaut) pour préciser que le composant doit être placéjuste à droite (pour gridx) ou juste en dessous (pour gridy) du composant qui a été ajouté précédemment au container
42
GridBagConstraints (2/6)
!GridBagConstraints.gridwidth,GridBagConstraints.gridheight" précisent le nombre de cellules dans une rangée ou dans une colonne associées à la zone d’affichage du composant
" la valeur par défaut est 1" utiliser GridBagConstraints.REMAINDER pour préciser que le composant doit être le dernier dans sa rangée ou sa colonne
" utiliser GridBagConstraints.RELATIVE pour préciser que le composant doit être le suivant du dernier de sa rangée ou de sa colonne
43
GridBagConstraints (3/6)
!GridBagConstraints.fill" utilisé lorsque la zone d’affichage du composant est plus grande que le composant à y afficher afin de déterminer quand et comment retailler ce composant
" GridBagConstraints.NONE (la valeur par défaut) : pas de retaillage
" GridBagConstraints.HORIZONTAL : agrandit suffisamment le composant en largeur pour remplir horizontalement la zone d’affichage, sans changer sa hauteur
" GridBagConstraints.VERTICAL : dans l’autre dimension …" GridBagConstraints.BOTH : dans les 2 dimensions …
44
GridBagConstraints (4/6)
!GridBagConstraints.ipadx, GridBagConstraints.ipady" précisent les marge internes du composant à afficher àl'intérieur du gestionnaire de positionnement
!GridBagConstraints.insets" précise les marges externes du composant : l’espace minimal entre le composant et les extrémités de sa zone d’affichage
45
GridBagConstraints (5/6)
!GridBagConstraints.anchor" utilisé quand le composant est plus petit que sa zone d’affichage pour déterminer où le placer à l'intérieur de cette zone
" valeurs possibles :• GridBagConstraints.CENTER (la valeur par défaut)• GridBagConstraints.NORTH, GridBagConstraints.NORTHEAST• GridBagConstraints.EAST, GridBagConstraints.SOUTHEAST• GridBagConstraints.SOUTH, GridBagConstraints.SOUTHWEST• GridBagConstraints.WEST, GridBagConstraints.NORTHWEST
46
GridBagConstraints (6/6)
!GridBagConstraints.weightx,GridBagConstraints.weighty" utilisés pour déterminer comment répartir l’espace, et ainsi déterminer le comportement lors d’un retaillage
" à moins de préciser un poids pour au moins un composant dans une ligne (weightx) et une colonne (weighty), tous les composants se regroupent au centre de leur container :• c’est parce que lorsque le poids est 0 (la valeur par défaut), le GridBagLayout place tout l’espace superflu entre sa grille de cellules et les extrémités du container
47
GridBag… Layout et Constraints (1/6)
import java.awt.GridBagConstraints;import java.awt.GridBagLayout;
import javax.swing.JButton;import javax.swing.JFrame;
public class MyJFrameWithGridBagLayout extends JFrame {
private static final long serialVersionUID = 1L;
protected void makebutton (String name,GridBagLayout gridbag,GridBagConstraints c) {
JButton button = new JButton (name) ;gridbag.setConstraints (button, c) ;add (button) ;
}
48
GridBag… Layout et Constraints (2/6)
public MyJFrameWithGridBagLayout () {super ("GridBag Layout Example") ;GridBagLayout gridbag = new GridBagLayout () ;GridBagConstraints c = new GridBagConstraints () ;
setLayout (gridbag) ;
c.fill = GridBagConstraints.BOTH ;c.weightx = 1.0 ;makebutton ("Button1", gridbag, c) ;makebutton ("Button2", gridbag, c) ;makebutton ("Button3", gridbag, c) ;
49
GridBag… Layout et Constraints (3/6)
c.gridwidth = GridBagConstraints.REMAINDER ; //end rowmakebutton ("Button4", gridbag, c) ;
c.weightx = 0.0; //reset to the defaultmakebutton ("Button5", gridbag, c) ; //another row
c.gridwidth = GridBagConstraints.RELATIVE ; //next-to-last in rowmakebutton ("Button6", gridbag, c) ;
c.gridwidth = GridBagConstraints.REMAINDER ; //end rowmakebutton ("Button7", gridbag, c) ;
50
GridBag… Layout et Constraints (4/6)
c.gridwidth = 1 ; //reset to the defaultc.gridheight = 2 ;c.weighty = 1.0 ;makebutton ("Button8", gridbag, c) ;
c.weighty = 0.0 ; //reset to the defaultc.gridwidth = GridBagConstraints.REMAINDER ; //end rowc.gridheight = 1 ; //reset to the defaultmakebutton ("Button9", gridbag, c) ;makebutton ("Button10", gridbag, c) ;
}
51
GridBag… Layout et Constraints (5/6)
public static void main (String args []) {JFrame jf = new MyJFrameWithGridBagLayout () ;jf.addWindowListener (new Fermeur ()) ;jf.pack () ;jf.setVisible (true) ;
}
}
52
GridBag… Layout et Constraints (6/6)
53
Positionnement : les possibilités
! FlowLayout
! BorderLayout
! GridLayout
! GridBagLayout
! CardLayout
! BoxLayout
! AbsoluteLayout
! null (pas de Layout)
54
Le container le plus simple : JPanel
! Héritage :" java.lang.Object" java.awt.Component" java.awt.Container" javax.swing.JComponent" Javax.swing.JPanel
! C’est le plus simple des « containers »
!On peut y mettre d’autres composants, y compris d’autres « panels »
! Est associé par défaut à un FlowLayout
55
JPanel et FlowLayout version 1
import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;
public class MyFirstPanelInAJFrame extends JFrame {
private static final long serialVersionUID = 1L;
public MyFirstPanelInAJFrame () {super () ;addWindowListener (new Fermeur ()) ;JPanel p = new JPanel () ;p.add (new JButton ("1")) ; p.add (new JButton ("2")) ;p.add (new JButton ("3")) ; p.add (new JButton ("4")) ;p.add (new JButton ("5")) ; p.add (new JButton ("6")) ;add (p) ;pack () ;setVisible (true) ;
}
public static void main (String argvs []) {new MyFirstPanelInAJFrame () ;
}
}56
JPanel et FlowLayout version 2
import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;
public class MySecondPanelInAFrame extends JPanel {
private static final long serialVersionUID = 1L;
public MySecondPanelInAFrame () {add (new JButton ("1")) ; add (new JButton ("2")) ;add (new JButton ("3")) ; add (new JButton ("4")) ;add (new JButton ("5")) ; add (new JButton ("6")) ;
}
public static void main (String argvs []) {JFrame jf = new JFrame ("My Second JPanel In A Frame") ;jf.addWindowListener (new Fermeur ()) ;JPanel jp = new MySecondPanelInAFrame () ;jf.getContentPane ().add (jp) ;jf.pack () ;jf.setVisible (true) ;
}
}
57
Le container JApplet
! Héritage :" java.lang.Object" java.awt.Component" java.awt.Container" java.awt.Panel" java.applet.Applet" javax.swing.JApplet
! Destinée à être incorporée dans une autre application
! Propriétés (IHM) similaires à celles d’un JFrame58
JApplet et html…
<html><head><title>MyVeryFirstApplet</title></head>
<body><applet code="MyVeryFirstApplet.class" width=300 height=200></applet></body></html>
59
JApplet et pb de couleur…
import java.awt.Color;
import javax.swing.JApplet;
public class MyVeryFirstJApplet extends JApplet {
private static final long serialVersionUID = 1L;
public MyVeryFirstJApplet () {setSize (400, 300) ;setBackground (Color.yellow) ;
}
}
60
JApplet et couleur OK…
import java.awt.Color;
import javax.swing.JApplet;
public class MyVeryFirstJAppletBis extends JApplet {
private static final long serialVersionUID = 1L;
public MyVeryFirstJAppletBis () {setSize (400, 300) ;getContentPane ().setBackground (Color.yellow) ;
}
}
61
JApplet et BorderLayout
import java.awt.BorderLayout;import javax.swing.JApplet;import javax.swing.JButton;
public class MyJAppletWithBorderLayout extends JApplet {
private static final long serialVersionUID = 1L;
public MyJAppletWithBorderLayout () {getContentPane ().add (BorderLayout.NORTH, new JButton ("North")) ;getContentPane ().add (BorderLayout.SOUTH, new JButton ("South")) ;getContentPane ().add (BorderLayout.EAST, new JButton ("East")) ;getContentPane ().add (BorderLayout.WEST, new JButton ("West")) ;getContentPane ().add (BorderLayout.CENTER, new JButton ("Center")) ;
}
}
62
JApplet et FlowLayout
import java.awt.FlowLayout;import javax.swing.JApplet;import javax.swing.JButton;
public class MyJAppletWithFlowLayout extends JApplet {
private static final long serialVersionUID = 1L;
public MyJAppletWithFlowLayout () {getContentPane ().setLayout (new FlowLayout()) ;getContentPane ().add (new JButton ("1")) ;getContentPane ().add (new JButton ("2")) ;getContentPane ().add (new JButton ("3")) ;getContentPane ().add (new JButton ("4")) ;getContentPane ().add (new JButton ("5")) ;getContentPane ().add (new JButton ("6")) ;
}
}
63
JApplet et GridLayout
import java.awt.GridLayout;
import javax.swing.JApplet;import javax.swing.JButton;
public class MyJAppletWithGridLayout extends JApplet {
private static final long serialVersionUID = 1L;
public MyJAppletWithGridLayout () {getContentPane ().setLayout (new GridLayout(3, 2)) ;getContentPane ().add (new JButton ("1")) ;getContentPane ().add (new JButton ("2")) ;getContentPane ().add (new JButton ("3")) ;getContentPane ().add (new JButton ("4")) ;getContentPane ().add (new JButton ("5")) ;getContentPane ().add (new JButton ("6")) ;
}
}64
Pour dessiner dans un objet
! En général on crée un nouveau type d’objet par dérivation d’un objet graphique
! Il faut redéfinir la méthode : void paint (Graphics g)
" Ou : paintComponent, paintBorder, paintChildren, paintImmediately, paintComponents, paintAll, …
! g est le contexte graphique, capable de faire des dessins
! La méthode paint peut être appelée explicitement àl’aide de la méthode : void repaint ()
! À l’intérieur de la méthode paint redéfinie, on appelle souvent la méthode paint de l’ancêtre…
65
Les événements depuis le JDK 1.1
! Les événements sont (depuis la version 1.1) générés par des sources :" un ou plusieurs « composant(s) à l’écoute » (listeners) peuvent demander à être notifiés de l’apparition d’un événement particulier en provenance d’une source particulière
" les gestionnaires d’événements peuvent être instances de n’importe quelle classe ...
" ... à condition que la classe en question implémente une interface de composant à l’écoute d’événement : ses instances peuvent alors gérer des événements
66
La gestion des événements
! Dans une classe désirant gérer des événements :" déclarer une classe à l’écoute d’événements" implémenter le code correspondant à l’interface choisie
class UnBoutonListener implements ActionListener {public void actionPerformed (ActionEvent e) {...
}}
" attacher une instance de cette classe à au moins un composant
b = new JButton ("Appuie !! Touche : " + nbTouches + " fois") ;b.addActionListener (new UnBoutonListener ()) ;
67
Une 1ère JApplet interactive
import java.awt.event.ActionListener;import java.awt.event.ActionEvent;import javax.swing.JApplet;import javax.swing.JButton;
public class MyJAppletWithAJButton extends JApplet {
private static final long serialVersionUID = 1L;
protected JButton b ;protected int nbTouches ;
public MyJAppletWithAJButton () {nbTouches = 0 ;b = new JButton ("Appuie !!") ;b.addActionListener (new UnBoutonListener ()) ;getContentPane ().add (b) ;
}
class UnBoutonListener implements ActionListener {public void actionPerformed (ActionEvent e) {nbTouches ++ ; b.setText ("Touché : " + nbTouches + " fois") ;
}}
}
68
Une 1ère application interactive (1/2)
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;
import javax.swing.JButton;import javax.swing.JFrame;
public class MyJFrameWithAJButton extends JFrame {
private static final long serialVersionUID = 1L;
protected JButton b ;protected int nbTouches ;
public MyJFrameWithAJButton () {super ("My First JFrame") ;nbTouches = 0 ;b = new JButton ("Appuie !!") ;b.addActionListener (new UnBoutonListener ()) ;getContentPane ().add (b) ;pack () ;setVisible (true) ;
}
69
Une 1ère application interactive (2/2)
class UnBoutonListener implements ActionListener {public void actionPerformed (ActionEvent e) {nbTouches ++ ; b.setText ("Touché : " + nbTouches + " fois") ;
}}
public static void main (String argvs []) {new MyJFrameWithAJButton () ;
}
}
70
Listeners et adapters (1/3)
! Certaines interfaces de listeners possèdent de nombreuses méthodes à définir…
!On peut donc parfois avantageusement utiliser plutôt des adapters, classes abstraites (non instanciables) qui implémentent des listeners avec des méthodes qui ne font rien
!On peut alors ne redéfinir que certaines méthodes, en héritant de ces adapters :" attention cependant à ne pas se tromper de noms de méthodes lors des redéfinitions !
71
Listeners et adapters (2/3)interface listener classe adapter méthodes
ActionListener actionPerformed (ActionEvent)
AdjustmentListener adjustmentValueChanged (AdjustmentEvent)
AWTEventListener eventDispatched (AWTEvent)
ComponentListener ComponentAdapter componentHidden (ComponentEvent)componentMoved (ComponentEvent)componentResized (ComponentEvent)componentShown (ComponentEvent)
ContainerListener ContainerAdapter componentAdded (ContainerEvent)componentRemoved (ContainerEvent)
FocusListener FocusAdapter focusGained (FocusEvent)focusLost (FocusEvent)
HierarchyBoundsListener HierarchyBoundsAdapter ancestorMoved (HierarchyEvent)ancestorResized (HierarchyEvent)
HierarchyListener hierarchyChanged (HierarchyEvent)
InputMethodListener caretPositionChanged (InputMethodEvent)inputMethodTextChanged (InputMethodEvent)
72
Listeners et adapters (3/3)interface listener classe adapter méthodes
ItemListener itemStateChanged (ItemEvent)
KeyListener KeyAdapter keyPressed (KeyEvent)keyReleased (KeyEvent)keyTyped (KeyEvent)
MouseListener MouseAdapter mouseClicked (MouseEvent)mouseEntered (MouseEvent)mouseExited (MouseEvent)mousePressed (MouseEvent)mouseReleased (MouseEvent)
MouseMotionListener MouseMotionAdapter mouseDragged (MouseEvent)mouseMoved (MouseEvent)
TextListener textValueChanged (TextEvent)
WindowListener WindowAdapter windowActivated (WindowEvent)windowClosed (WindowEvent)windowClosing (WindowEvent)windowDeactivated (WindowEvent)windowDeiconified (WindowEvent)windowIconified (WindowEvent)windowOpened (WindowEvent)
73
Les types d’événements
AWTEvent
ContainerEvent
FocusEvent
ItemEvent
ComponentEvent
AdjustmentEvent
InputMethodEvent
ActionEvent
TextEvent
InvocationEvent
HierarchyEvent
InputEvent
MouseEventKeyEvent
WindowEvent
PaintEvent
74
Production d’événements (partielle)
ComposantAWT action adjustment component container focus item key mouse mouse motion text window
Button oui oui oui oui oui ouiCanvas oui oui oui oui ouiCheckbox oui oui oui oui oui oui
CheckboxMenuItem ouiChoice oui oui oui oui oui oui
Component oui oui oui oui ouiContainer oui oui oui oui oui ouiDialog oui oui oui oui oui oui ouiFrame oui oui oui oui oui oui ouiLabel oui oui oui oui ouiList oui oui oui oui oui oui oui
MenuItem ouiPanel oui oui oui oui oui
Scrollbar oui oui oui oui oui oui ouiScrollPane oui oui oui oui ouiTextArea oui oui oui oui oui oui oui
TextComponent oui oui oui oui oui ouiTextField oui oui oui oui oui oui ouiWindow oui oui oui oui oui oui oui
Types d'événements susceptibles d'être générés
75
Gestion des événements
! Chaque méthode de gestion d’événement est paramétrée par l’événement à gérer
! Parfois (souvent ?) on peut se passer d’utiliser cet événement
! Parfois il est indispensable de l’interroger pour obtenir des informations relatives à la façon dont il a été produit :" instant de production" composant source" état des modifieurs associés à l’événement" position relative à la source (pour certains types)" …
76
Méthodes d’InputEvent (1/2)
! public void consume () :" consomme l’événement de sorte qu’il ne sera pas traité de la façon habituelle par sa source
! public boolean isConsumed () :" retourne si cet événement a été consommé
! public int getModifiers () :" retourne l’état du « modifieur » pour cet événement (bouton1, shift, ...)
! public long getWhen () :" retourne l’estampille temporelle de l’événement
77
Méthodes d’InputEvent (2/2)
! public boolean isAltDown () :" retourne si la touche Alt était enfoncée ...
! public boolean isControlDown () :" ...
! public boolean isMetaDown () :" ...
! public boolean isShiftDown () :" ...
! public String paramString () :" ?
78
Méthodes de MouseEvent (1/2)
! Celles d’InputEvent (dont il hérite)
! public Point getPoint () :
" retourne la position du point origine de l’événement relative à son composant source
! public int getX () :
" retourne la position en x de l’événement relative à son composant source
! public int getY ()
79
Méthodes de MouseEvent (2/2)
! public int getClickCount () :
" retourne le nombre de clicks associé à cet événement
! public boolean isPopupTrigger () :" retourne si oui ou non cet événement est le « déclencheur de PopUp » pour cette plate-forme (?)
! public synchronized void translatePoint (int, int) :" translate les coordonnées du point de l’événement ...
80
Les événements : des points (1/4)
81
Les événements : des points (2/4)
import java.awt.Color;import java.awt.Graphics;import java.awt.Point;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;
import javax.swing.JApplet;
class SpotListener extends MouseAdapter {
MySpots _theSpots ;
SpotListener (MySpots theSpot) {_theSpots = theSpot ;
}
public void mouseClicked (MouseEvent e) {_theSpots.addSpot (e.getPoint ()) ;
}
}
82
Les événements : des points (3/4)
public class MySpots extends JApplet {
private static final long serialVersionUID = 1L;
final int MAXSPOTS = 10 ;Point spots [] ;int currspots ;
public MySpots () {spots = new Point [MAXSPOTS] ;currspots = 0 ;addMouseListener (new SpotListener (this)) ;setBackground (Color.white) ;
}
83
Les événements : des points (4/4)
void addSpot (Point p) {if (currspots < MAXSPOTS) {spots [currspots] = p ;currspots ++ ;repaint () ;
} else {System.out.println ("Too many spots.") ;
}}
public void paint (Graphics g) {g.setColor (Color.blue) ;for (int i = 0 ; i < currspots ; i++) {g.fillOval (spots [i].x - 10, spots [i].y - 10, 20, 20) ;
}}
}84
Les événements : des cercles (1/9)
85
Les événements : des cercles (2/9)
import java.awt.Color;import java.awt.Graphics;import java.awt.Point;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseMotionAdapter;import javax.swing.JApplet;
public class MyCircles extends JApplet {
private static final long serialVersionUID = 1L;
86
Les événements : des cercles (3/9)
class CircleListener extends MouseAdapter {
public void mousePressed (MouseEvent e) {beginCircle (e.getPoint ()) ;
}
public void mouseReleased (MouseEvent e) {endCircle (e.getPoint ()) ;
}
}
87
Les événements : des cercles (4/9)
class CircleMotionListener extends MouseMotionAdapter {
public void mouseDragged (MouseEvent e) {motionCircle (e.getPoint ()) ;
}
}
final int MAXCIRCLES = 10 ;Point circles [] ;int radius [] ;int currentCircle ;int nbCircles ;CircleListener aCL ;CircleMotionListener aCML ;
88
Les événements : des cercles (5/9)
public MyCircles () {circles = new Point [MAXCIRCLES] ;radius = new int [MAXCIRCLES] ;currentCircle = 0 ;nbCircles = 0 ;aCL = new CircleListener () ;aCML = new CircleMotionListener () ;addMouseListener (aCL) ;addMouseMotionListener (aCML) ;setBackground (Color.white) ;
}
89
Les événements : des cercles (6/9)
void beginCircle (Point p) {circles [currentCircle] = p ;radius [currentCircle] = 0 ;nbCircles ++ ;
}
void motionCircle (Point p) {int dx = circles [currentCircle].x - p.x ;int dy = circles [currentCircle].y - p.y ;int oldRadius = radius [currentCircle] ;radius [currentCircle] = (int)Math.sqrt (dx * dx + dy * dy) ;int maxRadius = Math.max (oldRadius, radius [currentCircle]) ;repaint (circles [currentCircle].x - maxRadius,
circles [currentCircle].y - maxRadius,2 * maxRadius, 2 * maxRadius) ;
}90
Les événements : des cercles (7/9)
void endCircle (Point p) {motionCircle (p) ;if (radius [currentCircle] != 0) {currentCircle ++ ;if (nbCircles == MAXCIRCLES) {removeMouseListener (aCL) ;removeMouseMotionListener (aCML) ;
}} else {
nbCircles -- ;}
}
91
Les événements : des cercles (8/9)
public void paint (Graphics g) {g.setColor (Color.blue) ;for (int i = 0 ; i < nbCircles ; i++) {g.fillOval (circles [i].x - radius [i], circles [i].y - radius [i],
2 * radius [i], 2 * radius [i]) ;}
}}
92
Les événements : des cercles (9/9)
! Dans cet exemple, les listeners sont internes àl’application :" ils n’ont pas besoin d’être paramétrés par l’application avec laquelle on veut interagir
" les méthodes des listeners ont le droit de directement invoquer les bonnes méthodes du composant à l’intérieur duquel ils ont été instanciés
93
Listeners ou adapters ? (1/3)
class CircleListener implements MouseListener {
public void mousePressed (MouseEvent e) {beginCircle (e.getPoint ()) ;
}
public void mouseReleased (MouseEvent e) {endCircle (e.getPoint ()) ;
}
public void mouseClicked (MouseEvent e) { }
public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
}
94
Listeners ou adapters ? (2/3)
class CircleMotionListener implements MouseMotionListener {
public void mouseDragged (MouseEvent e) {motionCircle (e.getPoint ()) ;
}
public void mouseMoved (MouseEvent e) { }
}
95
Listeners ou adapters ? (3/3)
! Dans ce premier cas, rien à changer dans le restant du code, car sont fonctionnellement équivalents :" CircleListener implémente MouseListener et
CircleMotionListener implémente MouseMotionListener
" CircleListener hérite de MouseAdapter etCircleMotionListener hérite de MouseMotionAdapter
!On peut même mélanger listeners et adapters :" CircleListener implémente MouseListener et
CircleMotionListener hérite de MouseMotionAdapter
" CircleListener hérite de MouseAdapter etCircleMotionListener implémente MouseMotionListener
96
Une seule classe de listeners (1/4)
class CircleListenerAndMotionListener implements MouseListener,MouseMotionListener {
public void mousePressed (MouseEvent e) {beginCircle (e.getPoint ()) ;
}public void mouseReleased (MouseEvent e) {endCircle (e.getPoint ()) ;
}public void mouseClicked (MouseEvent e) { }public void mouseEntered (MouseEvent e) { }public void mouseExited (MouseEvent e) { }public void mouseDragged (MouseEvent e) {motionCircle (e.getPoint ()) ;
}public void mouseMoved (MouseEvent e) { }
}
97
Une seule classe de listeners (2/4)
class CircleListenerAndMotionListener extends MouseMotionAdapterimplements MouseListener {
public void mousePressed (MouseEvent e) {beginCircle (e.getPoint ()) ;
}public void mouseReleased (MouseEvent e) {endCircle (e.getPoint ()) ;
}public void mouseClicked (MouseEvent e) { }public void mouseEntered (MouseEvent e) { }public void mouseExited (MouseEvent e) { }public void mouseDragged (MouseEvent e) {motionCircle (e.getPoint ()) ;
}}
98
Une seule classe de listeners (3/4)
class CircleListenerAndMotionListener extends MouseAdapterimplements MouseMotionListener {
public void mousePressed (MouseEvent e) {beginCircle (e.getPoint ()) ;
}public void mouseReleased (MouseEvent e) {endCircle (e.getPoint ()) ;
}public void mouseDragged (MouseEvent e) {motionCircle (e.getPoint ()) ;
}public void mouseMoved (MouseEvent e) { }
}
99
Une seule classe de listeners (4/4)
! Intérêt de fusionner ainsi plusieurs listeners :" quand il y a des données à partager entre les différents listeners et que ces listeners ne sont pas à l’intérieur d’une même classe ou bien qu’on ne veut pas mettre de telles données dans cette classe
! Dans les 3 cas, le code de l’application est modifié : CircleListenerAndMotionListener aCLandML ;…addMouseListener (aCLandML) ;addMouseMotionListener (aCLandML) ;…removeMouseListener (aCLandML) ;removeMouseMotionListener (aCLandML) ;
100
Mieux gérer les objets graphiques
! Ne pas gérer explicitement une liste de dessins! Créer un nouveau type de composant graphique
" Redéfinir sa façon de se dessiner
! Créer ainsi des composants graphiques! Laisser le container gérer partiellement les objets
101
Des cercles, v2 (1/7)
import java.awt.Color;import java.awt.Graphics;import java.awt.Point;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseMotionAdapter;
import javax.swing.JApplet;import javax.swing.JPanel;
class MyPanelForCircles extends JPanel {
private static final long serialVersionUID = 1L;
102
Des cercles, v2 (2/7)
class CircleListener extends MouseAdapter {
public void mousePressed (MouseEvent e) {beginCircle (e.getPoint ()) ;
}
public void mouseReleased (MouseEvent e) {endCircle (e.getPoint ()) ;
}}
class CircleMotionListener extends MouseMotionAdapter {
public void mouseDragged (MouseEvent e) {motionCircle (e.getPoint ()) ;
}}
103
Des cercles, v2 (3/7)
final int MAXCIRCLES = 10 ;Point currentCenter ;int currentRadius ;int nbCircles ;Circle currentCircle ;CircleListener aCL ;CircleMotionListener aCML ;
public MyPanelForCircles () {nbCircles = 0 ;aCL = new CircleListener () ;aCML = new CircleMotionListener () ;addMouseListener (aCL) ;addMouseMotionListener (aCML) ;setBackground (Color.white) ;setLayout (null) ;
}
104
Des cercles, v2 (4/7)
void beginCircle (Point p) {currentCenter = p ;currentRadius = 0 ;currentCircle = new Circle () ;add (currentCircle) ;nbCircles ++ ;System.out.println ("création du cercle numéro " + nbCircles) ;
}
void motionCircle (Point p) {int dx = currentCenter.x - p.x ;int dy = currentCenter.y - p.y ;currentRadius = (int)Math.sqrt (dx * dx + dy * dy) ;currentCircle.setBounds (currentCenter.x - currentRadius,
currentCenter.y - currentRadius,currentRadius*2, currentRadius*2) ;
}
105
Des cercles, v2 (5/7)
void endCircle (Point p) {motionCircle (p) ;if (currentRadius != 0) {if (nbCircles == MAXCIRCLES) {removeMouseListener (aCL) ;removeMouseMotionListener (aCML) ;System.out.println ("l'interactivité est terminée") ;
}} else {remove (currentCircle) ;System.out.println ("le cercle numéro " + nbCircles + " est supprimé");nbCircles -- ;
}}
}106
Des cercles, v2 (6/7)
class Circle extends JPanel {
private static final long serialVersionUID = 1L;
public Circle () {setOpaque (false) ;
}
public void paint (Graphics g) {super.paint (g) ;g.setColor (Color.blue) ;g.fillOval (0, 0, getWidth (), getHeight ()) ;
}
}
107
Des cercles, v2 (7/7)
public class MyCirclesV2 extends JApplet {
private static final long serialVersionUID = 1L;
public MyCirclesV2 () {add (new MyPanelForCircles ()) ;
}
}
108
Autre exemple d’interaction
! Utilisation de quelques composants Swing :" JLabel
" JTextArea
" JScrollBar
" JScrollPane
! Évolution dynamique de l’IHM selon les interactions
!Montre comment relier des composants d’IHM
!Montre l’intérêt des IHM dynamiques
109
Le composant JLabel
! Héritage :" java.lang.Object" java.awt.Component" java.awt.Container" javax.swing.JComponent" javax.swing.JLabel
! Sert à afficher du texte dans une zone
! Ce texte est en lecture seule, et n’est donc pas éditable directement par l’utilisateur
! Il est possible de l’éditer par programmation... 110
Le composant JTextArea
! Héritage :" java.lang.Object" java.awt.Component" java.awt.Container" javax.swing.JComponent" javax.swing.text.JTextComponent" javax.swing.JTextArea
! Zone de texte multi-ligne :" peut être utilisée pour de l’édition de texte" peut également être utilisée en « lecture seule »
111
Le composant JScrollBar
! Héritage :" java.lang.Object" java.awt.Component" java.awt.Container" javax.swing.JComponent" javax.swing.JScrollBar
! Permet de saisir une valeur dans un intervalle
! Fournit ainsi un guidage implicite pour l’utilisateur
112
Le composant JScrollPane
! Héritage :" java.lang.Object" java.awt.Component" java.awt.Container" javax.swing.JComponent" javax.swing.JScrollPane
! Fournit une vue « srcollable » d’un JComponent
!Gère un « viewport » et d’éventuelles « scrollbars »
113
MyScrolling.java (1/3)
import java.awt.FlowLayout;import java.awt.event.AdjustmentEvent;import java.awt.event.AdjustmentListener;
import javax.swing.JApplet;import javax.swing.JLabel;import javax.swing.JScrollBar;import javax.swing.JScrollPane;import javax.swing.JTextArea;
public class MyScrolling extends JApplet {
private static final long serialVersionUID = 1L;
JLabel label ;JScrollBar barre ;JTextArea zone ;JScrollPane vue ;
114
MyScrolling.java (2/3)
public MyScrolling () {getContentPane ().setLayout (new FlowLayout ()) ;barre = new JScrollBar () ;getContentPane ().add (barre) ;barre.setOrientation (JScrollBar.HORIZONTAL) ;barre.setUnitIncrement (2) ;barre.setVisibleAmount (1) ;barre.setBlockIncrement (5) ;barre.setMinimum (1) ;barre.setMaximum (21) ;barre.setValue (10) ; // à faire après les incrémentsbarre.addAdjustmentListener (new MyBarreListener ()) ;label = new JLabel () ;label.setText ("" + barre.getValue ()) ;getContentPane ().add (label) ;
115
MyScrolling.java (3/3)
zone = new JTextArea ("Zone de texte : ", barre.getValue (), 30) ;zone.setEnabled (true) ;vue = new JScrollPane () ;vue.setViewportView (zone) ;getContentPane ().add (vue) ;
}
class MyBarreListener implements AdjustmentListener {public void adjustmentValueChanged (AdjustmentEvent e) {label.setText ("" + barre.getValue ()) ;zone.setRows (barre.getValue ()) ;zone.setEnabled (true) ;
}}
}116
Le graphisme
! Les dessins :" lignes, rectangles, polygones, ovales, arcs
! Les textes
! Les couleurs
117
Une applet : le fichier HTML
<HTML><HEAD><TITLE>Lines</TITLE></HEAD><BODY><P><APPLET CODE="MyLine.class" WIDTH=200 HEIGHT=150></APPLET></BODY></HTML>
118
Une applet : le fichier MyLine.java
import java.awt.Graphics ;import javax.swing.JApplet;
public class MyLine extends JApplet {
private static final long serialVersionUID = 1L;
public void paint (Graphics g) {g.drawLine (25, 25, 75, 75) ;
}}
119
Objets graphiques (1/3)
import java.awt.Color;import java.awt.Graphics;import java.awt.Polygon;
import javax.swing.JApplet;
public class MyGraphicExamples extends JApplet {
private static final long serialVersionUID = 1L;
120
Objets graphiques (2/3)
public void paint (Graphics g) {g.drawArc (235, 120, 60, 60, 90, 270) ; g.fillArc (335, 120, 60, 60, 90, 270) ;g.setColor (Color.blue) ;g.drawOval (20, 120, 60, 60) ; g.fillOval (120, 120, 100, 60) ;g.setColor (Color.red) ;int x [] = { 39, 94, 97, 142, 53, 58, 26 } ;int y [] = { 33, 74, 36, 70, 108, 80, 106 } ;int pts = x.length ; Polygon poly = new Polygon (x, y, pts) ;g.fillPolygon (poly) ;g.setColor (Color.yellow) ;g.draw3DRect (20, 220, 60, 60, true) ;g.draw3DRect (120, 220, 60, 60, false) ;g.fill3DRect (220, 220, 60, 60, true) ;g.fill3DRect (320, 220, 60, 60, false) ;
}}
121
Objets graphiques (3/3)
122
Textes
import java.awt.Font;import java.awt.Graphics;import javax.swing.JApplet;
public class MyFonts extends JApplet {
public void paint (Graphics g) {Font f = new Font ("TimesRoman", Font.PLAIN, 18) ;Font fb = new Font ("TimesRoman", Font.BOLD, 18) ;Font fbi = new Font ("TimesRoman", Font.BOLD + Font.ITALIC, 18) ;g.setFont (f) ;g.drawString ("This is a plain font", 10, 25) ;g.setFont (fb) ;g.drawString ("This is a bold font", 10, 50) ;g.setFont (fbi) ;g.drawString ("This is a bold italic font", 10, 100) ;
}}
123
Couleurs (1/2)
!Modèle RGB par défaut
! La plupart des autres modèles via la classe ColorSpace
124
Couleurs (2/2)
import java.awt.Color;import java.awt.Graphics;import javax.swing.JApplet;
public class MyColors extends JApplet {
public void paint (Graphics g) {int rval, gval, bval ;for (int j = 30 ; j < (this.getSize ().height - 25) ; j += 30) {for (int i = 5 ; i < (this.getSize ().width - 25) ; i += 30) {rval = (int)Math.floor (Math.random () * 256) ;gval = (int)Math.floor (Math.random () * 256) ;bval = (int)Math.floor (Math.random () * 256) ;g.setColor (new Color (rval,gval,bval)) ;g.fillRect (i, j, 25, 25) ;g.setColor (Color.black) ;g.drawRect (i-1, j-1, 25, 25) ;
}}
}}
125
Autre réceptacle : JDialog
! Héritage :" java.lang.Object" java.awt.Component" java.awt.Container" java.awt.Window" java.awt.Dialog" javax.swing.JDialog
! Fenêtre de plus haut niveau avec titre et bord! Possède par défaut un BorderLayout
! Est propriété d’une autre fenêtre (lancé par)! Peut être modale :
" Bloque alors les entrées de son propriétaire126
JDialog (1/4)
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;
import javax.swing.JButton;import javax.swing.JDialog;import javax.swing.JFrame;
public class MyJFrameWithJDialog extends JFrame {
private static final long serialVersionUID = 1L;
public static void main (String args []) {new MyJFrameWithJDialog () ;
}
127
JDialog (2/4)
public MyJFrameWithJDialog () {super ("Essai de JDialog") ;addWindowListener (new Fermeur ()) ;JDialog jd = new JDialog (this, "JDialog modal", true) ;JButton ouvrir = new JButton ("Ouvrir un JDialog") ;ouvrir.addActionListener (new OuvrirListener (jd)) ;getContentPane ().add (ouvrir) ;JButton fermer = new JButton ("Fermer cette fenetre") ;fermer.addActionListener (new FermerListener (jd)) ;jd.getContentPane ().add (fermer) ;jd.setSize (200, 100) ;setSize (200, 100) ;setVisible (true) ;
}
}128
JDialog (3/4)
class OuvrirListener implements ActionListener {
JDialog jd ;
public OuvrirListener (JDialog jd) {this.jd = jd ;
}
public void actionPerformed (ActionEvent ae) {jd.setVisible (true) ;
}
}
129
JDialog (4/4)
class FermerListener implements ActionListener {
JDialog jd ;
public FermerListener (JDialog jd) {this.jd = jd ;
}
public void actionPerformed (ActionEvent ae) {jd.dispose () ;
}
}
130
Les composants logiciels en Java
! Le modèle composant logiciel :" évolution du modèle objet" schéma général d’architecture logicielle" ensemble de règles d’écriture du code" modules manipulables par les générateurs de code
! Java propose les Java Beans
131
Caractéristiques du modèle composant logiciel
! Portabilité (Write Once, Run Anywhere)! Personnalisation (Customization/GUI Buildersupport)
! Autodocumentation (Reflection/Introspection)! Propriétés (Properties/GUI Merging)! Evénements (Events Handling/Communication)! Sauvegarde (Serialization/Persistence)! Interopérabilité (ActiveX, OpenDoc, OLE, ...)
132
Architecture interne du modèle composant logiciel
! Evénements (Events)!Objet (EventObject)! Récepteur (Event listeners)! Emetteurs (Events sources)! Propriétés : état de l’objet (Properties)!Observateurs (accessors, getters)!Modificateurs (mutators, setters)!Méthodes (Methods)
133
Architecture générale du modèle composant logiciel
! Package : regroupement de l'ensemble des classes relatives à un composant, dans un fichier .jar
! BeanInfo : objet optionnel permettant l'introspection! Customizer(s) : objet(s) optionnel(s) permettant la consultation et la modification des propriétés
!MANIFEST : fichier descripteur du paquetage! Certificat : fichier optionnel d'authentification des classes du paquetage
! Containers/BeanContexts : réceptacles de composants
134
Le modèle composant logiciel
135
Exemple : SimpleBean v1
! SimpleBeanV1 hérite de javax.swing.JPanel
! SimpleBeanV1 implémente java.io.serializable
!On lui adjoint un Manifest : SimpleBeanV1.manifest
!On compile et on crée le composant
136
SimpleBeanV1.java
import java.awt.Color;import java.io.Serializable ;
import javax.swing.JPanel;
public class SimpleBeanV1 extends JPanel implements Serializable {
private static final long serialVersionUID = 1L;
public SimpleBeanV1 () {setSize (200,100) ;setPreferredSize (getSize ()) ;setBackground (Color.red) ;
}
}
137
SimpleBeanV1.manifest
! Name: SimpleBeanV1.class
! Java-Bean: True
138
Création du composant
! Compilation :• javac SimpleBeanV1.java
! Création du composant :• jar cfm SimpleBeanV1.jar SimpleBeanV1.manifest SimpleBeanV1.class
139
Utilisation du composant
import java.awt.FlowLayout;import javax.swing.JFrame;
public class TestBeanV1 extends JFrame {
public TestBeanV1 () {super ("SimpleBean v1") ;addWindowListener (new Fermeur ()) ;setLayout (new FlowLayout ()) ;SimpleBeanV1 sb = new SimpleBeanV1 () ;getContentPane ().add (sb) ;pack () ; setVisible (true) ;
}
public static void main (String argvs []) {new TestBeanV1 () ;
}}
140
Propriétés
! Attributs maintenant l’état du composant
! Ces attributs et les méthodes afférentes sont soumis à des règles d’écriture (design pattern)
! A chaque propriété, associer : un observateur, un modificateur
! Les modifications de propriétés sont des événements
141
Types de propriétés
! Simples
! Indexées
! Booléennes
! Liées et/ou contraintes
142
Propriétés simples
! Déclaration :• <propertyType> <propertyName> ;
!Observateur :" <propertyType> get<propertyName> () ;
!Modificateur :" void set<propertyName> (<propertyType> propertyValue) ;
143
SimpleBeanV2.java (1/2)
import java.io.Serializable ;
import javax.swing.JPanel;
public class SimpleBeanV2 extends JPanel implements Serializable {
private Color color = Color.green ;
private static final long serialVersionUID = 1L;
public SimpleBeanV2 () {setSize (200,100) ;setPreferredSize (getSize ()) ;setBackground (Color.red) ;
}
144
SimpleBeanV2.java (2/2)
public Color getColor () {return color ;
}
public void setColor (Color newColor) {color = newColor ;repaint () ;
}
public void paint (Graphics g) {super.paint (g) ;g.setColor (color) ;g.fillRect (50, 25, 100, 50) ;
}
}
145
Tableaux et propriétés indexées
! Déclaration :• <propertyType> <propertyName> [<propertyLength>] ;
!Observateur indexé :• <propertyType> get<propertyName> (int index) ; }
!Modificateur :• void set<propertyName> (int index, <propertyType> propertyValue)• throws ArrayIndexOfBoundsException ;
146
Propriétés booléennes
! Déclaration :• boolean <propertyName> ;
!Observateur :• boolean is<propertyName> () ;
!Modificateur :• void set<propertyName> (boolean propertyValue) ;
147
Propriétés liées
! Le changement d’une propriété d’un composant peut en intéresser d’autres …
! La modification d’une propriété liée sera diffusée aux composants intéressés
! Un éditeur d'événements doit maintenir la liste des souscripteurs dans un container
! Une instance de la classe PropertyChangeSupport
aide à la gestion des souscripteurs, au tir des événements et à leur propagation
148
PropertyChangeSupport
! Constructeur :• public PropertyChangeSupport (Object sourceBean) ;
!Méthodes :• public synchronized void addPropertyChangeListener (PropertyChangeListener Listener) ;
• public synchronized void removePropertyChangeListener (PropertyChangeListener Listener) ;
• public void firePropertyChange (String pName, Object oldVal, Object newVal) ;
149
PropertyChangeEvent
! Constructeur :" public PropertyChangeEvent (Object sourceBean, String propertyName, Object oldValue, Object newValue) ;
!Méthodes :" public Object getNewValue () ;" public Object getOldValue () ;" public String getPropertyName () ;" public Object getSource () ;
150
SimpleBeanV3.java (1/3)
import java.awt.Color;import java.awt.Graphics;import java.beans.PropertyChangeListener;import java.beans.PropertyChangeSupport;import java.io.Serializable ;
import javax.swing.JPanel;
public class SimpleBeanV3 extends JPanel implements Serializable {
private Color color = Color.green ;
public SimpleBeanV3 () {setSize (200,100) ;setPreferredSize (getSize ()) ;setBackground (Color.red) ;
}
151
SimpleBeanV3.java (2/3)
public Color getColor () {return color ;
}
public void setColor (Color newColor) {Color oldColor = color ;color = newColor ;repaint () ;changes.firePropertyChange ("color", oldColor, newColor) ;
}
public void paint (Graphics g) {super.paint (g) ;g.setColor (color) ;g.fillRect (50, 25, 100, 50) ;
}152
SimpleBeanV3.java (3/3)
private PropertyChangeSupport changes =new PropertyChangeSupport (this) ;
public void addPropertyChangeListener (PropertyChangeListener l) {changes.addPropertyChangeListener (l) ;
}
public void removePropertyChangeListener (PropertyChangeListener l) {changes.removePropertyChangeListener (l) ;
}
}
153
ReadyToListenBean.java (1/3)
import java.awt.Color;import java.awt.Graphics;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;
import javax.swing.JPanel;
public class ReadyToListenBean extends JPanelimplements PropertyChangeListener, java.io.Serializable {
private static final long serialVersionUID = 1L;private Color color = Color.cyan ;
154
ReadyToListenBean.java (2/3)
public ReadyToListenBean () {setSize (200,100) ;setPreferredSize (getSize ()) ;setBackground (Color.yellow) ;
}
public Color getColor () {return color ;
}
public void setColor (Color newColor) {color = newColor ;repaint () ;
}
155
ReadyToListenBean.java (3/3)
public void paint (Graphics g) {super.paint (g) ;g.setColor (color) ;g.fillRect (50, 25, 100, 50) ;
}
public void propertyChange (PropertyChangeEvent e) {if (e.getPropertyName ().equals ("color") &&(e.getNewValue().getClass() == Color.class) &&(e.getOldValue().getClass() == Color.class)) {System.out.println ("on passe de " + e.getOldValue ().toString ()
+ " a " + e.getNewValue ().toString ()) ;setColor ((Color)e.getNewValue ()) ;
}}
}
156
TestBeanV3.java (1/3)
import java.awt.BorderLayout;import java.awt.Color;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;
import javax.swing.JFrame;
public class TestBeanV3 extends JFrame {
private static final long serialVersionUID = 1L;private SimpleBeanV3 sb ;private ReadyToListenBean rtlb ;
157
TestBean.java v3 (2/3)
public TestBeanV3 () {super () ;rtlb = new ReadyToListenBean () ;sb = new SimpleBeanV3 () ;sb.addMouseListener (new AMouseListener ()) ;sb.addPropertyChangeListener (rtlb) ;addWindowListener (new Fermeur ()) ;getContentPane ().add (BorderLayout.NORTH, sb) ;getContentPane ().add (BorderLayout.SOUTH, rtlb) ;pack () ;setVisible (true) ;
}
158
TestBean.java v3 (3/3)
class AMouseListener extends MouseAdapter {public void mouseClicked (MouseEvent e) {
if (sb.getColor () == Color.green) {sb.setColor (Color.blue) ;
} else {sb.setColor (Color.green) ;
}}
}
public static void main (String argvs []) {new TestBeanV3 () ;
}
}
159
Propriétés liées
160
Propriétés contraintes
! La propagation des changements de valeurs de certaines propriétés peut ne pas être acceptée par d’autres Beans ayant un droit de veto
! Les VetoableChangeListeners reçoivent la requête de modification de valeur de propriété
! Les VetoableChangeListeners peuvent lever une exception
! Après le tir de la requête de changement l’émetteur traite l’exception si elle apparaît
161
SimpleBeanV4.java (1/3)
import java.awt.Color;import java.awt.Graphics;import java.beans.PropertyVetoException;import java.beans.VetoableChangeListener;import java.beans.VetoableChangeSupport;import java.io.Serializable ;
import javax.swing.JPanel;
public class SimpleBeanV4 extends JPanel implements Serializable {
private Color color = Color.green ;
public SimpleBeanV4 () {setSize (200,100) ;setPreferredSize (getSize ()) ;setBackground (Color.red) ;
}162
SimpleBeanV4.java (2/3)
public Color getColor () {return color ;
}
public void setColor (Color newColor) {Color oldColor = color ;try {
changes.fireVetoableChange ("color", oldColor, newColor) ;color = newColor ;repaint () ;
} catch (PropertyVetoException e) {System.out.println (e) ;color = Color.black ;repaint () ;
}}
163
SimpleBeanV4.java (3/3)
public void paint (Graphics g) {super.paint (g) ;g.setColor (color) ;g.fillRect (50, 25, 100, 50) ;
}
private VetoableChangeSupport changes =new VetoableChangeSupport (this) ;
public void addVetoableChangeListener (VetoableChangeListener l) {changes.addVetoableChangeListener (l) ;
}
public void removeVetoableChangeListener (VetoableChangeListener l) {changes.removeVetoableChangeListener (l) ;
}
}164
NearlyReadyToListenBean.java (1/3)
import java.awt.Color;import java.awt.Graphics;import java.beans.PropertyChangeEvent;import java.beans.PropertyVetoException;import java.beans.VetoableChangeListener;import javax.swing.JPanel;
public class NearlyReadyToListenBean extends JPanelimplements VetoableChangeListener, java.io.Serializable {
private Color color = Color.magenta ;
public NearlyReadyToListenBean () {setSize (200,100) ;setPreferredSize (getSize ()) ;setBackground (Color.cyan) ;
}
165
NearlyReadyToListenBean.java (2/3)
public Color getColor () {return color ;
}
public void setColor (Color newColor) {color = newColor ;repaint () ;
}
public void paint (Graphics g) {super.paint(g) ;g.setColor (color) ;g.fillRect (50, 25, 100, 50) ;
}
166
NearlyReadyToListenBean.java (3/3)
public void vetoableChange (PropertyChangeEvent e)throws PropertyVetoException {if (e.getPropertyName ().equals ("color")) {try {if (Color.red.equals ((Color)e.getNewValue ())) {String msg = "Rouge interdit !" ; System.out.println (msg) ; throw (new PropertyVetoException (msg, e)) ;
} else {System.out.println ("on passe de " + e.getOldValue ().toString ()
+ " a " + e.getNewValue ().toString ()) ;setColor ((Color)e.getNewValue ()) ;
}} catch (ClassCastException cce) {}
}}
}
167
TestBeanV4.java (1/3)
import java.awt.BorderLayout;import java.awt.Color;import java.awt.event.InputEvent;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;
import javax.swing.JFrame;
public class TestBeanV4 extends JFrame {
private static final long serialVersionUID = 1L;private SimpleBeanV4 sb ;private NearlyReadyToListenBean nrtlb ;
168
TestBeanV4.java (2/3)
public TestBeanV4 () {super ("Test Bean v4") ;nrtlb = new NearlyReadyToListenBean () ;sb = new SimpleBeanV4 () ;sb.addMouseListener (new AMouseListener ()) ;sb.addVetoableChangeListener (nrtlb) ;addWindowListener (new Fermeur ()) ;getContentPane ().add (BorderLayout.NORTH, sb) ;getContentPane ().add (BorderLayout.SOUTH, nrtlb) ;pack () ;setVisible (true) ;
}
169
TestBeanV4.java (3/3)
class AMouseListener extends MouseAdapter {public void mouseClicked (MouseEvent e) {Color autre = Color.blue ;if (e.getModifiers () == InputEvent.BUTTON2_MASK) {autre = Color.red ;
}if (sb.getColor () == Color.green) {sb.setColor (autre) ;
} else {sb.setColor (Color.green) ;
}}
}
public static void main (String argvs []) {new TestBeanV4 () ;
}}
170
Propriétés contraintes
171
SimpleBeanV5.java (1/4)
import java.awt.Color;import java.awt.Graphics;import java.beans.PropertyChangeListener;import java.beans.PropertyChangeSupport;import java.beans.PropertyVetoException;import java.beans.VetoableChangeListener;import java.beans.VetoableChangeSupport;import java.io.Serializable ;
import javax.swing.JPanel;
public class SimpleBeanV5 extends JPanel implements Serializable {
private Color color = Color.green ;
private static final long serialVersionUID = 1L;172
SimpleBeanV5.java (2/4)
public void setColor (Color newColor) {Color oldColor = color ;pChanges.firePropertyChange ("color", oldColor, newColor) ;try {vChanges.fireVetoableChange ("color", oldColor, newColor) ;color = newColor ;repaint () ;
} catch (PropertyVetoException e) {System.out.println (e) ;System.out.println ("je le fais quand meme !") ;color = newColor ;repaint () ;
}}
173
SimpleBeanV5.java (3/4)
public void paint (Graphics g) {g.setColor (color) ;g.fillRect (50, 25, 100, 50) ;
}
private PropertyChangeSupport pChanges =new PropertyChangeSupport (this) ;
public void addPropertyChangeListener (PropertyChangeListener l) {pChanges.addPropertyChangeListener (l) ;
}
public void removePropertyChangeListener (PropertyChangeListener l) {pChanges.removePropertyChangeListener (l) ;
}
174
SimpleBeanV5.java (4/4)
public SimpleBeanV5 () {setSize (200,100) ;setPreferredSize (getSize ()) ;setBackground (Color.red) ;
}
private VetoableChangeSupport vChanges =new VetoableChangeSupport (this) ;
public void addVetoableChangeListener (VetoableChangeListener l) {vChanges.addVetoableChangeListener (l) ;
}
public void removeVetoableChangeListener (VetoableChangeListener l) {vChanges.removeVetoableChangeListener (l) ;
}
}
175
TestBeanV5.java (1/3)
import java.awt.BorderLayout;import java.awt.Color;import java.awt.event.InputEvent;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;
import javax.swing.JFrame;
public class TestBeanV5 extends JFrame {
private static final long serialVersionUID = 1L;private SimpleBeanV5 sb ;private ReadyToListenBean rtlb ;private NearlyReadyToListenBean nrtlb ;
176
TestBeanV5.java (2/3)
public TestBeanV5 () {super ("Test Bean v5") ;rtlb = new ReadyToListenBean () ;nrtlb = new NearlyReadyToListenBean () ;sb = new SimpleBeanV5 () ;sb.addMouseListener (new AMouseListener ()) ;sb.addPropertyChangeListener (rtlb) ;sb.addVetoableChangeListener (nrtlb) ;addWindowListener (new Fermeur ()) ;getContentPane ().add (BorderLayout.NORTH, sb) ;getContentPane ().add (BorderLayout.CENTER, rtlb) ;getContentPane ().add (BorderLayout.SOUTH, nrtlb) ;pack () ;setVisible (true) ;
}
177
TestBeanV5.java (3/3)
class AMouseListener extends MouseAdapter {public void mouseClicked (MouseEvent e) {
Color autre = Color.blue ;if (e.getModifiers () == InputEvent.BUTTON2_MASK) {
autre = Color.red ;}if (sb.getColor () == Color.green) {
sb.setColor (autre) ;} else {
sb.setColor (Color.green) ;}
}}
public static void main (String argvs []) {new TestBeanV5 () ;
}}
178
Propriétés liées et contraintes
179
Le composant JButton (1/3)
! Support pour une icône (Icon)! Support pour accélérateur (mnemonic)! Texte explicatif (tips)! Alignement des labels! Activation/désactivation
180
Le composant JButton (2/3)
import java.awt.Container;import javax.swing.Icon;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;
public class TestJButton {
JPanel panel ;JButton button1 ;JButton button2 ;
public TestJButton (JFrame frame) { Container c = frame.getContentPane () ;panel = new JPanel () ;c.add (panel) ;button1 = new JButton ("Hello World!") ;panel.add (button1) ;
181
Le composant JButton (3/3)
Icon icon = new ImageIcon ("java.jpg") ;button2 = new JButton ("Hello World again!", icon) ;button2.setToolTipText ("This is a JButton with Text") ;button2.setMnemonic ('o') ;panel.add (button2) ;
}
public static void main (String args []) {JFrame frame = new JFrame ("TestJButton : JButton") ;frame.addWindowListener (new Fermeur ()) ;frame.setSize (420, 210) ;new TestJButton (frame) ;frame.setVisible (true) ;
}
}182
MVC et le composant JButton
! La classe JButton :" représente les parties Vue et Contrôleur d’un bouton au sens d’un composant MVC
" délègue la gestion de son comportement à un modèle :• une instance d’une classe implémentant l’interface ButtonModel• protected ButtonModel model ;
183
Le DefaultButtonModel (1/2)
! Classe qui implémente l’interface ButtonModel! Partie Modèle d’un bouton, au sens MVC!Modèle de l'état du bouton, utilisé :
" pour les boutons classiques :• l’appui sur le bouton de la souris « arme » le bouton• le relâchement du bouton de la souris au dessus du bouton déclenche l’action associée au bouton
• le relâchement du bouton de la souris ailleurs « désarme » le bouton
" pour les cases à cocher et les boutons radio :• l’appui sur le bouton de la souris sélectionne le bouton
184
Le DefaultButtonModel (2/2)
! Pour une case à cocher ou un bouton radio :" la partie liée à l’interface utilisateur invoque setSelected(boolean) lors du clic souris
! Pour un bouton classique :" invocation, par l’IU, de setArmed (boolean) lors de l’appui du bouton de la souris
" invocation de setPressed (boolean) quand le bouton de la souris est relâché
" dans l’intervalle, si la souris quitte le bouton, setArmed(false) indiquera au bouton de ne pas se déclencher lors de l’invocation de setPressed
" si la souris revient sur le bouton, il est « réarmé »
185
Le dessin dans un composant
! Le remplissage du fond
! Le texte
! Le contour
186
Dériver JButton
! La forme et l’aspect des boutons sont personnalisables
187
RoundButton.java (1/4)
import java.awt.Color;import java.awt.Graphics;import java.awt.Shape;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.geom.Ellipse2D;
import javax.swing.AbstractButton;import javax.swing.JButton;
public class RoundButton extends JButton {
private static final long serialVersionUID = 1L;
188
RoundButton.java (2/4)
public RoundButton (String label) {super (label) ;setContentAreaFilled (false) ;addMouseListener (new Espion ()) ;
}
Shape shape ;public boolean contains (int x, int y) {if (shape == null || ! shape.getBounds ().getSize().equals (getSize ())) {
shape = new Ellipse2D.Float (0, 0, getWidth (), getHeight ()) ;}return (shape.contains (x, y)) ;
}
protected void paintBorder (Graphics g) {g.setColor (getForeground ()) ;g.drawOval (0, 0, getWidth () - 1, getHeight () - 1) ;
}
189
RoundButton.java (3/4)
protected void paintComponent (Graphics g) {if (getModel ().isEnabled ()) {if (getModel ().isPressed ()) {if (getModel ().isArmed ()) {g.setColor (Color.blue) ;
} else {g.setColor (Color.cyan) ;
}} else if (getModel ().isRollover ()) {g.setColor (Color.green) ;
} else {g.setColor (Color.yellow) ;
}} else {
g.setColor (Color.red) ; }g.fillOval (0, 0, getWidth () - 1, getHeight () - 1) ;super.paintComponent (g) ;
}190
RoundButton.java (4/4)
void espionne () {System.out.println("----------- Espion ------------") ;if (getModel ().isEnabled ()) { System.out.print ("enabled ") ; }if (getModel ().isRollover ()) { System.out.print ("rollover ") ; }if (getModel ().isArmed ()) { System.out.print ("armed ") ; }if (getModel ().isPressed ()) { System.out.print ("pressed ") ; }if (getModel ().isSelected ()) { System.out.print ("selected ") ; }System.out.println ("") ;
}
class Espion implements MouseListener {
public void mouseEntered (MouseEvent e) {System.out.println ("mouseEntered") ;espionne () ;
}…
}}
191
TestRoundButton.java (1/4)
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;
import javax.swing.AbstractButton;import javax.swing.JButton;import javax.swing.JCheckBox;import javax.swing.JFrame;import javax.swing.JPanel;
192
TestRoundButton.java (2/4)
class Activeur implements ActionListener {
AbstractButton source ;AbstractButton cible ;
public Activeur (AbstractButton source, AbstractButton cible) {super () ;this.source = source ;this.cible = cible ;
}
public void actionPerformed (ActionEvent e) {cible.setEnabled (source.isSelected ()) ;
}
}
193
TestRoundButton.java (3/4)
public class TestRoundButton extends JFrame {
private static final long serialVersionUID = 1L;
public static void main (String args []) {new TestRoundButton () ;
}
194
TestRoundButton.java (4/4)
public TestRoundButton () {super ("TestRoundButton") ;addWindowListener (new Fermeur ()) ;JPanel panel = new JPanel () ;getContentPane ().add (panel) ;// il faut mettre les boutons dans des états compatiblesJCheckBox checkBox = new JCheckBox ("Actif", true) ;//JCheckBox checkBox = new SpyCheckBox ("Actif", true) ;panel.add (checkBox) ;JButton button = new RoundButton ("Bouton arrondi") ;panel.add (button) ;Activeur activeur = new Activeur (checkBox, button) ;checkBox.addActionListener (activeur) ;pack () ;setVisible (true) ;
}
}
195
Exemples de Look And Feel
! Disponibles lors des essais :" Metal" Nimbus" CDE/Motif" Windows" Windows classic
! Une application avec quelques composants …
196
LookAndFeelComponents.java (1/5)
import java.awt.FlowLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;import javax.swing.JButton;import javax.swing.JCheckBox;import javax.swing.JFrame;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JRadioButton;import javax.swing.JSlider;import javax.swing.JTextField;import javax.swing.JToggleButton;import javax.swing.SwingUtilities;import javax.swing.UIManager;import javax.swing.UnsupportedLookAndFeelException;
197
LookAndFeelComponents.java (2/5)
public class LookAndFeelComponents extends JFrame {
private static final long serialVersionUID = 1L;
public LookAndFeelComponents () {super ("LookAndFeelComponents") ;addWindowListener (new Fermeur ()) ;getContentPane().setLayout (new FlowLayout ()) ;getContentPane().add (new JButton ("JButton")) ;getContentPane().add (new JTextField ("JTextField : ", 20)) ;getContentPane().add (new JSlider ()) ;getContentPane().add (new JToggleButton ("JToggleButton1")) ;getContentPane().add (new JToggleButton ("JToggleButton2")) ;getContentPane().add (new JToggleButton ("JToggleButton3")) ;getContentPane().add (new JCheckBox ("JCheckBox1")) ;getContentPane().add (new JCheckBox ("JCheckBox2")) ;getContentPane().add (new JCheckBox ("JCheckBox3")) ;
198
LookAndFeelComponents.java (3/5)
ButtonGroup groupe = new ButtonGroup () ;for (int i = 1 ; i < 5 ; i ++) {
JRadioButton bouton = new JRadioButton ("JRadioButton" + i) ;groupe.add (bouton) ; getContentPane().add (bouton) ;
}JMenuBar menuBar = new JMenuBar () ;UIManager.LookAndFeelInfo [] lnfInfo =
UIManager.getInstalledLookAndFeels () ;JMenu menuLnF = new JMenu ("look'n feel") ;for (int j = 0 ; j < lnfInfo.length ; j ++) {
JMenuItem jmi = new JMenuItem (lnfInfo [j].getName ()) ;menuLnF.add (jmi) ;jmi.addActionListener(new LnFListener (lnfInfo [j])) ;
}menuBar.add (menuLnF) ;setJMenuBar (menuBar) ;
199
LookAndFeelComponents.java (4/5)
pack () ;setVisible (true) ;
}
public static void main (String[] args) {new LookAndFeelComponents () ;
}
class LnFListener implements ActionListener {
UIManager.LookAndFeelInfo lnfi ;
public LnFListener (UIManager.LookAndFeelInfo lnfi) {this.lnfi = lnfi ;
}
200
LookAndFeelComponents.java (5/5)
public void actionPerformed (ActionEvent arg0) {try {UIManager.setLookAndFeel (lnfi.getClassName ()) ;SwingUtilities.updateComponentTreeUI
(LookAndFeelComponents.this) ;} catch (ClassNotFoundException e) {e.printStackTrace();
} catch (InstantiationException e) {e.printStackTrace();
} catch (IllegalAccessException e) {e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {e.printStackTrace();
}}
}
}
201
Look and Feel Metal
202
Look and Feel CDE/Motif
203
Le « Drag And Drop » AWT (1/2)
! 2 packages :" java.awt.dnd :
• DragSource, DragSourceDragEvent, DragSourceDropEvent, DragSourceListener
• DropTarget, DropTargetDragEvent, DropTargetDropEvent, DropTargetListener
• DragGestureRecognizer, DragGestureEvent, DragGestureListener
" java.awt.datatransfer :• DataFlavor• Transferable
204
Le « Drag And Drop » AWT (2/2)
! Avoir des objets qui implémentent Transferable
! Partir d’un container « associé » à une DragSource :" à qui on associera un DragSourceListener
" par le biais d’un DragGestureListener associé" lui même associé au container
! Arriver dans un container associé à une DropTarget :" à qui on ajoutera un DropTargetListener
205
Les objets en transit
! Implémenter Transferable
! Définir la donnée à transférer selon le format :• public Object getTransferData (DataFlavor flavor)
! Définir les formats d’échanges supportés :• public DataFlavor [] getTransferDataFlavors ()
! Indiquer si un format d’échange est supportée :• public boolean isDataFlavorSupported (DataFlavor flavor)
! Peuvent proposer d’autres méthodes pour un retour visuel syntaxique ou sémantique ...
206
TransferableJLabel.java (1/3)
import java.awt.datatransfer.DataFlavor;import java.awt.datatransfer.Transferable;
import javax.swing.JLabel;
public class TransferableJLabel extends JLabelimplements Transferable,
java.io.Serializable {
private static final long serialVersionUID = 1L;
public TransferableJLabel (String texte) {super (texte) ;
}
207
TransferableJLabel.java (2/3)
public DataFlavor [] getTransferDataFlavors () {DataFlavor data [] = new DataFlavor [2] ;try {
data [0] = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType) ;
data [1] = new DataFlavor (String.class, null) ;} catch (java.lang.ClassNotFoundException e) { }return (data) ;
}
public boolean isDataFlavorSupported (DataFlavor flavor) {if ((flavor.isMimeTypeEqual (DataFlavor.javaJVMLocalObjectMimeType))
|| (flavor.isMimeTypeEqual (new DataFlavor (String.class, null)))) {return (true) ;
} else {return (false) ;
}}
208
TransferableJLabel.java (3/3)
public Object getTransferData (DataFlavor flavor) {Object result = null ;if (flavor.isMimeTypeEqual (
DataFlavor.javaJVMLocalObjectMimeType)) {result = this ;
} else if (flavor.isMimeTypeEqual (new DataFlavor (String.class, null))) {result = getText () ;
} else {result = null ;
}return (result) ;
}
}
209
Le container de départ (DnD AWT)
! Créer une DragSource
! Lui associer un DragGestureListener :" lui même associé au container" chargé de démarrer le processus de DND
! Lequel lui associera un DragSourceListener :" au démarrage du DND" qui gère le DND jusqu’à la fin …
210
AWTDragSourcePanel.java (1/4)
import java.awt.Dimension;import java.awt.dnd.DnDConstants;import java.awt.dnd.DragGestureEvent;import java.awt.dnd.DragGestureListener;import java.awt.dnd.DragSource;import java.awt.dnd.DragSourceDragEvent;import java.awt.dnd.DragSourceDropEvent;import java.awt.dnd.DragSourceEvent;import java.awt.dnd.DragSourceListener;
import javax.swing.JPanel;
public class AWTDragSourcePanel extends JPanel {
private static final long serialVersionUID = 1L;
211
AWTDragSourcePanel.java (2/4)
protected DragSource dragSource = null ;
protected MyDragSourceListener myDragSourceListener = null ;
protected TransferableJLabel selected = null ;
protected DragGestureEvent theInitialEvent;
public AWTDragSourcePanel () {setPreferredSize (new Dimension (200, 200)) ;myDragSourceListener = new MyDragSourceListener () ;dragSource = new DragSource () ;dragSource.createDefaultDragGestureRecognizer (this,
DnDConstants.ACTION_MOVE,new MyDragGestureListener ()) ;
}212
AWTDragSourcePanel.java (3/4)
protected class MyDragGestureListener implements DragGestureListener {
public void dragGestureRecognized (DragGestureEvent event) {selected = null ;try {
selected = (TransferableJLabel)getComponentAt (event.getDragOrigin ()) ;
} catch (Exception e) { }if (selected != null){
theInitialEvent = event ;dragSource.startDrag (event, DragSource.DefaultMoveDrop,
selected, myDragSourceListener) ;repaint () ;
} else {System.out.println ("nothing was selected") ;
}}
}
213
AWTDragSourcePanel.java (4/4)
protected class MyDragSourceListener implements DragSourceListener {
public void dragDropEnd (DragSourceDropEvent event) {if (event.getDropSuccess ()) {
remove (selected) ;validate () ;repaint () ;
}}
public void dragEnter (DragSourceDragEvent event) { }
public void dragExit (DragSourceEvent event) { }
public void dragOver (DragSourceDragEvent event) { }
public void dropActionChanged (DragSourceDragEvent event) { }
}}
214
Le container d’arrivée (DnD AWT)
! Créer une une DropTarget associée au container
! Lui ajouter un DropTargetListener :" qui devra gérer le DND du point de vue du receveur
• mise en évidence lors du survol par l’objet en transit• gestion de la chute de l’objet sur le receveur
215
AWTDropTargetPanel.java (1/6)
import java.awt.Dimension;import java.awt.datatransfer.DataFlavor;import java.awt.datatransfer.Transferable;import java.awt.datatransfer.UnsupportedFlavorException;import java.awt.dnd.DnDConstants;import java.awt.dnd.DropTarget;import java.awt.dnd.DropTargetDragEvent;import java.awt.dnd.DropTargetDropEvent;import java.awt.dnd.DropTargetEvent;import java.awt.dnd.DropTargetListener;import javax.swing.BorderFactory;import javax.swing.JComponent;import javax.swing.JPanel;import javax.swing.border.Border;
public class AWTDropTargetPanel extends JPanel {
private static final long serialVersionUID = 1L;216
AWTDropTargetPanel.java (2/6)
protected Border raisedbevel;protected Border loweredbevel;
protected DropTarget dropTarget = null ;
public AWTDropTargetPanel() {setPreferredSize(new Dimension (200, 200)) ;dropTarget = new DropTarget(this, new MyDropTargetListener()) ;raisedbevel = BorderFactory.createRaisedBevelBorder() ;loweredbevel = BorderFactory.createLoweredBevelBorder() ;empty = BorderFactory.createEmptyBorder() ;
}
public void addElement(Object o) {add((JComponent)o) ;validate() ;repaint() ;
}
217
AWTDropTargetPanel.java (3/6)
protected class MyDropTargetListener implements DropTargetListener {
public void dragEnter(DropTargetDragEvent event) {setBorder(loweredbevel) ;
}
public void dragExit(DropTargetEvent event) {setBorder(raisedbevel) ;
}
public void dragOver(DropTargetDragEvent event) { }
218
AWTDropTargetPanel.java (4/6)
public void drop(DropTargetDropEvent event) {try {Transferable transferable = event.getTransferable () ;System.out.println (transferable) ;if (event.isLocalTransfer ()) {if (transferable.isDataFlavorSupported (
new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType))) {System.out.println("transfert local") ;event.acceptDrop(DnDConstants.ACTION_MOVE) ;TransferableJLabel b =(TransferableJLabel)transferable.getTransferData (new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType)) ;
addElement(b) ;event.getDropTargetContext().dropComplete(true) ;
}
219
AWTDropTargetPanel.java (5/6)
} else { // transfert non localif (transferable.isDataFlavorSupported (
new DataFlavor(String.class, null))) {System.out.println ("transfert serialisé") ;event.acceptDrop (DnDConstants.ACTION_MOVE) ;String s = (String)transferable.getTransferData (
new DataFlavor(String.class, null)) ;TransferableJLabel tjl = new TransferableJLabel (s) ;addElement (tjl) ;event.getDropTargetContext().dropComplete(true) ;
} else {event.rejectDrop() ;
}}
220
AWTDropTargetPanel.java (6/6)
} catch (java.io.IOException exception) {event.rejectDrop() ;
} catch (UnsupportedFlavorException ufException) {event.rejectDrop() ;
} catch (java.lang.ClassNotFoundException e) {event.rejectDrop() ;
}}
public void dropActionChanged(DropTargetDragEvent event) { }
}
}
221
AWTMainForDragAndDrop.java (1/3)
import java.awt.Color;import javax.swing.JFrame;import javax.swing.JPanel;
public class AWTMainForDragAndDrop {
public static void main (String args []) {
222
AWTMainForDragAndDrop.java (2/3)
JFrame dragFrame = new JFrame ("Drag Frame") ;JPanel dragPanel = new AWTDragSourcePanel () ;dragPanel.setBackground (Color.red) ;dragPanel.add (new TransferableJLabel ("DND1")) ;dragPanel.add (new TransferableJLabel ("DND2")) ;dragPanel.add (new TransferableJLabel ("DND3")) ;dragPanel.add (new TransferableJLabel ("DND4")) ;dragPanel.add (new TransferableJLabel ("DND5")) ;dragFrame.getContentPane ().add (dragPanel) ;dragFrame.addWindowListener (new Fermeur ()) ;dragFrame.pack () ;dragFrame.setVisible (true) ;
223
AWTMainForDragAndDrop.java (3/3)
JFrame dropFrame1 = new JFrame ("Drop Frame 1") ;JPanel dropPanel1 = new AWTDropTargetPanel () ;dropPanel1.setBackground (Color.yellow) ;dropFrame1.getContentPane ().add (dropPanel1) ;dropFrame1.addWindowListener (new Fermeur ()) ;dropFrame1.pack () ;dropFrame1.setVisible (true) ;
…
}
}
224
AWTMainForDrag.java
import java.awt.Color;import javax.swing.JFrame;import javax.swing.JPanel;public class AWTMainForDrag {public static void main (String args []) {JFrame dragFrame = new JFrame ("Drag Frame") ;JPanel dragPanel = new AWTDragSourcePanel () ;dragPanel.setBackground (Color.magenta) ;dragPanel.add (new TransferableJLabel ("DND1")) ;dragPanel.add (new TransferableJLabel ("DND2")) ;dragPanel.add (new TransferableJLabel ("DND3")) ;dragPanel.add (new TransferableJLabel ("DND4")) ;dragPanel.add (new TransferableJLabel ("DND5")) ;dragFrame.getContentPane ().add (dragPanel) ;dragFrame.addWindowListener (new Fermeur ()) ;dragFrame.pack () ; dragFrame.setVisible (true) ;
}}
225
AWTMainForDrop.java
import java.awt.Color;
import javax.swing.JFrame;import javax.swing.JPanel;
public class AWTMainForDrop {
public static void main (String args []) {JFrame dropFrame = new JFrame ("Drop Frame") ;JPanel dropPanel = new AWTDropTargetPanel () ;dropPanel.setBackground (Color.green) ;dropFrame.getContentPane ().add (dropPanel) ;dropFrame.addWindowListener (new Fermeur ()) ;dropFrame.pack () ;dropFrame.setVisible (true) ;
}
}226
Un meilleur container de départ
! Ajouter un DragSourceMotionListener :" lui même associé au DragSource" chargé de déplacer l’objet en mouvement
! Prévoir une « Window » pour toujours voir l’objet :" même lors d’un changement de JFrame…
227
AWTDragSourcePanel.java (1/6)
import java.awt.Dimension;import java.awt.Window;import java.awt.dnd.DnDConstants;import java.awt.dnd.DragGestureEvent;import java.awt.dnd.DragGestureListener;import java.awt.dnd.DragSource;import java.awt.dnd.DragSourceDragEvent;import java.awt.dnd.DragSourceDropEvent;import java.awt.dnd.DragSourceEvent;import java.awt.dnd.DragSourceListener;import java.awt.dnd.DragSourceMotionListener;
import javax.swing.JPanel;
public class AWTDragSourcePanel extends JPanel {
private static final long serialVersionUID = 1L;
228
AWTDragSourcePanel.java (2/6)
protected DragSource dragSource = null ;protected MyDragSourceListener myDragSourceListener = null ;protected MyDragSourceMotionListener myDragSourceMotionListener = null ;protected TransferableJLabel selected = null ;protected Window valise = null ;protected DragGestureEvent theInitialEvent ;
public AWTDragSourcePanel () {setPreferredSize (new Dimension (200, 200)) ;myDragSourceListener = new MyDragSourceListener () ;dragSource = new DragSource () ;dragSource.createDefaultDragGestureRecognizer (this,
DnDConstants.ACTION_MOVE, new MyDragGestureListener ()) ;myDragSourceMotionListener = new MyDragSourceMotionListener () ;dragSource.addDragSourceMotionListener (myDragSourceMotionListener) ;
}
229
AWTDragSourcePanel.java (3/6)
class MyDragSourceMotionListenerimplements DragSourceMotionListener {
public void dragMouseMoved (DragSourceDragEvent event) {valise.setLocation (1 + event.getX (),
1 + event.getY ()) ;System.out.println (valise.getLocation ()) ;
}
}
230
AWTDragSourcePanel.java (4/6)
protected class MyDragGestureListener implements DragGestureListener {
public void dragGestureRecognized (DragGestureEvent event) {selected = null ;try {selected = (TransferableJLabel)getComponentAt (
event.getDragOrigin ()) ;} catch (Exception e) { }
231
AWTDragSourcePanel.java (5/6)
if (selected != null) {theInitialEvent = event ;dragSource.startDrag (event, DragSource.DefaultMoveDrop,
selected, myDragSourceListener) ;remove (selected) ;valise = new Window ((Window)(getRootPane ().getParent ())) ;valise.add (selected) ; valise.pack () ; valise.setVisible (true) ;validate () ; repaint () ;
} else {System.out.println ("nothing was selected") ;
}}
}
232
AWTDragSourcePanel.java (6/6)
protected class MyDragSourceListener implements DragSourceListener {
public void dragDropEnd (DragSourceDropEvent event) {if (! event.getDropSuccess ()) {
add (selected) ;validate () ;repaint () ;
}valise.setVisible (false) ;
}
public void dragEnter (DragSourceDragEvent event) { }public void dragExit (DragSourceEvent event) { }public void dragOver (DragSourceDragEvent event) {}public void dropActionChanged (DragSourceDragEvent event) { }
}}
233
Bibliographie
! http://java.sun.com! K. Arnold, J. Gosling : The Java ProgrammingLanguage, Addison-Wesley, 1997
!M. Campione, K. Walrath : The Java Tutorial --Object-Oriented Programming for the Internet, Addison-Wesley, 1997
! B. Eckel : Thinking in Java, http://www.EckelObjects.com/javabook.html
!G. Hamilton, R. Cattell, M. Fisher : JDBC DatabaseAccess with Java -- A Tutorial and AnnotatedReference, Addison-Wesley, 1997
234
Bibliographie
! J. Kanerva : The Java FAQ, Addison-Wesley, 1997 ! D. Lea : Concurrent Programming in Java -- Design Principles and Patterns, Addison-Wesley, 1997
! S. Morvan : Les composants d’interfaces Java Foundation Class, Notes de cours ENIB, 2000.
! K. Walrath, M. Campione : The JFC SWING Tutorial -- A Guide to Constructing GUIS, Addison-Wesley, 1999
! J. Zukowski : Definite Guide to Swing for Java 2, Second Edition, apress, 2000. (www.apress.com)