cours gl40 interface graphique partie 1 : swingmultiagent.fr/images/gl40-swing-mvc.pdf · avantages...
TRANSCRIPT
GL40
Stéphane GALLAND UTBM 2014 1
Cours GL40
Interface graphiquePartie 1 : SWING
Dr.habil. Stéphane [email protected]
Université de Technologie de Belfort-Montbéliard (UTBM)
GL40
Stéphane GALLAND UTBM 2014 2
Plan du cours
● Historique● Propriétés de SWING● Composants SWING● SWING et Modèle Vue Contrôleur● Composants conteneurs, de contrôle, afficheurs● Layouts● Gestion des événements (Listeners)● Composants complexes (JTree, JTable)● Dessiner librement des formes
GL40
Stéphane GALLAND UTBM 2014 3
Références
● Ce support de cours est une introduction à la programmation avec AWT et SWING
● Pour avoir plus d'informations et de détails, veuillez consulter les sites Internet suivants :
– manuel de référence de Java :http://java.sun.com/javase/reference/api.jsp
– explications et tutoriels :http://java.sun.com/javase/6/docs/
GL40
Stéphane GALLAND UTBM 2014 4
SWING
Introduction
GL40
Stéphane GALLAND UTBM 2014 5
Historique
● Au départ il avait AWT (Abstract Windowing Toolkit)● Ensuite il a eu dans l’ordre chronologique:
– SWING par Sun/Oracle, – mais également SWT du projet Eclipse,– et plus récemment JFace, GWT.
● Actuellement, SWING est souvent choisi car il est fourni en standard dans le SDK
● Il est préférable de n'en utiliser qu'un seul à la fois, tant les risques d'erreurs peuvent survenir entre les deux API graphiques (leurs syntaxes sont très proches)
GL40
Stéphane GALLAND UTBM 2014 6
Historique
● Avantages et inconvénients AWT vs. Swing:– Swing, plus récent que AWT, est également plus
optimisé, et donc plus rapide. De son côté, AWT existe depuis plus longtemps, il est donc reconnu par plus de systèmes/outils.
– Swing prend en compte un plus grand nombre de widgets. De plus, étant le remplaçant officiel d'AWT, il est donc encore amélioré avec les nouvelles versions de Java.
– AWT garde encore pour lui son intégration à J2ME, et donc sa reconnaissance au sein d'un plus grand nombre de téléphones.
– Les inconvénients de Swing sont susceptibles de disparaître avec les évolutions de Java.
GL40
Stéphane GALLAND UTBM 2014 7
Historique
● Existent également les gestionnaires SWT et JFace, créés par Eclipse pour palier les manques des gestionnaires de Sun pour le propre usage d'Eclipse.
● SWT se veut plus léger que AWT et Swing réunis, tout en fournissant un large jeu de widgets et bibliothèques graphiques. Ce cadriciel est indépendant du système tout en étant capable d'utiliser des éléments natifs.
● JFace, de son côté, est une boîte à outils qui permet de simplifier la plupart des tâches graphiques. Il est construit à partir de SWT.
● GWT est le cadriciel proposé par Google pour Android.
GL40
Stéphane GALLAND UTBM 2014 8
Propriétés de SWING
● Beaucoup de widgets : boutons, panel, …
● « Pluggable Look and Feel »– on peut changer l’apparence en faisant très peu de
changements dans le code et en utilisant des packages graphiques: windows-like, Mac-like,…
● Accessibilité à des éléments d’IHM non usuels : interface braille, écrans tactiles,…
● Intègre une partie des graphiques Java2D
● Supporte le drag and drop
GL40
Stéphane GALLAND UTBM 2014 9
Propriétés de SWING
● Différentes apparences (« look & feel »)
Java
Windows Classique Mac OS
GTK+
GL40
Stéphane GALLAND UTBM 2014 10
Propriétés de SWING
● Différentes apparences (« look & feel »)
Java
Windows Classique Mac OS
GTK+UIManager.setLookAndFeel(lnfName); SwingUtilities.updateComponentTreeUI(frame);frame.pack();
GL40
Stéphane GALLAND UTBM 2014 11
Composants SWING
● Plusieurs types de composants:– conteneurs (containers) :
● de haut niveau● généraux● spéciaux
– objets de contrôle (control objects)
– afficheurs (displayers) :● non-éditables● interactifs spéciaux
– Layouts
GL40
Stéphane GALLAND UTBM 2014 12
Composants Lourds et composants légers
● Il est utile de faire la différence entre composants « lourds » et composants « légers ».
● Les composants « lourds » sont gérés par le système d’exploitation
● Les composants « légers » sont des dessins gérés par l’API SWING. Il est donc possible de contrôler leur rafraîchissement contrairement aux composants lourds.
● Les composants « légers » ont en plus quelques propriétés : transparence, superposition, ...
● Dans AWT la plupart des composants sont gérés par le système d’exploitation. Ils sont donc « lourds ».
GL40
Stéphane GALLAND UTBM 2014 13
Arborescence de composants SWING
Composants AWT
Composants SWING
GL40
Stéphane GALLAND UTBM 2014 14
SWING et Modèle Vue Contrôleur
● Plusieurs composants SWING sont implémentés suivant l’architecture « Modèle Vue Contrôleur » (MVC, voir fin de ce support de cours),
● c’est à dire que les fonctionnalités suivantes sont implémentées de manière séparées :– modèle : la logique de fonctionnement du
composant (combien d’états, est-il activé ?, ...);– vue : comment ce composant est affiché, aspect du
composant;– contrôleur : en charge des actions utilisateur.
● Dans SWING les rôles vue et contrôleur sont souvent joués par les mêmes entités.
GL40
Stéphane GALLAND UTBM 2014 15
Composants graphiquesd'affichage
GL40
Stéphane GALLAND UTBM 2014 16
Composants d'affichage
● Les composants d'affichage sont des composants graphiques permettant d'afficher une information.
● Généralement ces composants ne proposent pas de moyen d'interaction avec l'utilisateur.
● Les composants d'affichage abordés dans ce cours sont :
– les étiquettes
– les barres de progression
– les bulles d'information
GL40
Stéphane GALLAND UTBM 2014 17
Composant d'affichage : Etiquette
● Les étiquettes sont des composants graphiques capables d'afficher un texte et/ou une image.
● Classe Java : JLabel
JComponent
JLabel
Container
Component
GL40
Stéphane GALLAND UTBM 2014 18
Composant d'affichage : Etiquette
● Illustration :
Icon ic = new ImageIcon("splash.png");
JLabel et1 = new JLabel("Image and Text",ic);
GL40
Stéphane GALLAND UTBM 2014 19
Composant d'affichage : Etiquette
● Illustration :
Icon ic = new ImageIcon("splash.png");
JLabel et1 = new JLabel("Image and Text",ic);
JLabel et2 = new JLabel("Text-only Label");
GL40
Stéphane GALLAND UTBM 2014 20
Composant d'affichage : Etiquette
● Illustration :
Icon ic = new ImageIcon("splash.png");
JLabel et1 = new JLabel("Image and Text",ic);
JLabel et2 = new JLabel("Text-only Label");
JLabel et3 = new JLabel(ic);
GL40
Stéphane GALLAND UTBM 2014 21
● Une barre de progression permet d'afficher l'état d'avancement de la réalisation d'une tâche. En général, cet état d'avancement est affiché sous la forme d'une barre colorée et d'un pourcentage.
● Classe Java : JProgressBar
JComponent
JProgressBar
Container
Component
Composant d'affichage : Barre de progression
GL40
Stéphane GALLAND UTBM 2014 22
Composant d'affichage : Barre de progression
● Illustration :
JProgressBar jpb = new JProgressBar();
//when the task of (initially) unknown length begins:
jpb.setIndeterminate(true);
//do some work; get length of task...
jpb.setMaximum(newLength);
jpb.setValue(newValue);
jpb.setIndeterminate(false);
GL40
Stéphane GALLAND UTBM 2014 23
● Une bulle d'information est un composant graphique affichant un texte expliquant l'état ou les fonctionnalités d'un autre composant.
● Les bulles d'information apparaîssent en général lorsque la souris reste immobile au dessus du composant.
● Classe Java : JToolTip
JComponent
JToolTip
Container
Component
Composant d'affichage : Bulle d'information
GL40
Stéphane GALLAND UTBM 2014 24
Composant d'affichage : Bulle d'information
● Illustration :
JButton bt = new JButton("Disable middle button");
bt.setToolTipText("Click this button to disable middle button");
String txt = bt.getToolTipText();
● Lorsqu'elle est surchargée, la fonction suivante permet de créer des bulles d'information pouvant s'afficher de manière particulière :
JToolTip Component.createToolTip();
GL40
Stéphane GALLAND UTBM 2014 25
Composants graphiquesde contrôle
GL40
Stéphane GALLAND UTBM 2014 26
Objets de contrôle
● Les objets de contrôle sont des composants graphiques permettant de « contrôler » une application
● Les objets de contrôle abordés dans ce cours sont :
– les boutons (standard, radio, ou à cocher)
– les listes (déroulantes ou non)
– les barres de menu et les menus
– les champs de texte
– les sélecteurs numériques
GL40
Stéphane GALLAND UTBM 2014 27
Objet de contrôle : Bouton classique
● Un bouton est un composant sur lequel il est possible de cliquer avec la souris afin de réaliser une action. Un bouton peut afficher un texte et/ou une image.
● Classe Java : JButton AbstractButton
JButton
JComponent
Container
GL40
Stéphane GALLAND UTBM 2014 28
Objet de contrôle : Bouton classique
● Illustration :
JButton bt1 = new JButton("Text only");JButton bt2 = new JButton(
new ImageIcon("icone.png"));JButton bt3 = new JButton(
"Text and icon",new ImageIcon("icone.png"));
GL40
Stéphane GALLAND UTBM 2014 29
Objet de contrôle : Bouton radio
● Un bouton radio est un bouton fesant partie d'un groupe de boutons. Un seul bouton peut être sélectionné par groupe.
● Lorque l'utilisateur sélectionne un bouton appartenant à un groupe, les autres boutons sont automatiquement désélectionnés.
● Classe Java : JRadioButton
JToggleButton
JRadioButton
AbstractButton
JComponent
GL40
Stéphane GALLAND UTBM 2014 30
Objet de contrôle : Bouton radio
● Illustration :
ButtonGroup grp = new ButtonGroup();
JRadioButton bt1 = new JRadioButton("Bird");JRadioButton bt2 = new JRadioButton("Cat");JRadioButton bt3 = new JRadioButton("Dog");JRadioButton bt4 = new JRadioButton("Rabbit");JRadioButton bt5 = new JRadioButton("Pig");
grp.add(bt1);grp.add(bt2);grp.add(bt3);grp.add(bt4);grp.add(bt5);
bt5.doClick();
GL40
Stéphane GALLAND UTBM 2014 31
Objet de contrôle : Case à cocher
● Une case à cocher est un bouton pouvant être sélectionné ou non.
● Lorque l'utilisateur clique sur une case à cocher, la valeur booléenne associée à cette case change de valeur.
● Classe Java : JCheckBox
JToggleButton
JCheckBox
AbstractButton
JComponent
GL40
Stéphane GALLAND UTBM 2014 32
Objet de contrôle : Case à cocher
● Illustration :
JCheckBox bt1 = new JCheckBox("Chin");JCheckBox bt2 = new JCheckBox("Glasses");JCheckBox bt3 = new JCheckBox("Hair");JCheckBox bt4 = new JCheckBox("Teeth");
bt1.setSelected(true);bt2.setSelected(true);bt3.setSelected(true);bt4.setSelected(true);
assert(bt1.isSelected() == true);assert(bt2.isSelected() == true);assert(bt3.isSelected() == true);assert(bt4.isSelected() == true);
GL40
Stéphane GALLAND UTBM 2014 33
Objet de contrôle : Liste d'items
● Une liste d'items permet :– d'afficher des items (texte et/ou
image)
– de sélectionner un ou plusieurs items
● Classe Java : JList<T>● Une liste d'items respecte une
approche MVC. L'objet JList étant une vue et un contrôleur.
JComponent
JList
Container
Component
ListModel
GL40
Stéphane GALLAND UTBM 2014 34
Objet de contrôle : Liste d'items
● Illustration :
String[] data = {"one", "two", "three", "four"};JList dataList = new JList<String>(data);
List<Class<?>> superClasses = new ArrayList<>();Class<?> rootClass = javax.swing.JList.class;for(Class<?> cls=rootClass; cls!=null; cls=cls.getSuperclass()) {
superClasses.addElement(cls);
}Jlist<Class<?>> classList =
new JList<>(superClasses);
GL40
Stéphane GALLAND UTBM 2014 35
Objet de contrôle : Liste d'items
● Illustration :
String[] data = {"one", "two", "three", "four"};JList dataList = new JList(data);
Vector superClasses = new Vector();Class rootClass = javax.swing.JList.class;for(Class cls=rootClass; cls!=null; cls=cls.getSuperclass()) {
superClasses.addElement(cls);
}JList classList =
new JList(superClasses);
Les ascenseurs affichés dans cet exemple ne font pas partie des
JList.
Ces ascenseurs ont été obtenus à l'aide de composants JScrollPane
dans lesquels les composants JList ont été ajoutés.
GL40
Stéphane GALLAND UTBM 2014 36
Objet de contrôle : Liste d'items
● Une liste d'items respecte l'approche Modèle Vue Contrôleur (MVC) :
– Modèle● Représenté par une instance de
l'interface ListModel● Fonctions d'accès :ListModel JList.getModel()
void JList.setModel(ListModel model)
– Vue et Contrôleur● Ces deux aspects sont gérés par
l'instance de l'objet JList
« abstract »AbstractListModel
DefaultListModel
« interface »ListModel
GL40
Stéphane GALLAND UTBM 2014 37
Objet de contrôle : Liste d'items
● Illustration :
DefaultListModel<String> model = new DefaultListModel<>();
JList<String> dataList = new JList<>(model);
model.addElement("one");model.addElement("two");model.addElement("three");model.addElement("four");
GL40
Stéphane GALLAND UTBM 2014 38
Objet de contrôle : Liste déroulante
● Une liste déroulante permet :– d'afficher un champs de saisie
– d'afficher une liste déroulante de valeurs pour le champs de saisie
● Classe Java : JComboBox<T>● Une liste déroulante respecte
une approche MVC. L'objet JComboBox étant une vue et un contrôleur.
JComponent
JComboBox
Container
Component
ComboBoxModel
GL40
Stéphane GALLAND UTBM 2014 39
Objet de contrôle : Liste déroulante
● Illustration :
String[] data = {"one", "two", "three", "four"};JComboBox<String> dataList = new JComboBox<>(data);
List<Class<?>> superClasses = new ArrayList<>();Class<?> rootClass = javax.swing.JList.class;for(Class<?> cls=rootClass; cls!=null; cls=cls.getSuperclass()) {
superClasses.addElement(cls);
}JcomboBox<Class<?>> classList =
new JComboBox<>(superClasses);
GL40
Stéphane GALLAND UTBM 2014 40
Objet de contrôle : liste déroulante
● Une liste déroulante respecte l'approche Modèle Vue Contrôleur (MVC) :
– Modèle● Représenté par une instance de
l'interface ComboBoxModel● Fonctions d'accès :ComboBoxModel JCombobox.getModel()
void JComboBox.setModel(ComboBoxModel model)
– Vue et Contrôleur● Ces deux aspects sont gérés par
l'instance de l'objet JComboBox
«interface»MutableCombo
BoxModel
DefaultComboBoxModel
« interface »ComboBoxModel
GL40
Stéphane GALLAND UTBM 2014 41
Objet de contrôle : Liste déroulante
● Illustration :
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
JComboBox<String> dataList = new JComboBox<>(model);
model.addElement("one");model.addElement("two");model.addElement("three");model.addElement("four");
GL40
Stéphane GALLAND UTBM 2014 42
Objet de contrôle : Liste déroulante
● Une liste déroulante est composée d'un champs de saisie et d'une liste déroulante.
● Le champs de saisie ne permet pas toujours à l'utilisateur de saisir une information librement :void JComboBox.setEditable(boolean isEditable);
boolean JComboBox.isEditable();
● Si le champs de saisie est
disponible, alors il est possible
d'utiliser une liste déroulante comme
un champs de saisie classique (voir la suite de ce cours pour plus de détails sur les champs de saisie)
GL40
Stéphane GALLAND UTBM 2014 43
Objet de contrôle : Barres de menus et menus
● Le concept de menu est très utilisé dans les applications graphiques.
● Classes Java : JMenuBar, JMenu, JMenuItem
JComponent
JMenuBar
Container
Component
AbstractButton
JMenuItem
JMenu
GL40
Stéphane GALLAND UTBM 2014 44
JComponent
JMenuBar
Container
Component
AbstractButton
JMenuItem
JMenu
Objet de contrôle : Barres de menus et menus
GL40
Stéphane GALLAND UTBM 2014 45
JComponent
JMenuBar
Container
Component
AbstractButton
JMenuItem
JMenu
Objet de contrôle : Barres de menus et menus
GL40
Stéphane GALLAND UTBM 2014 46
JComponent
JMenuBar
Container
Component
AbstractButton
JMenuItem
JMenu
Objet de contrôle : Barres de menus et menus
GL40
Stéphane GALLAND UTBM 2014 47
JComponent
JMenuBar
Container
Component
AbstractButton
JMenuItem
JMenu
Objet de contrôle : Barres de menus et menus
GL40
Stéphane GALLAND UTBM 2014 48
Objet de contrôle : Liste déroulante
● Illustration :
JMenuBar bar = new JMenuBar();
JMenu menu1 = new JMenu()bar.add(menu1);
JMenuItem it1 = new JMenuItem("A text-only menu item");
menu1.add(it1);
...
GL40
Stéphane GALLAND UTBM 2014 49
Objet de contrôle : Liste déroulante
● Les options d'un menu peuvent être de trois types :
– une étiquette avec un texte et/ou une image : JMenuItem
– un bouton radio : JRadioButtonMenuItem– une case à cocher : JCheckBoxMenuItem
JMenuItem
JRadioButtonMenuItem JCheckBoxMenuItem
1
2
3
1
2
3
GL40
Stéphane GALLAND UTBM 2014 50
Objet de contrôle : Champs de saisie
● Une zone (ou champs) de saisie permet à l'utilisateur d'entrer une information au clavier.
● Classe Java : JTextField
JTextComponent
JTextField
JComponent
Container
GL40
Stéphane GALLAND UTBM 2014 51
Objet de contrôle : Champs de saisie
● Illustration :
JTextField field = new JTextField();
field.setText("My default value");
String value = field.getText();
GL40
Stéphane GALLAND UTBM 2014 52
Objet de contrôle : Champs de saisie
● Deux extensions d'un champs de saisie existent dans la biliothèque SWING :
– un champs de saisie avec formattage automatique de la valeur saisie
– un champs de saisie cachant la valeur saisie (utile pour la saisie de mots de passe)
JTextField
JFormattedTextField JPasswordField
GL40
Stéphane GALLAND UTBM 2014 53
Objet de contrôle : Potentiomètre
● Un potentiomètre est un composant permettant de sélectionner une valeur numérique en déplaçant un curseur avec la souris
● Classe Java : JSlider
JComponent
JSlider
Container
GL40
Stéphane GALLAND UTBM 2014 54
Objet de contrôle : Sélecteur ensembliste
● Un sélecteur ensembliste est un composant permettant de sélectionner une valeur dans un ensemble de valeurs
● L'ensemble des valeurs est doté des opérateurs « suivant » et « précédent ». Ces opérateurs sont utilisés par le composant pour changer de valeur.
● Classe Java : JSpinner
JComponent
JSpinner
Container
GL40
Stéphane GALLAND UTBM 2014 55
Objet de contrôle : Sélecteur de couleur
● Un sélecteur de couleur est un composant permettant à l'utilisateur de choisir une couleur
● Classe Java : JColorChooser● Ce composant affiche l'interface
graphique utilisée par le système d'exploitation pour la sélection d'une couleur
JComponent
JColorChooser
Container
GL40
Stéphane GALLAND UTBM 2014 56
Objet de contrôle : Sélecteur de fichier
● Un sélecteur de fichier est un composant permettant à l'utilisateur de choisir un fichier à ouvrir ou à enregistrer
● Classe Java : JFileChooser● Ce composant utilise la boîte de
dialogue « Ouvrir » ou « Enregistrer » du système d'exploitation
JComponent
JFileChooser
Container
GL40
Stéphane GALLAND UTBM 2014 57
Composants conteneursde haut niveau
GL40
Stéphane GALLAND UTBM 2014 58
Composants conteneurs de haut niveau
● Aussi nommés : « Top-level Containers »● Ils permettent de construire l'interface graphique en
proposant un objet graphique pouvant contenir d'autres objets graphiques
● Une application possède au moins un composant conteneur de haut-niveau
● Les composants conteneurs de haut niveau sont de trois types principaux :– Les applets Java (applets)– Les fenêtres de dialogue (dialog/message windows)– Les fenêtres classiques (frames or windows)
GL40
Stéphane GALLAND UTBM 2014 59
Composants conteneurs de haut niveau
● Applet
– Application pouvant être exécutée dans un navigateur internet
– Pour définir une applet il faut hériter de la classe JApplet et redéfinir un certain nombre de méthode (init,…)
Applet
JApplet
GL40
Stéphane GALLAND UTBM 2014 60
Composants conteneurs de haut niveau
● Fenêtre de Dialogue
– C’est une fenêtre « classique » en programmation
– Généralement, elle est modale.
– Souvent utilisée avec un JOptionPane.
Dialog
JDialog
GL40
Stéphane GALLAND UTBM 2014 61
Composants conteneurs de haut niveau
● Fenêtre de Dialogue – exemple
public class MyDialog extends JDialog {
public MyDialog(JDialog parent) {
super(parent,"An lname Question");JOptionPane theContent = new JOptionPane(
"Would you like green eggs and ham?",QUESTION_MESSAGE, YES_NO_OPTION);
getContentPane().add(theContent);setPreferredSize(new Dimension(300,200));pack();
}
}
GL40
Stéphane GALLAND UTBM 2014 62
Composants conteneurs de haut niveau
● Fenêtre classique
– C’est le type de fenêtre que vous allez le plus utiliser
– Pour définir une nouvelle fenêtre il suffit de créer un objet héritant de JFrame (cf. exemple un peu plus loin)
Frame
JFrame
GL40
Stéphane GALLAND UTBM 2014 63
Composants conteneurs de haut niveau
● Fenêtre classique – exemple
public class MyFrame extends JFrame {
public MyFrame() {
super("FrameDemo");JPanel theContent = new JPanel();add(theContent);setPreferredSize(new Dimension(300,200));pack();
}
}
GL40
Stéphane GALLAND UTBM 2014 64
Autres composants conteneurs
GL40
Stéphane GALLAND UTBM 2014 65
Composants conteneurs généraux
● Les composants conteneurs sont des composants graphiques contenant un ensemble de composants graphiques auxquels sont appliquées les règles d'interaction et d'affichage du composant conteneur
● Les composants conteneurs généraux présentés dans ce support de cours sont :
– les panneaux
– les panneaux avec ascenseurs
– les onglets
– les barres d'outils
– les panneaux séparés
– les panneaux multi-couches
GL40
Stéphane GALLAND UTBM 2014 66
Composant JPanel
● Un panneau classique est un composant léger pouvant contenir d'autres composants.
● Classe Java : JPanel
JPanel p = new JPanel();
JButton b = new JButton();
p.add(b);
JComponent
JPanel
Container
Component
GL40
Stéphane GALLAND UTBM 2014 67
Composant JPanel
● Un panneau classique est un composant léger pouvant contenir d'autres composants.
● Classe Java : JPanel
JPanel p = new JPanel();
JButton b = new JButton();
p.add(b);
Création d'une
instance de panneau
JComponent
JPanel
Container
Component
GL40
Stéphane GALLAND UTBM 2014 68
Composant JPanel
● Un panneau classique est un composant léger pouvant contenir d'autres composants.
● Classe Java : JPanel
JPanel p = new JPanel();
JButton b = new JButton();
p.add(b);
Création d'un
composantbouton
JComponent
JPanel
Container
Component
GL40
Stéphane GALLAND UTBM 2014 69
Composant JPanel
● Un panneau classique est un composant léger pouvant contenir d'autres composants.
● Classe Java : JPanel
JPanel p = new JPanel();
JButton b = new JButton();
p.add(b);
Ajout du boutondans le panneau
classique.
JComponent
JPanel
Container
Component
GL40
Stéphane GALLAND UTBM 2014 70
Composant JScrollPane
● Un panneau avec ascenseurs est un panneau pouvant contenir un autre composant. Il affiche des ascenseurs lorsque la taille du composant à l'intérieur est supérieure à la taille du panneau avec ascenseurs
● Classe Java : JWcrollPane
JButton p = new JButton();
JScrollPane sp = new JScrollPane(p);
JComponent
JScrollPane
Container
Component
GL40
Stéphane GALLAND UTBM 2014 71
Composant JScrollPane
● Illustration :
JLabel jimg = new Jlabel(
new ImageIcon("voiture.png"));jimg : JLabel
img : ImageIcon
Création d'un composant
pouvant afficher une image
GL40
Stéphane GALLAND UTBM 2014 72
Composant JScrollPane
● Illustration :
JLabel jimg = new Jlabel(
new ImageIcon("voiture.png"));
JScrollPane jsp = new
JScrollPane(jimg);
Création d'un panneau affichant des
ascenseurs lorsque la taille du contenu est
plus grand que la taille du panneau
jsp : JScrollPane
jimg : JLabel
img : ImageIcon
GL40
Stéphane GALLAND UTBM 2014 73
Composant JTabbedPane
● Un panneau avec onglets permet d'afficher des composants spécifiques en fonction de l'onglet sélectionné
● Classe Java : JTabbedPane
JTabbedPane jtp = new JTabbedPane();JPanel onglet1 = new JPanel();JPanel onglet2 = new Jpanel();
jtp.add("Onglet 1", onglet1);jtp.add("Onglet 2", onglet2);
JComponent
JTabbedPane
Container
Component
GL40
Stéphane GALLAND UTBM 2014 74
Composant JScrollPane
● Illustration :JLabel onglet1 = new JLabel("blah");JPanel onglet2 = new JPanel();JPanel onglet3 = new JPanel();JPanel onglet4 = new JPanel();
onglet2 : JPanel
onglet1 : JLabel
Création des quatre composants qui
correspondront aux contenus des quatre
onglets
onglet3 : JPanel
onglet4 : JPanel
GL40
Stéphane GALLAND UTBM 2014 75
Composant JScrollPane
● Illustration :JLabel onglet1 = new JLabel("blah");JPanel onglet2 = new JPanel();JPanel onglet3 = new JPanel();JPanel onglet4 = new Jpanel();
JTabbedPane jtb = new JTabbedPane();
onglet2 : JPanel
onglet1 : JLabel
Création de l'instance du composant pouvant
contenir des onglets
onglet3 : JPanel
onglet4 : JPaneljtb : JTabbedPane
GL40
Stéphane GALLAND UTBM 2014 76
Composant JScrollPane
● Illustration :JLabel onglet1 = new JLabel("blah");JPanel onglet2 = new JPanel();JPanel onglet3 = new JPanel();JPanel onglet4 = new Jpanel();
JTabbedPane jtb = new JTabbedPane();
jtb.add("one",onglet1);jtb.add("Two",onglet2);jtb.add("Three",onglet3);jtb.add("Four",onglet3);
Ajout des onglets
onglet2 : JPanel
onglet1 : JLabel
onglet3 : JPanel
onglet4 : JPaneljtb : JTabbedPane
GL40
Stéphane GALLAND UTBM 2014 77
Composant JToolBar
● Une barre d'outils est un composant graphique regroupant des contrôles simples (boutons, listes déroulantes, ...). Une barre d'outils est généralement située en haut d'une fenêtre.
● Classe Java : JToolBar
JToolBar jtb = new JToolBar();JButton bouton = new JButton();jtb.add(bouton);
JComponent
JToolBar
Container
Component
GL40
Stéphane GALLAND UTBM 2014 78
Composant JToolBar
● Illustration :JButton bt1 = new JButton(new ImageIcon("left.png"));
JButton bt2 = new JButton(new ImageIcon("right.png"));
JButton bt3 = new Jbutton(new ImageIcon("home.png"));
JButton bt4 = new Jbutton(new ImageIcon("notes.png"));
i1 : ImageIconbt1 : JButton
i2 : ImageIconbt2 : JButton
i3 : ImageIconbt3 : JButton
i4 : ImageIconbt4 : JButton
Création des quatre boutons de la barre
d'outils
GL40
Stéphane GALLAND UTBM 2014 79
Composant JToolBar
● Illustration :JButton bt1 = new JButton(new ImageIcon("left.png"));
JButton bt2 = new JButton(new ImageIcon("right.png"));
JButton bt3 = new JButton(new ImageIcon("home.png"));
JButton bt4 = new JButton(new ImageIcon("notes.png"));
JToolBar jtb = new JToolBar();
i1 : ImageIconbt1 : JButton
i2 : ImageIconbt2 : JButton
i3 : ImageIconbt3 : JButton
i4 : ImageIconbt4 : JButton
Création de l'instance de la barre d'outils
(vide)
jtb : JToolBar
GL40
Stéphane GALLAND UTBM 2014 80
Composant JToolBar
● Illustration :JButton bt1 = new JButton(new ImageIcon("left.png"));
JButton bt2 = new JButton(new ImageIcon("right.png"));
JButton bt3 = new JButton(new ImageIcon("home.png"));
JButton bt4 = new JButton(new ImageIcon("notes.png"));
JToolBar jtb = new JToolBar();jtb.add(bt1); jtb.add(bt2);jtb.add(bt3); jtb.add(bt4);
Ajout des boutons dans la barre d'outils
i1 : ImageIconbt1 : JButton
i2 : ImageIconbt2 : JButton
i3 : ImageIconbt3 : JButton
i4 : ImageIconbt4 : JButton
jtb : JToolBar
GL40
Stéphane GALLAND UTBM 2014 81
Composant JSplitPane
● Un panneau de séparation contient deux panneaux séparé par une barre que l'utilisateur peut déplacer avec la souris.
● Classe Java : JSplitPane
JPanel left = new JPanel();JPanel right = new JPanel();JSplitPane jsp = new JSplitPane();jsp.setLeftComponent(left);jsp.setRightComponent(right);
JComponent
JSplitPane
Container
Component
GL40
Stéphane GALLAND UTBM 2014 82
Composant JSplitPane
● Illustration :JLabel left = new JLabel("left");JLabel right = new JLabel("right"); right : JLabel
left : JLabel
Création des deux panneaux qui seront à l'intérieur du panneau
avec séparation
GL40
Stéphane GALLAND UTBM 2014 83
Composant JSplitPane
● Illustration :JLabel left = new JLabel("left");JLabel right = new Jlabel("right");
JSplitPane jsp = new JSplitPane();
right : JLabel
left : JLabel
Création d'un panneau avec séparation. Ce panneau incluse une barre de séparation
jsp : JSplitPane
GL40
Stéphane GALLAND UTBM 2014 84
Composant JSplitPane
● Illustration :JLabel left = new JLabel("left");JLabel right = new Jlabel("right");
JSplitPane jsp = new JSplitPane();
jsp.setLeftComponent(left);jsp.setRightComponent(right);
Ajout des deux composants comme
partie gauche et partie droite du panneau avec séparation
right : JLabel
left : JLabel
jsp : JSplitPane
GL40
Stéphane GALLAND UTBM 2014 85
Composant JInternalFrame
● Une fenêtre interne est un composant léger représentant une fenêtre à l'intérieur d'une fenêtre « mère » (généralement un composant JDesktopPane)
● Classe Java : JInternalFrame
JComponent
JInternalFrame
Container
Component
GL40
Stéphane GALLAND UTBM 2014 86
Composant JLayeredPane
● Le panneau contenant des calque permet d'afficher des composants les uns au dessus des autres.
● Classe Java : JLayeredPane● Un JLayeredPane contient
différentes couches (calques) dans lesquelles des composants peuvent être insérés (affichés) JComponent
JLayeredPane
Container
Component
GL40
Stéphane GALLAND UTBM 2014 87
Composant JLayeredPane
● Les couches accessibles sont :
– DEFAULT_LAYER● La couche par défaut dans
laquelle la plupart des composants sont insérés.
● C'est la couche la plus profonde.
GL40
Stéphane GALLAND UTBM 2014 88
Composant JLayeredPane
● Les couches accessibles sont :
– DEFAULT_LAYER
– PALETTE_LAYER● Couche généralement utilisée
pour placer des composants flotants comme les barres d'outils ou les palettes d'outils.
GL40
Stéphane GALLAND UTBM 2014 89
Composant JLayeredPane
● Les couches accessibles sont :
– DEFAULT_LAYER
– PALETTE_LAYER
– MODAL_LAYER● La couche où sont placés les
composants modaux.
GL40
Stéphane GALLAND UTBM 2014 90
Composant JLayeredPane
● Les couches accessibles sont :
– DEFAULT_LAYER
– PALETTE_LAYER
– MODAL_LAYER
– POPUP_LAYER● Cette couche affiche les
composants « Popup » ce qui permet d'afficher les listes déroulantes correctement par exemple.
GL40
Stéphane GALLAND UTBM 2014 91
Composant JLayeredPane
● Les couches accessibles sont :
– DEFAULT_LAYER
– PALETTE_LAYER
– MODAL_LAYER
– POPUP_LAYER
– DRAG_LAYER● Lorsqu'un composant est déplacé
à la souris, ce calque permet de l'afficher au dessus de tous les autres composants.
GL40
Stéphane GALLAND UTBM 2014 92
Composant JLayeredPane
● Illustration :JPanel cyan = new JPanel();JPanel yellow = new JPanel();JPanel magenta = new JPanel();JPanel green = new JPanel();JPanel red = new JPanel();JLabel manIcon = new JLabel();
Création des différents composants devant apparaître dans un
panneau avec calques
GL40
Stéphane GALLAND UTBM 2014 93
Composant JLayeredPane
● Illustration :JPanel cyan = new JPanel();JPanel yellow = new JPanel();JPanel magenta = new JPanel();JPanel green = new JPanel();JPanel red = new JPanel();JLabel manIcon = new JLabel();
JLayeredPane jlp = new JLayeredPane();
Création d'un panneau avec calques ne contenant aucun
composant
GL40
Stéphane GALLAND UTBM 2014 94
Composant JLayeredPane
● Illustration :JPanel cyan = new JPanel();JPanel yellow = new JPanel();JPanel magenta = new JPanel();JPanel green = new JPanel();JPanel red = new JPanel();JLabel manIcon = new JLabel();
JLayeredPane jlp = new JLayeredPane();
jlp.add(red,JLayeredPane.MODAL_LAYER);jlp.add(green,JLayeredPane.MODAL_LAYER);jlp.add(yellow,JLayeredPane.DEFAULT_LAYER);jlp.add(magenta,JLayeredPane.DEFAULT_LAYER);jlp.add(cyan,JLayeredPane.PALETTE_LAYER);jlp.add(manIcon,JLayeredPane.PALETTE_LAYER);
Ajout des composants dans les calques
GL40
Stéphane GALLAND UTBM 2014 95
Composant JDesktopPane
● Les fenêtres MDI (Multi-Document Interface) sont des fenêtres pouvant contenir d'autres fenêtres
● Classe Java : JDesktopPane
JInternalFrameJDesktopIcon
JDesktopPane
JComponent
JFrame
Container
Component
JDesktopPane
GL40
Stéphane GALLAND UTBM 2014 96
Layouts
GL40
Stéphane GALLAND UTBM 2014 97
LayoutManager
● Lorsque vous ajoutez un composant à un composant conteneur, ce dernier doit calculer la position et la taille du nouveau composant.
● Pour cela, le composant conteneur utilise un gestionnaire de disposition appellé « LayoutManager »
● Un « LayoutManager » implante différentes règles pour placer les composants les uns par rapport aux autres.
● Ainsi, la position et la taille des composants dans une interface graphique n'est pas décidée par les composants, mais par un « LayoutManager »
GL40
Stéphane GALLAND UTBM 2014 98
LayoutManager
● Le changement de « LayoutManager » pour un composant conteneur est réalisé par la fonction :
void setLayout(LayoutManager manager);
● Pour aider le « LayoutManager », les composants peuvent indiquer la taille qu'ils préfèrent avoir :
void setPreferredSize(Dimension dim);Dimension getPreferredSize();
– Ces fonctions doivent être appellées sur les composants internes
GL40
Stéphane GALLAND UTBM 2014 99
LayoutManager
● Plusieurs types de « LayoutManager » sont disponibles:– BorderLayout : initialisé pour tous les composants de haut
niveau– BoxLayout : simple ligne ou colonne– CardLayout : zone qui contient des composants pouvant
changer en cours de fonctionnement– FlowLayout : par défaut pour tous les JPanel – une ligne
avec passage à la ligne par manque de place– GridLayout : utilisation d’une grille de cellules ayant la
même taille– GridBagLayout : utilisation d’une grille de cellules qui
peuvent être de tailles différentes, les composants peuvent en outre être sur plusieurs cellules
– SpringLayout : layout dynamique pour le redimensionnement
GL40
Stéphane GALLAND UTBM 2014 100
FlowLayout
● Le FlowLayout est un gestionnaire de positionnement qui place les composants les un à la suite des autres.
● Ce gestionnaire utilise les tailles préférées des composants pour calculer les tailles réelles de ceux-ci.
● Ce gestionnaire est le gestionnaire par défaut des composants de type JPanel.
Les composants sont placés sur deux lignes carla largeur de la fenêtre ne permet pas de les placer
sur une seule ligne
GL40
Stéphane GALLAND UTBM 2014 101
FlowLayout
● Exemple :
JPanel pnl = new JPanel();
pnl.setLayout(new FlowLayout());
pnl.add(new Jbutton("Button 1"));
pnl.add(new Jbutton("Button 2"));
pnl.add(new Jbutton("Button 3"));
pnl.add(new Jbutton("Long-Named Button 4"));
pnl.add(new JButton("5"));
GL40
Stéphane GALLAND UTBM 2014 102
BorderLayout
● Le BorderLayout est un gestionnaire de positionnement qui divise l'espace en cinq zones :
– début de page (en général en haut)– début de ligne (en général à gauche)– centre– fin de ligne (en général à droite)– fin de page (en général en bas)
● Ce gestionnaire utilise les tailles préférées des composants uniquement pour les zones autres de le centre. Pour cette dernière, le composant occupera la place la plus grande possible
GL40
Stéphane GALLAND UTBM 2014 103
BorderLayout
● Exemple :
JPanel pnl = new JPanel();
pnl.setLayout(new BorderLayout());
pnl.add(new JButton("Button 1"), BorderLayout.PAGE_START);
pnl.add(new JButton("Button 2"), BorderLayout.LINE_START);
pnl.add(new JButton("Button 3"), BorderLayout.PAGE_END);
pnl.add(new JButton("Button 4"), BorderLayout.CENTER);
pnl.add(new JButton("Button 5"), BorderLayout.LINE_END);
GL40
Stéphane GALLAND UTBM 2014 104
BoxLayout
● Le BoxLayout est un gestionnaire de positionnement qui place les composants verticalement ou horizontalement (en fonction d'une option donnée à son constructeur)
● Lorsque ce gestionnaire doit placer les composants horizontalement, il utilise uniquement les hauteurs préférées des composants
● Lorsque ce gestionnaire doit placer les composants verticalement, il utilise uniquement les largeurs préférées des composants
● Ce gestionnaire de positionnement supporte également un alignement des composants par rapport au centre vertical ou horizontal
GL40
Stéphane GALLAND UTBM 2014 105
BoxLayout
● Exemple :
JPanel pnl = new JPanel();
pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS));
//pnl.setLayout(new BoxLayout(pnl, BoxLayout.X_AXIS));
pnl.add(new JButton("Button 1"));
pnl.add(new JButton("2"));
pnl.add(new JButton("Button 3"));
pnl.add(new JButton("Long-Named Button 4"));
pnl.add(new JButton("Button 5"));
GL40
Stéphane GALLAND UTBM 2014 106
GridLayout
● Le GridLayout est un gestionnaire de positionnement qui place les composants sur une grille régulière.
● Le nombre de colonnes et le nombre de lignes doivent être passés en paramètre du constructeur.
● Grille régulière : grille dont toutes les cellules possèdent la même largeur et la même hauteur
GL40
Stéphane GALLAND UTBM 2014 107
GridLayout
● Exemple :
JPanel pnl = new JPanel();
// 3 lignes, 2 colonnes
pnl.setLayout(new GridLayout(3,2));
pnl.add(new JButton("Button 1"));
pnl.add(new JButton("Button 2"));
pnl.add(new JButton("Button 3"));
pnl.add(new JButton("Long-Name Button 4"));
pnl.add(new JButton("5"));
GL40
Stéphane GALLAND UTBM 2014 108
GridBagLayout
● Le GridBagLayout est une extension du GridLayout.● Il permet :
– d'avoir des tailles différentes de cellules– de placer un composant sur plusieurs cellules
GL40
Stéphane GALLAND UTBM 2014 109
GridBagLayout
● Exemple :
JPanel pnl = new JPanel();
GridBagLayout gb = new GridBagLayout();pnl.setLayout(gb);
GridBagConstraint c = new GridBagConstraint();c.gridx = 0;c.gridy = 0;c.gridwidth = 1;c.gridheight = 1;c.fill = GridBagConstraint.NONE;JButton bt = new JButton("Button 1");gb.setConstraint(bt,c);pnl.add(bt);
...
GL40
Stéphane GALLAND UTBM 2014 110
GridBagLayout
● Exemple :
JPanel pnl = new JPanel();
GridBagLayout gb = new GridBagLayout();pnl.setLayout(gb);
GridBagConstraint c = new GridBagConstraint();c.gridx = 0;c.gridy = 0;c.gridwidth = 1;c.gridheight = 1;c.fill = GridBagConstraint.NONE;JButton bt = new JButton("Button 1");gb.setConstraint(bt,c);pnl.add(bt);
...
Les conditions permettant de positionner un composant
doivent être données à l'aide d'une instance de cet objet
GL40
Stéphane GALLAND UTBM 2014 111
GridBagLayout
● Exemple :
JPanel pnl = new JPanel();
GridBagLayout gb = new GridBagLayout();pnl.setLayout(gb);
GridBagConstraint c = new GridBagConstraint();c.gridx = 0;c.gridy = 0;c.gridwidth = 1;c.gridheight = 1;c.fill = GridBagConstraint.NONE;JButton bt = new JButton("Button 1");gb.setConstraint(bt,c);pnl.add(bt);
...
Position du composant dansla grille
GL40
Stéphane GALLAND UTBM 2014 112
GridBagLayout
● Exemple :
JPanel pnl = new JPanel();
GridBagLayout gb = new GridBagLayout();pnl.setLayout(gb);
GridBagConstraint c = new GridBagConstraint();c.gridx = 0;c.gridy = 0;c.gridwidth = 1;c.gridheight = 1;c.fill = GridBagConstraint.NONE;JButton bt = new JButton("Button 1");gb.setConstraint(bt,c);pnl.add(bt);
...
Nombre de cellules en largeur et en hauteur devant être prises par le composant
GL40
Stéphane GALLAND UTBM 2014 113
GridBagLayout
● Exemple :
JPanel pnl = new JPanel();
GridBagLayout gb = new GridBagLayout();pnl.setLayout(gb);
GridBagConstraint c = new GridBagConstraint();c.gridx = 0;c.gridy = 0;c.gridwidth = 1;c.gridheight = 1;c.fill = GridBagConstraint.NONE;JButton bt = new JButton("Button 1");gb.setConstraint(bt,c);pnl.add(bt);
...
Précise si le composant peut remplir tout l'espace
verticalement ou horizontalement :
NONE, VERTICAL, HORIZONTAL
GL40
Stéphane GALLAND UTBM 2014 114
GridBagLayout
● Exemple :
JPanel pnl = new JPanel();
GridBagLayout gb = new GridBagLayout();pnl.setLayout(gb);
GridBagConstraint c = new GridBagConstraint();c.gridx = 0;c.gridy = 0;c.gridwidth = 1;c.gridheight = 1;c.fill = GridBagConstraint.NONE;JButton bt = new JButton("Button 1");gb.setConstraint(bt,c);pnl.add(bt);
...
Cet appel de fonction permet d'indiquer au gestionnaire de
positionnement que le composant passé en premier paramètre utilisera les valeurs
de la contrainte passée en second paramètre
GL40
Stéphane GALLAND UTBM 2014 115
GridBagLayout
● Exemple (suite) :...
c.gridx = 1;c.gridy = 0;bt = new JButton("Button 2");gb.setConstraint(bt,c);pnl.add(bt);
c.gridx = 2;c.gridy = 0;bt = new JButton("Button 3");gb.setConstraint(bt,c);pnl.add(bt);
...
GL40
Stéphane GALLAND UTBM 2014 116
GridBagLayout
● Exemple (suite) :...
c.gridx = 0;c.gridy = 1;c.griwidth = 3;c.gridheight = 1;c.ipadx = 40; // marginsbt = new Jbutton("Long-Named Button 4");gb.setConstraint(bt,c);pnl.add(bt);
...
GL40
Stéphane GALLAND UTBM 2014 117
GridBagLayout
● Exemple (suite) :...
c.gridx = 1;c.gridy = 2;c.fill = GridBagConstraint.REMAINDER;c.ipadx = 0; // reset to defaultbt = new JButton("5");gb.setConstraint(bt,c);pnl.add(bt);
...
Code équivalent :
pnl.add(bt, c);
GL40
Stéphane GALLAND UTBM 2014 118
Exercice corrigé
GL40
Stéphane GALLAND UTBM 2014 119
Exercice 1
● Réaliser une fenêtre ressemblant à :
GL40
Stéphane GALLAND UTBM 2014 120
Solution exercice 1
● Solution :– Liste des composants graphiques
JLabel
JScrollPane
JLabelJList
JScrollPane caché
JList
JButton
JButton
GL40
Stéphane GALLAND UTBM 2014 121
Solution exercice 1
public class MyFrame extends JFrame {
public MyFrame() {
JLabel listLabel1 = new JLabel("What MultiListener hears:");
JList list1 = new Jlist();JScrollPane scroll1 = new JScrollPane(list1);
JLabel listLabel2 = new JLabel("What Eavesdropper hears:");
JList list2 = new Jlist();JScrollPane scroll2 = new JScrollPane(list2);
JButton leftButton = new JButton("Blah blah blah");JButton rightButton = new JButton("You don't say!");...
GL40
Stéphane GALLAND UTBM 2014 122
Solution exercice 1
● Solution :– Deux panneaux possèdent des organisations
différentes (layouts)
Un grand panneau place
son contenu verticalement :
BoxLayout
Un petit panneau place son contenu horizontalement :
BoxLayout
GL40
Stéphane GALLAND UTBM 2014 123
Solution exercice 1
...JPanel smallPanel = new JPanel();smallPanel.setLayout(
new BoxLayout(smallPanel,BoxLayout.X_AXIS));smallPanel.add(leftButton);smallPanel.add(rightButton);
JPanel bigPanel = new JPanel();bigPanel.setLayout(
new BoxLayout(bigPanel,BoxLayout.Y_AXIS));bigPanel.add(listLabel1);bigPanel.add(scroll1);bigPanel.add(listLabel2);bigPanel.add(scroll2);bigPanel.add(smallPanel);...
GL40
Stéphane GALLAND UTBM 2014 124
Solution exercice 1
...// Ajoute le grand panneau dans la fenêtregetContentPane().add(bigPanel);
// Initialisation de la taille préférée de la fenêtre
setPreferredSize(new Dimension(400,400));
// Demande à la fenêtre de calculer la position réel
// de tous ses composantspack();
} // End of constructor
...
GL40
Stéphane GALLAND UTBM 2014 125
Solution exercice 1
● Les deux listes utilisent une approche MVC.● Pour remplir ces listes, il faut utiliser deux modèles de
type DefaultTreeModel
JList
JList
GL40
Stéphane GALLAND UTBM 2014 126
Solution exercice 1
...// Création des deux modèles, et association de// chacun d'eux à une listeDefaultTreeModel model1 = new DefaultTreeModel();
list1.setModel(model1);
DefaultTreeModel model2 = new DefaultTreeModel();
list2.setModel(model2);...
GL40
Stéphane GALLAND UTBM 2014 127
Solution exercice 1
...// Ajoute des données dans les listesmodel1.addElement("Blah blah blah");model1.addElement("You don't say!");model1.addElement("You don't say!");model1.addElement("Blah blah blah");model1.addElement("You don't say!");
model2.addElement("You don't say!");model2.addElement("You don't say!");model2.addElement("You don't say!");
} // end of MyFrame()
} // end of class MyFrame
GL40
Stéphane GALLAND UTBM 2014 128
Solution exercice 1
● Le résultat est :
GL40
Stéphane GALLAND UTBM 2014 129
Solution exercice 1
● La solution précédente possède quelques problèmes
Problème d'alignement
Problème d'alignement
Pas d'espace
GL40
Stéphane GALLAND UTBM 2014 130
Solution exercice 1
● Un composant possède un attribut d'alignement par défaut :– pour un JLabel : aligné à gauche (LEFT_ALIGNMENT)– pour une JList : alignée au centre (CENTER_ALIGNMENT)
Ligne d'alignement utilisée par BoxLayout
avec Y_AXIS.
Tous les composants sont alignés sur cette
ligne.
GL40
Stéphane GALLAND UTBM 2014 131
Solution exercice 1
● Pour corrigé ce problème d'alignement, il faut que tous les composants possède la même valeur de leurs paramètres d'alignement.
● Pour changer la valeur d'alignement :
void setAlignmentX(int alignment);void setAlignmentY(int alignment);
● La valeur du paramètre alignement peut être :
Component.LEFT_ALIGNMENT (valeur égale à 0)
Component.CENTER_ALIGNMENT (valeur égale à 0.5)
Component.RIGHT_ALIGNMENT (valeur égale à 1)
GL40
Stéphane GALLAND UTBM 2014 132
Solution exercice 1
...
scroll1.setAlignmentX( Component.LEFT_ALIGNMENT );
...
scroll2.setAlignmentX( Component.LEFT_ALIGNMENT );
...
smallPanel.setAlignmentX( Component.LEFT_ALIGNMENT );
...
GL40
Stéphane GALLAND UTBM 2014 133
Solution exercice 1
● Résoudre le problème de la position des boutons :
...
smallPanel.add(Box.createHorizontalGlue());
smallPanel.add(leftButton);
smallPanel.add(Box.createRigidArea(new Dimension(20,0)));
smallPanel.add(rightButton);
smallPanel.add(Box.createHorizontalGlue());
...
GL40
Stéphane GALLAND UTBM 2014 134
Gestion des événementsprovenant de l'utilisateur
GL40
Stéphane GALLAND UTBM 2014 135
Gestionnaire d'événements
● Lorsque l'utilisateur réalise une action sur l'interface graphique, cette action est transformer en un événement la décrivant.
● Tout composant SWING peut produire un événement. Il sera alors qualifié de source de cet événement.
● La gestion des événements est basée sur l'utilisation de Listeners. Un listener reçoit les événements qu'il veut écouter.
GL40
Stéphane GALLAND UTBM 2014 136
Gestionnaire d'événements
c : JComponent
Utilisateur
l1 : Listener l2 : Listener
actiongraphique notification
événement
notificationévénement
GL40
Stéphane GALLAND UTBM 2014 137
Gestionnaire d'événements
● Les listeners sont en général des interfaces que doivent implanter des classes pour être autorisées à recevoir un événement.
● Chaque composant utilise un ou plusieurs types de Listeners :– ActionListener (le plus utilisé) – en général touche « Enter »– MouseListener – mouvements et boutons de la souris– MouseWheelListener – roulette de la souris– …
GL40
Stéphane GALLAND UTBM 2014 138
ActionListener
● L'ActionListener est une interface de Listener permettant de recevoir les événements de la catégorie « action », exemples :– clique sur un JBouton– appuie sur la touche « Enter » dans un JTextField
● L'interface ActionListener définie la fonction suivante :void actionPerformed(ActionEvent event);
● Cette fonction est appellée par le composant source pour chacun des Listeners. Le paramètre corresponds à l'événement.
GL40
Stéphane GALLAND UTBM 2014 139
Procédure pour gérer des événements
● La procédure « classique » pour gérer les événements est la suivante :
1.Créer un instance du composant source2.Créer une instance de Listener3.Enregistrer le Listener créé à l'étape 2 auprès du
composant créé à l'étape 1. Cette étape est nécessaire pour informer le composant de la présence d'un nouveau Listener.
GL40
Stéphane GALLAND UTBM 2014 140
Procédure pour gérer des événements
● Cette procédure est illustrée sur l'exemple suivant :– A chaque clique sur un bouton graphique nommé
« Fenêtre », le message « bouton cliqué » est affiché sur la console.
● Nous proposerons deux versions :– une version avec une classe nommée pour Listener– une version avec une classe anonyme pour
Listener
GL40
Stéphane GALLAND UTBM 2014 141
Exemple : version 1
class MyListener implements ActionListener {public void actionPerformed(ActionEvent e) {
System.out.println("bouton cliqué");}
}
class MyWin extends JFrame {public MyWin() {
JButton bouton = new JButton("Fenêtre");ActionListener listener = new MyListener();bouton.addActionListener(listener);add(bouton);
}}
1
2
3
GL40
Stéphane GALLAND UTBM 2014 142
Exemple : version 2
class MyWin extends JFrame {public MyWin() {
JButton bouton = new JButton("Fenêtre");
ActionListener listener = new ActionListener() {public void actionPerformed(ActionEvent e) {System.out.println("bouton cliqué");
}};
bouton.addActionListener(listener);add(bouton);
}}
1
2
3
GL40
Stéphane GALLAND UTBM 2014 143
Exercice corrigé
GL40
Stéphane GALLAND UTBM 2014 144
Exercice 2
● Réaliser un convertisseur monétaire pour le dollars, l'euro, et le yuan.
● Les taux de convertion entre ces différentes devises monétaires devront être enregistrés dans des constantes.
● Conseil : utiliser une approche MVC
GL40
Stéphane GALLAND UTBM 2014 145
Solution exercice 2
● L'approche MVC nous permet de proposer une solution en trois parties :– partie « modèle »– partie « vue »– partie « contrôleur »
GL40
Stéphane GALLAND UTBM 2014 146
Solution exercice 2
● La partie « modèle » est une classe définie par :– un attribut contenant la valeur monétaire à convertir– un attribut indiquant le type de la convertion :
● euro vers dollars● euro vers yuan● dollars vers euro● dollars vers yuan● yuan vers euro● yuan vers dollars
– les fonctions permettant de convertir une valeur donnée dans une monnaie vers une valeur donnée dans une autre monnaie
GL40
Stéphane GALLAND UTBM 2014 147
Solution exercice 2
public class MonetaryModel {
// Fonctions permettant de convertir une monnaie dans une autre
public static double euro2yuan(double amount) {return amount * 10.7;
}public static double yuan2euro(double amount) {
return amount / 10.7;}public static double euro2dollars(double amount) {
return amount / 1.6;}public static double dollars2euro(double amount) {
return amount * 1.6;}public static double yuan2dollars(double amount) {
return euro2dollars(yuan2euro(amount));}public static double dollars2yuan(double amount) {
return euro2yuan(dollars2euro(amount));}...
GL40
Stéphane GALLAND UTBM 2014 148
Solution exercice 2
...
// Attributs du modèle
private double amountToConvert;private int convertionType;
// Valeurs pouvant être prises par l'attribut convertionType
public static final int EURO_TO_YUAN = 0;public static final int EURO_TO_DOLLARS = 1;public static final int DOLLARS_TO_YUAN = 2;public static final int DOLLARS_TO_EURO = 3;public static final int YUAN_TO_DOLLARS = 4;public static final int YUAN_TO_EURO = 5;
// Constructeurpublic MonetaryModel() {
amountToConvert = 0;
convertionType = YUAN_TO_EURO;
}
...
GL40
Stéphane GALLAND UTBM 2014 149
Solution exercice 2
...
// Fonctions pour lire et changer les valeurs
// des attributs du modèle
public void setConvertionType(int type) {convertionType = type;
}
public int getConvertionType() {return convertionType;
}
public void setAmount(double amount) {
amountToConvert = amount;
}
public double getAmountBeforeConvertion() {return amountToConvert;
}...
GL40
Stéphane GALLAND UTBM 2014 150
Solution exercice 2
...
public double getAmountAfterConvertion() {
switch(convertionType) {
case DOLLARS_TO_EURO:
return dollars2euro(amountToConvert);case DOLLARS_TO_YUAN:
return dollars2yuan(amountToConvert);case EURO_TO_DOLLARS:
return euro2dollars(amountToConvert);case EURO_TO_YUAN:
return euro2yuan(amountToConvert);case YUAN_TO_DOLLARS:
return yuan2dollars(amountToConvert);case YUAN_TO_EURO:
return yuan2euro(amountToConvert);default:
return amountToConvert;}
}} // End of class MonetaryModel
GL40
Stéphane GALLAND UTBM 2014 151
Solution exercice 2
● Selon la définition de l'approche MVC, un modèle doit avertir ses représentations graphiques (vues) que l'une des valeurs du modèle a changé.
● Pour cela, il faut créer un mécanisme de création et de notification des événements. En Java ce mécanisme est basé sur les concepts de « Listener » et de « Event »
GL40
Stéphane GALLAND UTBM 2014 152
Solution exercice 2
● Un « Listener » est un objet qui veut être informé à chaque fois qu'un événement se produit.
● Quels sont les événements qui peuvent se produire dans le modèle que nous venons d'écrire ?
– Réponse :● « Le montant a changé »● « Le type de la convertion a changé »
● En Java, un « Listener » est une interface qui fournit une déclaration d'une fonction pour chaque type d'événement.
GL40
Stéphane GALLAND UTBM 2014 153
Solution exercice 2
public interface MonetaryModelListener extends EventListener {
public void onAmountChangedEvent(MonetaryModelEvent event);
public void onTypeChangedEvent(MonetaryModelEvent event);
}
Cette classe représente la description de
l'événement.Elle est définie dans le
transparent suivant.
GL40
Stéphane GALLAND UTBM 2014 154
Solution exercice 2
public class MonetaryModelEvent extends EventObject {
private final double amount;
private final int type;
public MonetaryModelEvent(MonetaryModel source, double amount, int type) {
super(source);this.amount = amount;this.type = type;
}
public double getAmount() {
return amount;}
public int getType() {
return type;}
}
GL40
Stéphane GALLAND UTBM 2014 155
Solution exercice 2
● Une fois que les classes du « Listener » et de l'événement sont créées, il faut modifier la classe du modèle en ajoutant les fonctions permettant à un « Listener » de s'enregistrer pour recevoir l'événementpublic class MonetaryModel {
...
private final Vector listeners = new Vector();
public void addMonetaryModelListener(MonetaryModelListener listener) {
listeners.add(listener);}
public void removeMonetaryModelListener(MonetaryModelListener listener) {
listeners.remove(listener);}
}
GL40
Stéphane GALLAND UTBM 2014 156
Solution exercice 2
● Il faut ensuite créer une fonction par type d'événement qui permette d'envoyer l'événement aux « Listeners » public class MonetaryModel {
...
protected void fireAmountChangedEvent() {
MonetaryModelEvent event = new MonetaryModelEvent(this, amountToConvert, convertionType);
for(int i=0; i<listeners.size(); i++) {MonetaryModelEvent oneListener = listeners.get(i);oneListener.onAmountChangedEvent(event);
}}
protected void fireTypeChangedEvent() {
MonetaryModelEvent event = new MonetaryModelEvent(this, amountToConvert, convertionType);
for(int i=0; i<listeners.size(); i++) {MonetaryModelEvent oneListener = listeners.get(i);oneListener.onTypeChangedEvent(event);
}}
}
GL40
Stéphane GALLAND UTBM 2014 157
Solution exercice 2
● Enfin, la dernière étape pour implanter le modèle est la modification des fonctions qui permettent de changer les valeurs des attributs du modèle. Cette modification consiste à informer les « Listeners » que la valeur a changée.public class MonetaryModel {
...
public void setAmount(double amount) {
amountToConvert = amount;fireAmountChangedEvent();
}
...
public void setConvertionType(int type) {
convertionType = type;fireTypeChangedEvent();
}
...
}
GL40
Stéphane GALLAND UTBM 2014 158
Solution exercice 2
● La partie « vue » est un ensemble de composants graphiques correspondant à l'image suivante :
● Il faut créer une fenêtre avec ces composants
GL40
Stéphane GALLAND UTBM 2014 159
Solution exercice 2
public class MonetaryConvertionFrame extends JFrame {
// Constantes pour l'affichage
public static final String EURO_TO_YUAN = "Euro -> Yuan";
public static final String EURO_TO_DOLLARS = "Euro -> Dollars";
public static final String DOLLARS_TO_YUAN = "Dollars -> Yuan";
public static final String DOLLARS_TO_EURO = "Dollars -> Euro";
public static final String YUAN_TO_DOLLARS = "Yuan -> Dollars";
public static final String YUAN_TO_EURO = "Yuan -> Euro";
public static final String EURO = " €";
public static final String DOLLARS = " $US";
public static final String YUAN = " RMB";
// Modèle utilisé par cette vue
private final MonetaryModel model;
// Composants graphiques nécessitant des
// changements dans leurs affichages
private JTextField valueField;
private JComboBox typeList;
private JLabel resultLabel;
...
GL40
Stéphane GALLAND UTBM 2014 160
Solution exercice 2
...
public MonetaryConvertionFrame(MonetaryModel model) {
super("Convertion monétaire");
// La vue se souvient de son modèle
this.model = model;
// La vue veut recevoir les événements du modèle
this.model.addMonetaryModelListener(this);
// Création des composants graphiques
JLabel label1 = new JLabel("Valeur à convertir :");
valueField = new JTextField();
JLabel label2 = new JLabel("Type de convertion :");
typeList = new JComboBox();
typeList.setEditable(false);
DefaultComboBoxModel listModel = new DefaultComboBoxModel();
typeList.setModel(listModel);
JButton convertButton = new JButton("Convertir");
resultLabel = new JLabel();
...
GL40
Stéphane GALLAND UTBM 2014 161
Solution exercice 2
...
// Le constructeur continue ici
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3,2));
panel.add(label1);
panel.add(valueField);
panel.add(label2);
panel.add(typeList);
panel.add(convertButton);
panel.add(resultLabel);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(panel, BorderLayout.CENTER);
panel.setPreferredSize(new Dimension(400,200));
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
...
GL40
Stéphane GALLAND UTBM 2014 162
Solution exercice 2
...
// Le constructeur continue ici
// Remplir la liste des types de convertion
listModel.addElement(EURO_TO_YUAN);
listModel.addElement(EURO_TO_DOLLARS);
listModel.addElement(DOLLARS_TO_YUAN);
listModel.addElement(DOLLARS_TO_EURO);
listModel.addElement(YUAN_TO_DOLLARS);
listModel.addElement(YUAN_TO_EURO);
// Mise à jour du contenu des composants graphiques
// avec les informations extraites du modèle
updateViewContent();
} // End of the constructor
...
GL40
Stéphane GALLAND UTBM 2014 163
Solution exercice 2
...public void updateViewContent() {
valueField.setText(Double.toString(model.getAmountBeforeConvertion()));
String devise;
switch(model.getConvertionType()) {case MonetaryModel.DOLLARS_TO_EURO:
typeList.setSelectedItem(DOLLARS_TO_EURO); devise = EURO;
break;case MonetaryModel.DOLLARS_TO_YUAN:
typeList.setSelectedItem(DOLLARS_TO_YUAN); devise = YUAN;
break;case MonetaryModel.YUAN_TO_EURO:
typeList.setSelectedItem(YUAN_TO_EURO); devise = EURO;
break;...
GL40
Stéphane GALLAND UTBM 2014 164
Solution exercice 2
...case MonetaryModel.YUAN_TO_DOLLARS:
typeList.setSelectedItem(YUAN_TO_DOLLARS); devise = DOLLARS;
break;case MonetaryModel.EURO_TO_YUAN:
typeList.setSelectedItem(EURO_TO_YUAN); devise = YUAN;
break;case MonetaryModel.EURO_TO_DOLLARS:
typeList.setSelectedItem(EURO_TO_DOLLARS); devise = DOLLARS;
break;default:
return;}
resultLabel.setText(Double.toString(model.getAmountAfterConvertion()) + devise);
} // End of updateViewContent()...
GL40
Stéphane GALLAND UTBM 2014 165
Solution exercice 2
...
public static final void main(String[] args) {// Création du modèleMonetaryModel model = new MonetaryModel();// Création de la vue ET du contrôleurMonetaryConvertionFrame view = new MonetaryConvertionFrame(model);
// Affichage de la fenêtreview.setVisible(true);
}
} // End of class
GL40
Stéphane GALLAND UTBM 2014 166
Solution exercice 2
● Selon la définition de l'approche MVC, la partie « vue » doit être informée de chaque changement dans le modèle afin qu'elle puisse raffraichir son contenu.
● Dans cet exercice, la « vue » doit écouter le modèle concernant les événéments de modification.
● Nous en déduisons que la vue est un écouteur de type MonetaryModelListener
● Il faut donc modifier la classe MonetaryModelFrame comme indiqué dans le transparent suivant.
GL40
Stéphane GALLAND UTBM 2014 167
Solution exercice 2
public class MonetaryConvertionFrame extends JFrame implements MonetaryModelListener {
...
public void onAmountChange(MonetaryModelEvent event) {
// Lorsque le montant à convertir dans le modèle// change, il faut modifier les valeurs affichées// dans les composants graphiquesupdateViewContent();
}
public void onTypeChange(MonetaryModelEvent event) {
// Lorsque le type de convertion dans le modèle// change, il faut modifier les valeurs affichées// dans les composants graphiquesupdateViewContent();
}
} // End of class
GL40
Stéphane GALLAND UTBM 2014 168
Solution exercice 2
● La partie « contrôleur » définie comment l'utilisateur peut interagir avec l'interface graphique, et ce qui doit être fait en retour :
Quand l'utilisateur clique sur le bouton, le modèle est mis à jour
avec les données dans cette fenêtre
GL40
Stéphane GALLAND UTBM 2014 169
Solution exercice 2
● En accord avec le modèle de gestion des événéments de SWING, un bouton informe un ActionListener lorsque l'utilisateur clique sur le bouton.
● Dans cet exercice, le contrôleur est un ActionListener qui écoute les événements du bouton « Convertir »
● Le code de la classe MonetaryConvertionFrame est modifié comme cela est indiqué dans la diapositive suivante :
GL40
Stéphane GALLAND UTBM 2014 170
Solution exercice 2
public class MonetaryConvertionFrame extends JFrame implements MonetaryModelListener, ActionListener {
...
public void actionPerformed(ActionEvent event) {
// quelles sont les valeurs dans le modèle ?
double currentModelAmount = model.getAmountBeforeConvertion();
int currentModelType = model.getConvertionType();
...
GL40
Stéphane GALLAND UTBM 2014 171
Solution exercice 2
...
// quelles sont les valeurs saisie par l'utilisateur ?
double inputAmount = Double.parseDouble(valueField.getText());
int inputType;
String selectedType = (String)typeList.getSelectedItem();
if (EURO_TO_YUAN.equals(selectedType))
inputType = MonetaryModel.EURO_TO_YUAN;else if (EURO_TO_DOLLARS.equals(selectedType))
inputType = MonetaryModel.EURO_TO_DOLLARS;else if (YUAN_TO_DOLLARS.equals(selectedType))
inputType = MonetaryModel.YUAN_TO_DOLLARS;else if (YUAN_TO_EURO.equals(selectedType))
inputType = MonetaryModel.YUAN_TO_EURO;else if (DOLLARS_TO_YUAN.equals(selectedType))
inputType = MonetaryModel.DOLLARS_TO_YUAN;else
inputType = MonetaryModel.DOLLARS_TO_EURO;...
GL40
Stéphane GALLAND UTBM 2014 172
Solution exercice 2
...// Si la valeur saisie par l'utilisateur est différente// de la valeur dand le modèle, alors la valeur du modèle est// changéeif (currentModelAmount!=inputAmount) {
model.setAmount(inputAmount);}
// Si le type saisie par l'utilisateur est différent// du type dans le modèle, alors le type dans le modèle est// changéeif (currentModelType!=inputType) {
model.setConvertionType(inputType);}
} // End of actionPerformed()
} // End of class MonetaryConverterFrame
GL40
Stéphane GALLAND UTBM 2014 173
Composants complexesJTree et JTable
GL40
Stéphane GALLAND UTBM 2014 174
Composants complexes
● La suite de ce cours est consacrée à deux composants graphiques complexes :– JTree : affichage d'informations dans un arbre– JTable : affichage d'informations dans un tableau
GL40
Stéphane GALLAND UTBM 2014 175
Composant complexe : JTree
● La classe JTree permet d'afficher des données hiérarchiques
● Un objet JTree ne contient pas les données utilisateur; il fournit une vue sur ces données
● Comme la plupart des composants SWING, la classe JTree utilise une approche Modèle Vue Contrôleur (MVC) :– modèle : TreeModel<T>– vue et contrôleur : JTree<T>
GL40
Stéphane GALLAND UTBM 2014 176
Composant complexe : JTree
● Chaque ligne dans un JTree contient exactement un item, qui est appelé noeud (ou node)
● Chaque JTree possède un noeud racine (root). Par défaut un JTree affiche le noeud racine, mais il peut ne pas l'être si cela est nécessaire.
● Un noeud peut avoir des fils ou non. Les noeuds pouvant avoir des fils sont nommés noeuds de branche (branch node). Les noeuds ne pouvant pas avoir de fils sont nommés noeuds feuilles (leaf node)
GL40
Stéphane GALLAND UTBM 2014 177
Composant complexe : JTree
● Les noeuds de branche peuvent être ouverts ou fermés par l'utilisateur, rendant ainsi les noeuds fils visibles ou invisibles. Ces deux actions sont réalisables en :– cliquant sur le signe ou – en double cliquant sur le noeud
● Une application peut détecter ces changements en écoutant (listening) les événements d'expansion de l'arbre.
GL40
Stéphane GALLAND UTBM 2014 178
Créer un JTree
● Un JTree utilise un modèle basé sur des noeuds. La classe Java la plus utilisée pour représenter un noeud est DefaultMutableTreeNode.
● Un JTree étant une représentation hiérarchique, il est obligatoire d'avoir un noeud racine, généralement spécifié lors de la construction du JTree :
DefaultMutableTreeNode root = new
DefaultMutableTreeNode("Root Node");JTree tree = new JTree(root);
JScrollPane treeView = new JScrollPane(tree);
GL40
Stéphane GALLAND UTBM 2014 179
Créer un JTree
● Un JTree utilise un modèle basé sur des noeuds. La classe Java la plus utilisée pour représenter un noeud est DefaultMutableTreeNode.
● Un JTree étant une représentation hiérarchique, il est obligatoire d'avoir un noeud racine, généralement spécifié lors de la construction du JTree :
DefaultMutableTreeNode root = new
DefaultMutableTreeNode("Root Node");JTree tree = new JTree(root);
JScrollPane treeView = new JScrollPane(tree);
Création d'une instance représentant le noeud
racine
En général un objet de type JTree est inséré dans un JScrollPane afin de permettre l'apparition des
ascenseurs si le contenu du JTree ne peut pas apparaître totalement
à l'écran
Création d'une instance de JTree en spécifiant le
noeud racine
GL40
Stéphane GALLAND UTBM 2014 180
JTree : Créer des noeuds
● Les noeud d'un JTree sont en général des DefaultMutableTreeNode car cette classe possède les fonctions suivantes :
– support de la hiérarchie :void add(MutableTreeNode child);int getChildCount();MutableTreeNode getChildAt(int index);TreeNode getParent();...
– support de données utilisateur :void setUserObject(Object data);Object getUserObject();
GL40
Stéphane GALLAND UTBM 2014 181
JTree : Créer des noeuds
● Illustration (version 1):
DefaultMutableTreeNode parent1 = new DefaultMutableTreeNode("Parent 1");
root.add(parent1);
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1");
parent1.add(child1);
DefaultMutableTreeNode newNode1 = new DefaultMutableTreeNode("New Node 1");
DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child 2");
parent1.add(child2);
child2.add(newNode1);
tree.getModel().reload();
...
Afin de mettre à jour la vue, il est nécessaire d'appeller la fonction reload(). Celle-ci va notifier le JTree que le contenu
du modèle a été changé.D'autres fonctions existent afin d'informer plus finement la vue des changements.
GL40
Stéphane GALLAND UTBM 2014 182
JTree : Créer des noeuds
● Illustration (version 2):
DefaultTreeModel model =
(DefaultTreeModel)tree.getModel();DefaultMutableTreeNode parent1 = new
DefaultMutableTreeNode("Parent 1");
model.insertNodeInto(parent1,root,0);
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1");
model.insertNodeInto(child1,parent1,0);
...
Les fonctions d'insertion proposées par le modèle informe automatiquement la vue
(l'objet JTree) qu'elle doit se mettre à jour.
GL40
Stéphane GALLAND UTBM 2014 183
Répondre aux événements desélection dans un JTree
● Intercepter et répondre à un événement de sélection sur un JTree est simple.
● Il faut implanter un TreeSelectionListener et l'enregistrer auprès du Jtree avec la fonction addTreeSelectionListener() :
TreeSelectionListener listener = new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {// Réaction à une selection décrite par// l'événement e
}};
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(listener);
GL40
Stéphane GALLAND UTBM 2014 184
Répondre aux événements desélection dans un JTree
● Intercepter et répondre à un événement de sélection sur un JTree est simple.
● Il faut implanter un TreeSelectionListener et l'enregistrer auprès du Jtree avec la fonction addTreeSelectionListener() :
TreeSelectionListener listener = new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {// Réaction à une selection décrite par// l'événement e
}};
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(listener);Création d'un Listener devant réagir à un événement de sélection
GL40
Stéphane GALLAND UTBM 2014 185
Répondre aux événements desélection dans un JTree
● Intercepter et répondre à un événement de sélection sur un JTree est simple.
● Il faut implanter un TreeSelectionListener et l'enregistrer auprès du Jtree avec la fonction addTreeSelectionListener() :
TreeSelectionListener listener = new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {// Réaction à une selection décrite par// l'événement e
}};
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(listener);
Enregistrement du listener créé auprès de l'objet JTree afin qu'il soit notifié à chaque
fois qu'une sélection se produit dans le JTree.
GL40
Stéphane GALLAND UTBM 2014 186
Répondre aux événements desélection dans un JTree
● Intercepter et répondre à un événement de sélection sur un JTree est simple.
● Il faut implanter un TreeSelectionListener et l'enregistrer auprès du Jtree avec la fonction addTreeSelectionListener() :
TreeSelectionListener listener = new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {// Réaction à une selection décrite par// l'événement e
}};
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(listener);
L'objet JTree incluse un modèle de sélection des noeuds (getSelectionModel).Ce modèle permet de spécifier le type de sélection autorisé :- SINGLE_TREE_SELECTION : un seul noeud peut être sélectionné à la fois.- CONTIGUOUS_TREE_SELECTION : plusieurs noeuds peuvent être sélectionnés en même temps. Tous les noeuds sélectionnés sont contigus.- DISCONTIGUOUS_TREE_SELECTION : plusieurs noeuds peuvent être sélectionnés en même temps. Les noeuds sélectionnés peuvent ne pas être contigus.
GL40
Stéphane GALLAND UTBM 2014 187
Répondre aux événements demodification du contenu d'un JTree
● Intercepter et répondre à un événement de changement du contenu d'un JTree est simple.
● Il faut implanter un TreeModelListener et l'enregistrer auprès du modèle du JTree avec la fonction addTreeModelListener() :
TreeModelListener listener = new TreeModelListener() {
public void treeNodesChanged(TreeModelEvent e) {}public void treeNodesInserted(TreeModelEvent e) {}public void treeNodesRemoved(TreeModelEvent e) {}public void treeStructureChanged(TreeModelEvent e) {}
};
tree.getModel().addTreeModelListener(listener);
GL40
Stéphane GALLAND UTBM 2014 188
Changer l'affichage dans un JTree
● Voici quelques exemples d'affichages différents d'un même JTree :
● Quelques fonctions simples du JTree permettent de modifier l'affichage :– Affiche ou non le noeud racine :
void JTree.setRootVisible(boolean visible)– Affiche ou non la poignée du noeud racine :
void JTree.setShowsRootHandles(boolean visible)
– Change le style des lignes entre les noeuds :void JTree.putClientProperty("JTree.lineStyle", v);
où v est "Angled" (défaut), "Horizontal" ou "None"
GL40
Stéphane GALLAND UTBM 2014 189
Changer l'affichage dans un JTree
● Voici quelques exemples d'affichages différents d'un même JTree :
● Un JTree utilise un objet particulier pour dessiner les noeuds : un TreeCellRenderer ou DefaultTreeCellRenderer
● Il est alors possible de changer l'affichage d'un noeud en implantant un nouveau TreeRenderer et en le fournissant au JTree grâce à la fonction
void setRenderer(TreeCellRenderer renderer);
GL40
Stéphane GALLAND UTBM 2014 190
Composant complexe : JTable
● La classe JTable permet d'afficher des données au sein d'une table, et permet également d'éditer ces données
● Un objet JTable ne contient pas les données utilisateur; il fournit une vue sur ces données
● Comme la plupart des composants SWING, la classe JTable utilise une approche Modèle Vue Contrôleur (MVC) :– modèle : TableModel– vue et contrôleur : JTable
GL40
Stéphane GALLAND UTBM 2014 191
Composant complexe : JTable
● Une table est composée de colonnes de valeurs. Toutes les valeurs appartenant à une colonne sont du même type.
● Chaque cellule de la table est associée à une donnée utilisateur qui est alors affichée (en utilisant le plus souvant le résultat de la fonction toString()).
● Une table peut posséder une entête permettant :– de donner un nom aux colonnes– de trier les éléments de la colonne– de changer le type des élements de la colonnes
GL40
Stéphane GALLAND UTBM 2014 192
Créer une JTable
● Une JTable utilise un modèle basé sur des cellules. La classe Java la plus utilisée pour représenter ce modèle est DefaultTableModel.
● Une manière simple de créer une JTable est :
JTable table = new JTable();
JScrollPane tableView = new JScrollPane(table);
table.setFillsViewportHeight(true);
GL40
Stéphane GALLAND UTBM 2014 193
Modèle de données pour une JTable
● Le modèle de donnée utilisé par une JTable est accessible via les fonctions :
void JTable.setModel(TableModel model);
TableModel JTable.getModel();
● Le modèle de données pour une JTable implante l'interface TableModel qui propose les fonctions suivantes :
– int TableModel.getColumnCount();● retourne le nombre de colonnes dans la table
– String TableModel.getColumnName(int index);● retourne le nom de la colonne à l'index spécifié
– Class TableModel.getColumnClass(int index);● retourne le type des valeurs d'une colonne
– int TableModel.getRowCount();● retourne le nombre de lignes dans la table
GL40
Stéphane GALLAND UTBM 2014 194
Modèle de données pour une JTable
● Suite des fonctions proposées par le TableModel :– Object TableModel.getValueAt(int rowIndex, int columnIndex);
● retourne la valeur d'une cellule– void TableModel.setValueAt(Object newValue, int rowIndex, int columnIndex);
● change la valeur d'une cellule– boolean TableModel.isCellEditable(int rowIndex, int columnIndex);
● retourne une valeur indiquant si la cellule spécifiée est éditable ou non
GL40
Stéphane GALLAND UTBM 2014 195
Répondre aux événements desélection dans une JTable
● Par défaut, une JTable supporte une sélection de une ou plusieurs lignes (contiguës ou non).
● L'utilisateur peut utiliser la souris ou le clavier pour réaliser une sélection, comme cela est décrit dans la table suivante :
Opération Action Souris Action ClavierClic Haut ou Bas
Control+Clic
Séléction d'une seule ligne
Etendre une sélection continue
Shift+Clic ou drag sur plusieurs lignes
Shift+Haut ou Shift+Bas
Ajouter une ligne à la sélection ou inverser
la sélection d'une ligne
Déplacer la cellule courante avec Haut et Bas, puis appuyer sur Espace pour modifier
la sélection de la cellule
GL40
Stéphane GALLAND UTBM 2014 196
Répondre aux événements desélection dans une JTable
● Le modèle de sélection (TableSelectionModel) utilisé par une JTable autorise plusieurs modes de sélection :
– ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
– ListSelectionModel.SINGLE_INTERVAL_SELECTION
– ListSelectionModel.SINGLE_SELECTION
● Ces modes de sélection peuvent être utilisé en paramètre de la fonction :
– void TableSelectionModel.setSelectionMode(int mode);
GL40
Stéphane GALLAND UTBM 2014 197
Répondre aux événements desélection dans une JTable
● Le modèle de sélection (TableSelectionModel) utilise également des possibilités de restriction de la sélection :
– sélectionner uniquement les lignes
– sélectionner uniquement les colonnes
– sélectionner les cellules individuellement
void TableSelectionModel.setRowSelectionAllowed(boolean)
boolean TableSelectionModel.getRowSelectionAllowed();
void TableSelectionModel.setColumnSelectionAllowed(boolean)
boolean TableSelectionModel.getColumnSelectionAllowed();
void TableSelectionModel.setCellSelectionAllowed(boolean)
boolean TableSelectionModel.getCellSelectionAllowed();
GL40
Stéphane GALLAND UTBM 2014 198
Répondre aux événements desélection dans une JTable
● Intercepter et répondre à un événement de sélection sur une JTable est simple.
● Il faut implanter un ListSelectionListener et l'enregistrer auprès du JTable avec la fonction addListSelectionListener() :
ListSelectionListener listener = new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {// Réaction à une selection décrite par// l'événement e
}};
table.getSelectionModel().
addListSelectionListener(listener);
GL40
Stéphane GALLAND UTBM 2014 199
Répondre aux événements dechangement des données dans une JTable
● Intercepter et répondre à un événement de changement des données dans une JTable est simple.
● Il faut implanter un TableModelListener et l'enregistrer auprès du modèle de la JTable avec la fonction addTableModelListener() :
TableModelListener listener = new TableModelListener() {
public void tableChanged(TableModelEvent e) {// Réaction à un changement dans les données
}};
table.getModel().
addTableModelListener(listener);
GL40
Stéphane GALLAND UTBM 2014 200
Dessiner librement des formes
GL40
Stéphane GALLAND UTBM 2014 201
Bibliothèque AWT
● La bibliothèque AWT est à la base des applications graphiques écritent en Java. La bibliothèque SWING est une extension de la bibliothèque AWT.
● La bibliothèque AWT fournit un ensemble d'outils permettant de gérer l'affichage des composants.
● Chaque composant graphique possède une fonction qui permet de le dessiner à l'écran. Cette fonction s'appelle :
– void paint(Graphics g)
● La fonction paint() est appelée à chaque fois que le contenu du composant doit être dessiné :
– la 1ére fois qu'il est dessiné,– quand le composant est masqué puis démasqué, ...
GL40
Stéphane GALLAND UTBM 2014 202
Comment dessiner librement
● Un composant peut dessiner ce qu'il veut sur l'écran.● Pour cela il doit implanter une fonction paint().● En général les composants qui se dessine de cette manière sont des
classes filles du composant JPanel.
● Exemple d'un panneau qui affiche l'heure actuelle :
class ClockDisplayer extends JPanel {
public void paint(Graphics g) {Graphics2D g2d = (Graphics2D)g;Date currentDate = new Date();g2d.drawString(currentDate.toString(), 0, 0);
}}
GL40
Stéphane GALLAND UTBM 2014 203
Contexte graphique
● La fonction paint() prend en paramètre un contexte graphique (une représentation informatique d'écran d'ordinateur). La bibliothèque AWT appelle la fonction paint() en passant un paramètre un objet de type Graphics2D
class ClockDisplayer extends JPanel {
public void paint(Graphics g) {Graphics2D g2d = (Graphics2D)g;Date currentDate = new Date();g.drawString(currentDate.toString(), 0, 0);
}}
● Le contexte graphique est un objet qui est capable de dessiner directement sur l'écran.
● Par conséquent, les classes Graphics et Graphics2D proposent des fonctions permettant de dessiner.
GL40
Stéphane GALLAND UTBM 2014 204
Dessiner une chaîne de caractères
● Dessiner une chaîne de caractère est possible avec la fonction :
void drawString(String text, int x, int y);
● Exemple :
class ClockDisplayer extends JPanel {
public void paint(Graphics g) {Graphics2D g2d = (Graphics2D)g;Date currentDate = new Date();g.drawString(currentDate.toString(), 0, 0);
}}
GL40
Stéphane GALLAND UTBM 2014 205
Dessiner une ligne
● Dessiner une ligne entre deux points est possible avec la fonction :
void drawLine(int x1, int y1, int x2, int y2);
● Exemple :
class LineDisplayer extends JPanel {
public void paint(Graphics g) {Graphics2D g2d = (Graphics2D)g;Dimension size = getSize();int x1, x2, y1, y2;x1 = y1 = 0;x2 = 0 + size.width;y2 = 0 + size.height;g.drawLine(x1,y1,x2,y2);
}}
GL40
Stéphane GALLAND UTBM 2014 206
Changer la couleur
● Changer la couleur d'affichage :
void setColor(Color red);
● Exemple :
class StringDisplayer extends JPanel {
public void paint(Graphics g) {Graphics2D g2d = (Graphics2D)g;g2d.setColor(new Color(255,0,0));g2d.drawString("Exemple", 0,0);
}}
● L'objet Color définie une couleur à partir des composantes Rouge, Verte et Bleue.
GL40
Stéphane GALLAND UTBM 2014 207
Autres fonctions
● Les classes Graphics et Graphics2D proposent de nombreuses fonctions permettant de dessiner sur l'écran.
● Ce support de cours ne fait pas la liste de toutes les fonctions. Veuillez regarder la documentation officiel Java des classes Graphics et Graphics2D pour avoir une liste complète
– manuel de référence : http://java.sun.com/javase/reference/api.jsp– explications et tutoriels : http://java.sun.com/javase/6/docs/
GL40
Stéphane GALLAND UTBM 2014 208
Exercice corrigé
GL40
Stéphane GALLAND UTBM 2014 209
Exercice 3
● Réaliser une application permettant d'explorer le contenu d'un système de fichier.
● L'application devra avoir l'interface suivante (vous pourrez changer les images à votre convenance) :
GL40
Stéphane GALLAND UTBM 2014 210
Cours GL40
Interface graphiquePartie 2 : Modèle-Vue-Contrôleur
Dr.habil. Stéphane [email protected]
Université de Technologie de Belfort-Montbéliard (UTBM)
GL40
Stéphane GALLAND UTBM 2014 211
Plan du cours
● Architecture MVC● Rôles des 3 éléments du MVC● Intérêts de l'architecture MVC● L'architecture MVC et SWING● Implantation d'un MVC en Java● Exemple : liste d'éléments
GL40
Stéphane GALLAND UTBM 2014 212
Architecture Modèle Vue Contrôleur (MVC)
● Architecture logicielle (design pattern) qui permet de séparer :– les objets applicatifs(Model)
– leur représentation (View)
– les interactions qu'ils subissent (Controler)
● Utilisée pour la programmation de client/serveur, et d'interfaces graphiques
● Généralisation du design pattern Observer/observable présenté dans la partie précédente.
GL40
Stéphane GALLAND UTBM 2014 213
Architecture Modèle Vue Contrôleur (MVC)
● Schéma de programmation qui permet de séparer une application en 3 parties :– Applicatif – le modèle contient la logique de
l'application.
– Visuel – les vues affichent à l’utilisateur des informations sur le modèle.
– Événementiel – le contrôleur agit sur demande de l'utilisateur et effectue les actions nécessaires sur le modèle.
GL40
Stéphane GALLAND UTBM 2014 214
Architecture Modèle Vue Contrôleur (MVC)
Modèle
Vue Contrôleur
Utilisateur
manipuleMet à jour
Est perçue par Utilise
agit sur
GL40
Stéphane GALLAND UTBM 2014 215
Architecture Modèle Vue Contrôleur (MVC)
Modèle
Vue Contrôleur
Utilisateur
manipuleMet à jour
Est perçue par Utilise
agit sur
Evénements graphiques provenant de l'utilisateur
Mise à jour en cas de changement de contenuSignale tout changement
de contenu
GL40
Stéphane GALLAND UTBM 2014 216
Architecture Modèle Vue Contrôleur (MVC)
Contrôleur
Utilisateur
Vue Modèle
événementsgraphiques
Mise à jourdu contenu
Notification dechangementLecture du
contenu
Affichage
GL40
Stéphane GALLAND UTBM 2014 217
Architecture Modèle Vue Contrôleur (MVC)
Contrôleur
Utilisateur
Vue Modèle
événementsgraphiques
Mise à jourde l'affichage
Affichage
GL40
Stéphane GALLAND UTBM 2014 218
Exemple 1
● Document texte (modèle : chaîne de caractères html) peut avoir deux vues :– une vue WYSIWYG (What You See is What you
Get) vue par un navigateur
– une vue brute : code html source avec balises vue par un éditeur de textes
● Toute modification sur le modèle se répercute dans les deux vues
GL40
Stéphane GALLAND UTBM 2014 219
Exemple 2
● Application de calcul du budget d’une société– le modèle : les données et le procédures de calcul
pour le budget prévisionnel de la société
– les vues : une représentation sous forme de tableau, une sous forme graphique, une vue pour la direction, une pour la Direction des Ressources Humaines,...
– le contrôleur : des éléments de l’interface pour faire varierles paramètres du calcul
GL40
Stéphane GALLAND UTBM 2014 220
Rôle du contrôleur
● Reçoit les événements de l'interface utilisateur● Traduit ces événements :
– en changement dans la vue s'ils agissent sur le côté visuel
● exemple : clic dans l'ascenseur de la fenêtre
– en changement dans le modèle s'ils agissent sur le contenu dumodèle
● exemple : on réajuste le camembert, on modifie le diagramme en bâtons en agissant dans la vue
GL40
Stéphane GALLAND UTBM 2014 221
Rôle du modèle
● Il peut être modifié sur ordre du contrôleur● Il signale à ses vues tout changement de
contenu en leur envoyant un événement qui leur spécifie de se mettre à jour
● Mais il ignore :– comment il est affiché
– qui lui a notifié un changement d'état
GL40
Stéphane GALLAND UTBM 2014 222
Rôle de la vue
● La vue se met à jour dès qu'elle reçoit un ordre de notification– du contrôleur
– du modèle
● Quand la notification vient du modèle, elle va consulter le modèle pour se réafficher de manière adéquate
GL40
Stéphane GALLAND UTBM 2014 223
Intérêts de l'architecture MVC
● Indépendance entre :
– la représentation logique d'une application (modèle)
– la représentation visuelle qu’on en donne (vue)
– les actions que l ’utilisateur effectue (contrôleur)
⇒ Séparation claire entre les données du programme et l’interface graphique affichant ces données
⇒ Possibilités de vues différentes d'un même modèle
L'application peut montrer l'état du modèle de différentes façons, avecdifférentes interfaces utilisateurs
GL40
Stéphane GALLAND UTBM 2014 224
Intérêts de l'architecture MVC
● Cette indépendance favorise le développement et la maintenance des applications :
– Modularité dans la conception● vue et contrôleur peuvent être développés
indépendamment du modèle (pourvu qu'une interface entre les deux soit définie)
– Meilleure répartition des tâches● développeurs du modèle/développeurs de
l'interface ont des compétences différentes– développeurs du modèle : connaissance
métier– développeurs de l ’interface : connaissance
des besoins utilisateurs, souci d’ergonomie...●
GL40
Stéphane GALLAND UTBM 2014 225
Architecture MVC et SWING
● Chaque composant SWING s'appuie sur une architecture MVC en l'adaptant : la vue et le contrôleur sont combinés en un même objet
● Pour beaucoup de composants, cette architecture n’est pas exploitée (JButton,...)
● Pour d’autres, elle est très importante : JList, JTable
● L’architecture MVC fonctionne en utilisant la notiond’événemen
GL40
Stéphane GALLAND UTBM 2014 226
Fonctionnement du MVC avec lanotion d'événement notifié aux vues
● Le modèle doit connaître les vues qui dépendent de lui
● Dès que le modèle change,
– il crée un événement correspondant à ce changement
– il envoie cet événement à toutes ses vues– ses vues, à la notification de l’événement,
réagissent en conséquence, en mettant à jour leur apparence visuelle.
GL40
Stéphane GALLAND UTBM 2014 227
Implantation en Java des modèles
● Tous les composants SWING reposent sur le même principe:
– les modèles sont des interfaces XXModel– des classes abstraites AbstractXXModel
implémentent l’interface en fournissant le code de certaines méthodes
● de gestion du modèle (modification,...),● d'ajouts de vue● des méthodes de notification d’événements
● Le modèle mémorise l'ensemble de ses vues
GL40
Stéphane GALLAND UTBM 2014 228
Implantation en Java des vues et contrôleurs
● Les vues sont interfaces XXListener correspondant à des écouteurs d’événements
● Les événements correspondant à des changements dans le modèle sont des XXEvent
● Dès qu’un tel événement est notifié à une vue, elle réagit en déclenchant la méthode appropriée
● Les vues doivent connaître le modèlevue sur un modèle = composant qui s'est déclaré
comme écouteur d'événements de changement sur le modèle
GL40
Stéphane GALLAND UTBM 2014 229
Comment réaliser un MVC en Java
● Définir un modèle● Définir le composant qui sera une vue sur ce
modèle :
– Il doit se déclarer écouteur des événements de changement dans le modèle en implantant l'interface adéquate
– Il doit mémoriser le modèle en variable membre– Il doit donner un corps à chaque méthode de
l’interface– Il doit se faire ajouter à la liste des écouteurs du
modèle
GL40
Stéphane GALLAND UTBM 2014 230
Exemple
● La suite de ce cours illustre l'implantation en Java de l'architecture MVC sur l'exemple d'une liste d'élements
GL40
Stéphane GALLAND UTBM 2014 231
Exemple – Modèle MVC
● MVC
– Modèle : interface ListModel, classe abstraite AbstractListModel et classe DefaultListModel
– Vue : interface ListDataListener concernée par les changements sur le modèle : ajout/suppression d'éléments de la liste
– Evénement transmis du modèle aux vues : ListDataEvent
GL40
Stéphane GALLAND UTBM 2014 232
Exemple – Le modèle
● Par exemple, une instance de la classe DefaultListModel ou d’une sous-classe que vous créerez
● Il mémorise l’ensemble des données et fournit des méthodes qui permettent de manipuler ces données
void addElement(Object obj)boolean contains(Object elem)Object get(int index)boolean removeElement(Object obj)Object remove (int index)int size()
GL40
Stéphane GALLAND UTBM 2014 233
Exemple – Le modèle
● Il mémorise la liste des vues (ListDataListener) et fournit des méthodes d'ajout/suppression de tels écouteurs
void addListDataListener(ListDataListenerlistener);
void removeListDataListener(ListDataListener listener);
GL40
Stéphane GALLAND UTBM 2014 234
Exemple – Le modèle
● Il fournit des méthodes de notification d'événements à ses vues qu’il adresse à ses vues quand il se modifie
void fireContentsChanged(Object source, int index0, int index1)
void fireIntervalAdded(Object source, int index0, int index1)
void fireIntervalRemoved(Object source, int index0, int index1)
GL40
Stéphane GALLAND UTBM 2014 235
Exemple – La vue sur le modèle
● doit implémenter l'interface ListDataListener● doit donner un corps aux 3 méthodes :
– void contentsChanged(ListDataEvent e);
● en réponse à fireContentsChanged déclenchée dans le modèle ;
● reçu quand le contenu de la liste a changé
GL40
Stéphane GALLAND UTBM 2014 236
Exemple – La vue sur le modèle
● doit donner un corps aux 3 méthodes (suite):
– void intervalAdded(ListDataEvent e)
● en réponse à la méthode fireIntervalAdded déclenchée dans le modèle;
● reçu quand un intervalle (index0,index1) a été inséré dans le modèle
GL40
Stéphane GALLAND UTBM 2014 237
Exemple – La vue sur le modèle
● doit donner un corps aux 3 méthodes (suite) :
– void intervalRemoved(ListDataEvent e)
● en réponse à fireIntervalRemoved;● reçue quand l'intervalle a été enlevé
GL40
Stéphane GALLAND UTBM 2014 238
Exemple – L'événement de notification de changement
● Evénement de la classe ListDataEvent à exploiter par la vue pour savoir ce qui a changé dans le modèle.
● ListDataEvent posséde les méthodes :
public int getIndex0()public int getIndex1()public int getType()//renvoie un mnemonique pour le type de// l'evenement (defini en constante)// CONTENTS_CHANGED// INTERVAL_ADDED// INTERVAL_REMOVED
GL40
Stéphane GALLAND UTBM 2014 239
Exemple – Interaction entre modèle et vue
● Quand le modèle (l’ensemble d’objets) change parce qu'on lui a ajouté ou retiré un (ou plusieurs) élément(s),
● Le modèle
– construit un événement de type ListDataEvent prenant en compte le type de modifications
– notifie les écouteurs ListDataListener présents dans sa liste du changement. Pour cela, il déclenche la méthode correspondante, fireYY().
GL40
Stéphane GALLAND UTBM 2014 240
Exemple – Interaction entre modèle et vue
● Quand le modèle (l’ensemble d’objets) change parce qu'on lui a ajouté ou retiré un (ou plusieurs) élément(s),
● La vue
– déclenche la méthode correspondante– peut utiliser l'événement qu'elle a en paramètre
GL40
Stéphane GALLAND UTBM 2014 241
Exemple – Composant SWING encapsulant le MVCClasse JList
● La classe JList est un composant graphique de SWING qui affiche une liste
● Les données à afficher sont présentes dans un modèle sous-jacent (ListModel)
● JList est une classe "Wrapper"
– Elle écoute les événements reçus du modèle – Elle y réagit « toute seule »
⇒ Toute modification du modèle se répercutera dans la liste sans rien avoir à déclarer, ni faire de particulier
⇒ Transparent pour l’utilisateur
GL40
Stéphane GALLAND UTBM 2014 242
Exemple – Résumé
● Modèle (ensemble de nombres entiers) à créer et mémoriser : instance de la classe DefaultListModel
● Vue sur ce modèle : une JList dans le panneau central qui affiche cet ensemble
● On peut ajouter des entiers à la liste en les entrant dans une zone de texte située dans le panneau nord
● La vue doit se mettre à jour automatiquement
GL40
Stéphane GALLAND UTBM 2014 243
Exemple – Analyse
Modèle de typeDefaultListModel :
jModelUtilisateur
Zone de texte où unnombre entier peut êtresaisie : jNumberInput
Vue sous la formed'une liste :
jNumberListView
fournit les donnéesau modèle
le modèle s'affiche sousforme d'une liste
GL40
Stéphane GALLAND UTBM 2014 244
Exemple – Analyse
● jNumberListView : instance de JList possédant comme modèle : jModel.
=> utilisation du constructeur :
public JList<>(ListModel<> m)● jNumberInput : instance de JTextField devant
prévenir le modèle si l'utilisateur entre un nouveau nombre
=> lui associer un écouteur de classe ActionListener réalisant ce travail (l'événement ActionEvent est construit quand l'utilisateur tapera sur 'retour chariot' dans la zone de texte).
GL40
Stéphane GALLAND UTBM 2014 245
Exemple – Implantation
public class ExempleMVC extends JFrame {
private final JTextField jNumberInput;
private final JList<Number> jNumberListView;
private final DefaultListModel<Number> jModel;
public FenEnsembleMVC(String titre) {
super(titre);
jModel = new DefaultListModel<>();
jNumberListview = new JList<>(jModel);
jNumberInput = new JTextField();
initialize();
}
...
GL40
Stéphane GALLAND UTBM 2014 246
Exemple – Implantation
...
public void initialize() {
setBorderLayout(new BorderLayout());
add(BorderLayout.CENTER, jNumberListView);
add(BorderLayout.TOP, jNumberInput);
jNumberInput.addActionListener(
new InsertNumberHandler());}
...
GL40
Stéphane GALLAND UTBM 2014 247
Exemple – Implantation
...
private class InsertNumberHandler // Inner-class
implements ActionListener {
public void actionPerformed(ActionEvent e) {
String s = jNumberInput.getText();try {
jModel.addElement(new Integer(Integer.parseInt(s)));
}catch(NumberFormatException ex) {}jNumberInput.setText("");
}
}
}
GL40
Stéphane GALLAND UTBM 2014 248
Exemple – Remarque 1 sur l'implantation
...
private class InsertNumberHandler // Inner-class
implements ActionListener {
public void actionPerformed(ActionEvent e) {
String s = jNumberInput.getText();try {
jModel.addElement(new Integer(Integer.parseInt(s)));
}catch(NumberFormatException ex) {}jNumberInput.setText("");
}
}
} Le modèle se modifie ici part la méthode addElement()
GL40
Stéphane GALLAND UTBM 2014 249
Exemple – Remarque 2 sur l'implantation
...
private class InsertNumberHandler // Inner-class
implements ActionListener {
public void actionPerformed(ActionEvent e) {
String s = jNumberInput.getText();try {
jModel.addElement(new Integer(Integer.parseInt(s)));
}catch(NumberFormatException ex) {}jNumberInput.setText("");
}
}
}
ATTENTION: Dans un DefaultListModel, il est possible den'y placer que des Object, donc :● impossible d'y ranger directment une valeur de type int● on y rangera la représentation objet d'un int : Integer,
après avoir vérifier la validité du format numérique
GL40
Stéphane GALLAND UTBM 2014 250
Exemple – Implantation
public class ExempleMVC extends JFrame {
private final JTextField jNumberInput;
private final JList<Number> jNumberListView;
private final DefaultListModel<Number> jModel;
public FenEnsembleMVC(String titre) {
super(titre);
jModel = new DefaultListModel();
jNumberListview = new Jlist(jModel);
jNumberInput = new JTextField();
initialize();
}
...
Toute modification du modèle se répercute automatiquementdans la JList sans que le programmeur fasse quelque chose.
En effet, un objet de type JList est un « wrapper » qui gèreautomatiquement et sans intervention extérieure lesinteractions entre le modèle et la vue.
GL40
Stéphane GALLAND UTBM 2014 251
Exercices
GL40
Stéphane GALLAND UTBM 2014 252
Exercice 1
● Proposer l'implantation d'un MVC basé sur l'exemple précédent en introduisant un affichage dans une zone de texte.
● Remarque : une zone de texte est une instance de la classe JLabel
JLabel
void setText(String)String getText()
GL40
Stéphane GALLAND UTBM 2014 253
Exercice 2
● Proposer une implantation de la classe DefaultListModel afin que celle-ci puisse être utilisée comme cela est illustré dans l'exemple de ce support de cours.
GL40
Stéphane GALLAND UTBM 2014 254
A propos de l'auteur
Maître de Conférences (HDR)
Laboratoire IRTES-SET
Département Informatique
Université de Technologie de Belfort-Montbéliard
Page: http://www.multiagent.fr/People:Galland_stephane
Email: [email protected]
Contributions Open-source :
– http://www.janus-project.org
– http://www.arakhne.org