0% ont trouvé ce document utile (0 vote)
14 vues45 pages

Cours Swing

Transféré par

djihanekhadraoui6
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
14 vues45 pages

Cours Swing

Transféré par

djihanekhadraoui6
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

01/11/2019 Cours Java et Eclipse de J.M.

Doudoux

FORUMS TUTORIELS MAGAZINE FAQ BLOGS CHAT NEWSLETTER ÉTUDES EMPLOI CLUB

ALM Java .NET Dév. Web EDI Programmation SGBD Office Solutions d'entreprise Applications Mobiles Systèmes

Java Java Web Spring Android Eclipse NetBeans

Forums Java FAQ Java Tutoriels Java Livres Java Vidéos Java Sources Java Outils, EDI & API Java JavaSearch

Développons en Java 2.10

Copyright (C) 1999-2016 Jean-Michel DOUDOUX (date de publication : 19/03/2016)

[ Précédent ] [ Sommaire ] [ Suivant ] [Télécharger ] [Accueil ]

38. Le développement d'interfaces graphiques avec SWING

Niveau : Intermédiaire

Swing fait partie de la bibliothèque Java Foundation Classes (JFC). C'est une API dont le but est similaire à celui de l'API AWT mais dont les modes
de fonctionnement et d'utilisation sont complètement différents. Swing a été intégré au JDK depuis sa version 1.2. Cette bibliothèque existe
séparément. pour le JDK 1.1.

La bibliothèque JFC contient :

l'API Swing : de nouvelles classes et interfaces pour construire des interfaces graphiques
Accessibility API :
2D API: support du graphisme en 2D
API pour l'impression et le cliquer/glisser

Ce chapitre contient plusieurs sections :

La présentation de Swing
Les packages Swing
Un exemple de fenêtre autonome
Les composants Swing
Les boutons
Les composants de saisie de texte
Les onglets
Le composant JTree
Les menus
L'affichage d'une image dans une application.

38.1. La présentation de Swing


Swing propose de nombreux composants dont certains possèdent des fonctions étendues, une utilisation des mécanismes de gestion
d'événements performants (ceux introduits par le JDK 1.1) et une apparence modifiable à la volée (une interface graphique qui emploie le style
du système d'exploitation Windows ou Motif ou un nouveau style spécifique à Java nommé Metal).

Tous les éléments de Swing font partie d'un package qui a changé plusieurs fois de nom : le nom du package dépend de la version du J.D.K.
utilisée :

[Link] : jusqu'à la version 1.1 beta 2 de Swing, de la version 1.1 des JFC et de la version 1.2 beta 4 du J.D.K.
[Link] : utilisé par le J.D.K. 1.2 beta 2 et 3
[Link] : à partir des versions de Swing 1.1 beta 3 et J.D.K. 1.2 RC1

Les composants Swing forment un nouvelle hiérarchie parallèle à celle de l'AWT. L'ancêtre de cette hiérarchie est le composant JComponent.
Presque tous ses composants sont écrits en pur Java : ils ne possèdent aucune partie native sauf ceux qui assurent l'interface avec le système
d'exploitation : JApplet, JDialog, JFrame, et JWindow. Cela permet aux composants de toujours avoir la même apparence quelque soit le système
sur lequel l'application s'exécute.

Tous les composants Swing possèdent les caractéristiques suivantes :

[Link] 1/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
ce sont des beans
ce sont des composants légers (pas de partie native) hormis quelques exceptions.
leurs bords peuvent être changés

La procédure à suivre pour utiliser un composant Swing est identique à celle des composants de la bibliothèque AWT : créer le composant en
appelant son constructeur, appeler les méthodes du composant si nécessaire pour le personnaliser et l'ajouter dans un conteneur.

Swing utilise la même infrastructure de classes qu'AWT, ce qui permet de mélanger des composants Swing et AWT dans la même interface. Il est
toutefois recommandé d'éviter de les utiliser simultanément car certains peuvent ne pas être restitués correctement.

Les composants Swing utilisent des modèles pour contenir leurs états ou leurs données. Ces modèles sont des classes particulières qui possèdent
toutes un comportement par défaut.

38.2. Les packages Swing


Swing contient plusieurs packages :

package principal : il contient les interfaces, les principaux


[Link]
composants, les modèles par défaut

[Link] Classes représentant les bordures

[Link] Classes définissant un composant pour la sélection de couleurs

Classes et interfaces pour les événements spécifiques à Swing. Les


[Link]
autres événements sont ceux d'AWT ([Link])

[Link] Classes définissant un composant pour la sélection de fichiers

[Link] Classes et interfaces génériques pour gérer l'apparence

[Link] Classes et interfaces de base pour gérer l'apparence

Classes et interfaces pour définir l'apparence Metal qui est


[Link]
l'apparence par défaut

Classes définissant un composant pour la présentation de données


[Link]
sous forme de tableau

Classes et interfaces de bases pour les composants manipulant du


[Link]
texte

[Link] Classes permettant le support du format HTML

[Link] Classes permettant d'analyser des données au format HTML

[Link] Classes permettant le support du format RTF

Classes définissant un composant pour la présentation de données


[Link]
sous forme d'arbre

[Link] Classes permettant d'implémenter les fonctions annuler/refaire

38.3. Un exemple de fenêtre autonome


La classe de base d'une application est la classe JFrame. Son rôle est équivalent à la classe Frame de l'AWT et elle s'utilise de la même façon.

Exemple ( code Java 1.1 ) :

import [Link].*;
import [Link].*;

public class swing1 extends JFrame {

public swing1() {
super("titre de l'application");

[Link] 2/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
WindowListener l = new WindowAdapter() {
public void windowClosing(WindowEvent e){
[Link](0);
}
};

addWindowListener(l);
setSize(200,100);
setVisible(true);
}

public static void main(String [] args){


JFrame frame = new swing1();
}
}

38.4. Les composants Swing


Il existe des composants Swing équivalents pour chacun des composants AWT avec des constructeurs semblables. De nombreux constructeurs
acceptent comme argument un objet de type Icon, qui représente une petite image généralement stockée au format Gif.

Le constructeur d'un objet Icon admet comme seul paramètre le nom ou l'URL d'un fichier graphique

Exemple ( code Java 1.1 ) :

import [Link].*;
import [Link].*;

public class swing3 extends JFrame {

public swing3() {

super("titre de l'application");

WindowListener l = new WindowAdapter() {


public void windowClosing(WindowEvent e){
[Link](0);
}
};

addWindowListener(l);

ImageIcon img = new ImageIcon("[Link]");


JButton bouton = new JButton("Mon bouton",img);

JPanel panneau = new JPanel();


[Link](bouton);
setContentPane(panneau);
setSize(200,100);
setVisible(true);
}

public static void main(String [] args){


JFrame frame = new swing3();
}
}

38.4.1. La classe JFrame


JFrame est l'équivalent de la classe Frame de l'AWT : les principales différences sont l'utilisation du double buffering qui améliore les
rafraichissements et l'utilisation d'un panneau de contenu (contentPane) pour insérer des composants (ils ne sont plus insérés sans le JFrame
mais dans l'objet contentPane qui lui est associé). Elle représente une fenêtre principale qui possède un titre, une taille modifiable et
éventuellement un menu.

La classe possède plusieurs constructeurs :

Constructeur Rôle

JFrame()

JFrame(String) Création d'une instance en précisant le titre

Par défaut, la fenêtre créée n'est pas visible. La méthode setVisible() permet de l'afficher.

Exemple ( code Java 1.1 ) :

import [Link].*;

public class TestJFrame1 {

public static void main(String argv[]) {


JFrame f = new JFrame("ma fenetre");
[Link](300,100);
[Link](true);
}
}

[Link] 3/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
La gestion des événements est identique à celle utilisée dans l'AWT depuis le J.D.K. 1.1.

Exemple ( code Java 1.1 ) :

import [Link].*;
import [Link].*;

public class swing2 extends JFrame {

public swing2() {

super("titre de l'application");

WindowListener l = new WindowAdapter() {


public void windowClosing(WindowEvent e){
[Link](0);
}
};
addWindowListener(l);

JButton bouton = new JButton("Mon bouton");


JPanel panneau = new JPanel();
[Link](bouton);

setContentPane(panneau);
setSize(200,100);
setVisible(true);
}

public static void main(String [] args){


JFrame frame = new swing2();
}
}

Tous les composants associés à un objet JFrame sont gérés par un objet de la classe JRootPane. Un objet JRootPane contient plusieurs Panes.
Tous les composants ajoutés au JFame doivent être ajoutés à un des Pane du JRootPane et non au JFrame directement. C'est aussi à un de ces
Panes qu'il faut associer un layout manager si nécessaire.

Le Pane le plus utilisé est le ContentPane. Le Layout manager par défaut du contentPane est BorderLayout. Il est possible de le changer :

Exemple ( code Java 1.1 ) :

...
[Link]().setLayout(new FlowLayout());
...

Exemple ( code Java 1.1 ) :

import [Link].*;

public class TestJFrame2 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JButton b =new JButton("Mon bouton");
[Link]().add(b);
[Link](true);
}
}

Le JRootPane se compose de plusieurs éléments :

glassPane : un JPanel par défaut


layeredPane qui se compose du contentPane (un JPanel par défaut) et du menuBar (un objet de type JMenuBar)

Le glassPane est un JPanel transparent qui se situe au-dessus du layeredPane. Le glassPane peut être n'importe quel composant : pour le modifier
il faut utiliser la méthode setGlassPane() en fournissant le composant en paramètre.

Le layeredPane regroupe le contentPane et le menuBar.

Le contentPane est par défaut un JPanel opaque dont le gestionnaire de présentation est un BorderLayout. Ce panel peut être remplacé par
n'importe quel composant grâce à la méthode setContentPane().

Attention : il ne faut pas utiliser directement la méthode setLayout()


d'un objet JFrame sinon une exception est levée.

Exemple ( code Java 1.1 ) :

[Link] 4/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
import [Link].*;
import [Link].*;

public class TestJFrame7 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](new FlowLayout());
[Link](300,100);
[Link](true);
}
}

Résultat :

C:\swing\code>java TestJFrame7
Exception in thread "main" [Link]: Do not use [Link]
out() use [Link]().setLayout() instead
at [Link](Unknown Source)
at [Link](Unknown Source)
at [Link]([Link])

Le menuBar permet d'attacher un menu à la JFrame. Par défaut, le menuBar est vide. La méthode setJMenuBar() permet d'affecter un menu à la
JFrame.

Exemple ( code Java 1.1 ) : Création d'un menu très simple

import [Link].*;
import [Link].*;

public class TestJFrame6 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JButton b =new JButton("Mon bouton");
[Link]().add(b);

JMenuBar menuBar = new JMenuBar();


[Link](menuBar);

JMenu menu = new JMenu("Fichier");


[Link](menuItem);
[Link](menu);

[Link](true);
}
}

[Link]. Le comportement par défaut à la fermeture

Il est possible de préciser comment un objet JFrame, JInternalFrame, ou JDialog réagit à sa fermeture grâce à la méthode
setDefaultCloseOperation(). Cette méthode attend en paramètre une valeur qui peut être :

Constante Rôle

WindowConstants.DISPOSE_ON_CLOSE détruit la fenêtre

WindowConstants.DO_NOTHING_ON_CLOSE rend le bouton de fermeture inactif

WindowConstants.HIDE_ON_CLOSE cache la fenêtre

Cette méthode ne permet pas d'associer d'autres traitements. Dans ce cas, il faut intercepter l'événement et lui associer les traitements.

Exemple ( code Java 1.1 ) : la fenêtre disparaît lors de sa fermeture mais l'application ne se termine pas.

import [Link].*;

public class TestJFrame3 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JButton b =new JButton("Mon bouton");
[Link]().add(b);

[Link](WindowConstants.DISPOSE_ON_CLOSE);

[Link](true);
}
}

[Link] 5/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
[Link]. La personnalisation de l'icône

La méthode setIconImage() permet de modifier l'icône de la JFrame.

Exemple ( code Java 1.1 ) :

import [Link].*;

public class TestJFrame4 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JButton b =new JButton("Mon bouton");
[Link]().add(b);
[Link](WindowConstants.DISPOSE_ON_CLOSE);

ImageIcon image = new ImageIcon("[Link]");


[Link]([Link]());
[Link](true);

}
}

Si l'image n'est pas trouvée, alors l'icône est vide. Si l'image est trop grande, elle est redimensionnée.

[Link]. Centrer une JFrame à l'écran

Par défaut, une JFrame est affichée dans le coin supérieur gauche de l'écran. Pour la centrer dans l'écran, il faut procéder comme pour une
Frame : déterminer la position de la Frame en fonction de sa dimension et de celle de l'écran et utiliser la méthode setLocation() pour affecter
cette position.

Exemple ( code Java 1.1 ) :

import [Link].*;
import [Link].*;

public class TestJFrame5 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JButton b =new JButton("Mon bouton");
[Link]().add(b);

[Link](WindowConstants.DISPOSE_ON_CLOSE);

Dimension dim = [Link]().getScreenSize();


[Link]([Link]/2 - [Link]()/2, [Link]/2 - [Link]()/2);

[Link](true);
}
}

[Link]. Les événements associées à un JFrame

La gestion des événements associés à un objet JFrame est identique à celle utilisée pour un objet de type Frame de AWT.

Exemple ( code Java 1.1 ) :

import [Link].*;
import [Link].*;

public class TestJFrame8 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
[Link](true);
[Link](new WindowAdapter() {
public void windowClosing(WindowEvent e) {
[Link](0);
}
}
);

}
}

38.4.2. Les étiquettes : la classe JLabel


[Link] 6/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
Le composant JLabel propose les mêmes fonctionnalités que les intitulés AWT mais ils peuvent en plus contenir des icônes .

Cette classe possède plusieurs constructeurs :

Constructeurs Rôle

JLabel() Création d'une instance sans texte ni image

JLabel(Icon) Création d'une instance en précisant l'image

JLabel(Icon, int) Création d'une instance en précisant l'image et l'alignement horizontal

JLabel(String) Création d'une instance en précisant le texte

Création d'une instance en précisant le texte, l'image et l'alignement


JLabel(String, Icon, int)
horizontal

JLabel(String, int) Création d'une instance en précisant le texte et l'alignement horizontal

Le composant JLabel permet d'afficher un texte et/ou une icône en précisant leur alignement. L'icône doit être au format GIF et peut être une
animation dans ce format.

Exemple ( code Java 1.1 ) :

import [Link].*;
import [Link].*;

public class TestJLabel1 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](100,200);

JPanel pannel = new JPanel();


JLabel jLabel1 =new JLabel("Mon texte dans JLabel");
[Link](jLabel1);

ImageIcon icone = new ImageIcon("[Link]");


JLabel jLabel2 =new JLabel(icone);
[Link](jLabel2);

JLabel jLabel3 =new JLabel("Mon texte",icone,[Link]);


[Link](jLabel3);

[Link]().add(pannel);
[Link](true);
}
}

La classe JLabel définit plusieurs méthodes pour modifier l'apparence du composant :

Méthodes Rôle

setText() Permet d'initialiser ou de modifier le texte affiché

setOpaque() Indique si le composant est transparent (paramètre false) ou opaque (true)

setBackground() Indique la couleur de fond du composant (setOpaque doit être à true)

setFont() Permet de préciser la police du texte

setForeGround() Permet de préciser la couleur du texte

setHorizontalAlignment() Permet de modifier l'alignement horizontal du texte et de l'icône

setVerticalAlignment() Permet de modifier l'alignement vertical du texte et de l'icône

setHorizontalTextAlignment() Permet de modifier l'alignement horizontal du texte uniquement

[Link] 7/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
setVerticalTextAlignment() Permet de modifier l'alignement vertical du texte uniquement

Exemple :

[Link]([Link]);

setIcon() Permet d'assigner une icône

setDisabledIcon() Permet de définir l'icône associée au JLabel lorsqu'il est désactivé

L'alignement vertical par défaut d'un JLabel est centré. L'alignement horizontal par défaut est soit à droite s'il ne contient que du texte, soit centré
s'il contient une image avec ou sans texte. Pour modifier cet alignement, il suffit d'utiliser les méthodes ci-dessus en utilisant des constantes en
paramètres : [Link], [Link], [Link], [Link], [Link]

Par défaut, un JLabel est transparent : son fond n'est pas dessiné. Pour le dessiner, il faut utiliser la méthode setOpaque() :

Exemple ( code Java 1.1 ) :

import [Link].*;
import [Link].*;

public class TestJLabel2 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");

[Link](100,200);
JPanel pannel = new JPanel();

JLabel jLabel1 =new JLabel("Mon texte dans JLabel 1");


[Link]([Link]);
[Link](jLabel1);

JLabel jLabel2 =new JLabel("Mon texte dans JLabel 2");


[Link]([Link]);
[Link](true);
[Link](jLabel2);

[Link]().add(pannel);
[Link](true);
}
}

Dans l'exemple, les 2 JLabel ont le fond rouge demandé par la méthode setBackground(). Seul le deuxième affiche un fond rouge car il est rendu
opaque avec la méthode setOpaque().

Il est possible d'associer un raccourci clavier au JLabel qui permet de donner le focus à un autre composant. La méthode setDisplayedMnemonic()
permet de définir le raccourci clavier. Celui-ci sera activé en utilisant la touche Alt avec le caractère fourni en paramètre. La méthode
setLabelFor() permet d'associer le composant fourni en paramètre au raccourci.

Exemple ( code Java 1.1 ) :

import [Link].*;
import [Link].*;

public class TestJLabel3 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JPanel pannel = new JPanel();

JButton bouton = new JButton("saisir");


[Link](bouton);

JTextField jEdit = new JTextField("votre nom");

JLabel jLabel1 =new JLabel("Nom : ");


[Link]([Link]);
[Link]('n');
[Link](jEdit);
[Link](jLabel1);
[Link](jEdit);

[Link]().add(pannel);
[Link](true);
}
}

Dans l'exemple, à l'ouverture de la fenêtre, le focus est sur le bouton. Un appui sur Alt+'n' donne le focus au champ de saisie.

38.4.3. Les panneaux : la classe JPanel

La classe JPanel est un conteneur utilisé pour regrouper et organiser des composants grâce à un gestionnaire de présentation (layout manager).
Le gestionnaire par défaut d'un JPanel est un objet de la classe FlowLayout.

[Link] 8/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

38.5. Les boutons


Il existe plusieurs boutons définis par Swing.

38.5.1. La classe AbstractButton


C'est une classe abstraite dont héritent les boutons Swing JButton, JMenuItem et JToggleButton.

Cette classe définit de nombreuses méthodes dont les principales sont :

Méthode Rôle

AddActionListener Associer un écouteur sur un événement de type ActionEvent

AddChangeListener Associer un écouteur sur un événement de type ChangeEvent

AddItemListener Associer un écouteur sur un événement de type ItemEvent

doClick() Déclencher un clic par programmation

getText() Obtenir le texte affiché par le composant

Associer une icône affichée lorsque le composant a l'état


setDisabledIcon()
désélectionné

Associer une icône affichée lors du passage de la souris sur le


setDisabledSelectedIcon()
composant à l'état désélectionné

setEnabled() Activer/désactiver le composant

setMnemonic() Associer un raccourci clavier

setPressedIcon() Associer une icône affichée lorsque le composant est cliqué

Associer une icône affichée lors du passage de la souris sur le


setRolloverIcon()
composant

Associer une icône affichée lors du passage de la souris sur le


setRolloverSelectedIcon()
composant à l'état sélectionné

setSelectedIcon() Associer une icône affichée lorsque le composant a l'état sélectionné

setText() Mettre à jour le texte du composant

isSelected() Indiquer si le composant est dans l'état sélectionné

Définir l'état du composant (sélectionné ou non selon la valeur fournie


setSelected()
en paramètre

[Link] 9/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

Tous les boutons peuvent afficher du texte et/ou une image.

Il est possible de préciser une image différente lors du passage de la souris sur le composant et lors de l'enfoncement du bouton : dans ce cas, il
faut créer trois images pour chacun des états (normal, enfoncé et survolé). L'image normale est associée au bouton grâce au constructeur,
l'image enfoncée grâce à la méthode setPressedIcon() et l'image lors d'un survol grâce à la méthode setRolloverIcon(). Il suffit enfin d'appeler la
méthode setRolloverEnable() avec en paramètre la valeur true.

Exemple ( code Java 1.1 ) :

import [Link].*;
import [Link].*;

public class swing4 extends JFrame {

public swing4() {
super("titre de l'application");

WindowListener l = new WindowAdapter() {


public void windowClosing(WindowEvent e){
[Link](0);
}
};
addWindowListener(l);

ImageIcon imageNormale = new ImageIcon("[Link]");


ImageIcon imagePassage = new ImageIcon("[Link]");
ImageIcon imageEnfoncee = new ImageIcon("[Link]");

JButton bouton = new JButton("Mon bouton",imageNormale);


[Link](imageEnfoncee);
[Link](imagePassage);
[Link](true);
getContentPane().add(bouton, "Center");

JPanel panneau = new JPanel();


[Link](bouton);
setContentPane(panneau);
setSize(200,100);
setVisible(true);
}

public static void main(String [] args){


JFrame frame = new swing4();
}
}

Un bouton peut recevoir des événements de type ActionEvents (le bouton a été activé), ChangeEvents, et ItemEvents.

Exemple ( code Java 1.1 ) : fermeture de l'application lors de l'activation du bouton

import [Link].*;
import [Link].*;

public class TestJButton3 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JPanel pannel = new JPanel();

JButton bouton1 = new JButton("Bouton1");


[Link]( new ActionListener() {
public void actionPerformed(ActionEvent e) {
[Link](0);
}
}
);

[Link](bouton1);
[Link]().add(pannel);
[Link](true);
}
}

Pour de plus amples informations sur la gestion des événements, voir le chapitre correspondant.

38.5.2. La classe JButton


JButton est un composant qui représente un bouton : il peut contenir un texte et/ou une icône.

Les constructeurs sont :

Constructeur Rôle
JButton()
JButton(String) préciser le texte du bouton
JButton(Icon) préciser une icône
JButton(String, Icon) préciser un texte et une icône

Il ne gère pas d'état. Toutes les indications concernant le contenu du composant JLabel sont valables pour le composant JButton.

[Link] 10/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
Exemple ( code Java 1.1 ) : un bouton avec une image

import [Link].*;
import [Link].*;

public class swing3 extends JFrame {

public swing3() {

super("titre de l'application");

WindowListener l = new WindowAdapter() {


public void windowClosing(WindowEvent e){
[Link](0);
}
};
addWindowListener(l);

ImageIcon img = new ImageIcon("[Link]");


JButton bouton = new JButton("Mon bouton",img);

JPanel panneau = new JPanel();


[Link](bouton);
setContentPane(panneau);
setSize(200,100);
setVisible(true);
}

public static void main(String [] args){


JFrame frame = new swing3();
}

L'image gif peut être une animation.

Dans un conteneur de type JRootPane, il est possible de définir un bouton par défaut grâce à sa méthode setDefaultButton().

Exemple ( code Java 1.1 ) : définition d'un bouton par défaut dans un JFrame

import [Link].*;
import [Link].*;

public class TestJButton2 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JPanel pannel = new JPanel();
JButton bouton1 = new JButton("Bouton 1");
[Link](bouton1);

JButton bouton2 = new JButton("Bouton 2");


[Link](bouton2);

JButton bouton3 = new JButton("Bouton 3");


[Link](bouton3);

[Link]().add(pannel);
[Link]().setDefaultButton(bouton3);
[Link](true);
}
}

Le bouton par défaut est activé par un appui sur la touche Entrée alors que le bouton actif est activé par un appui sur la barre d'espace.

La méthode isDefaultButton() de JButton permet de savoir si le composant est le bouton par défaut.

38.5.3. La classe JToggleButton


Cette classe définit un bouton à deux états : c'est la classe mère des composants JCheckBox et JRadioButton.

La méthode setSelected() héritée de AbstractButton permet de mettre à jour l'état du bouton. La méthode isSelected() permet de connaître cet
état.

38.5.4. La classe ButtonGroup

La classe ButtonGroup permet de gérer un ensemble de boutons en garantissant qu'un seul bouton du groupe sera sélectionné.

Pour utiliser la classe ButtonGroup, il suffit d'instancier un objet et d'ajouter des boutons (objets héritant de la classe AbstractButton) grâce à la
méthode add(). Il est préférable d'utiliser des objets de la classe JToggleButton ou d'une de ses classes filles car elles sont capables de gérer leurs
états.

Exemple ( code Java 1.1 ) :

import [Link].*;

public class TestGroupButton1 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JPanel pannel = new JPanel();

[Link] 11/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

ButtonGroup groupe = new ButtonGroup();


JRadioButton bouton1 = new JRadioButton("Bouton 1");
[Link](bouton1);
[Link](bouton1);
JRadioButton bouton2 = new JRadioButton("Bouton 2");
[Link](bouton2);
[Link](bouton2);
JRadioButton bouton3 = new JRadioButton("Bouton 3");
[Link](bouton3);
[Link](bouton3);

[Link]().add(pannel);
[Link](true);
}
}

38.5.5. Les cases à cocher : la classe JCheckBox


Les constructeurs sont les suivants :

Constructeur Rôle

JCheckBox(String) précise l'intitulé

JCheckBox(String, boolean) précise l'intitulé et l'état

JCheckBox(Icon) spécifie l'icône utilisée

JCheckBox(Icon, boolean) précise l'intitulé et l'état du bouton

JCheckBox(String, Icon) précise l'intitulé et l'icône

JCheckBox(String, Icon, boolean) précise l'intitulé, une icône et l'état

Un groupe de cases à cocher peut être défini avec la classe ButtonGroup. Dans ce cas, un seul composant du groupe peut être sélectionné. Pour
l'utiliser, il faut créer un objet de la classe ButtonGroup et utiliser la méthode add() pour ajouter un composant au groupe.

Exemple ( code Java 1.1 ) :

import [Link].*;

public class TestJCheckBox1 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JPanel pannel = new JPanel();

JCheckBox bouton1 = new JCheckBox("Bouton 1");


[Link](bouton1);
JCheckBox bouton2 = new JCheckBox("Bouton 2");
[Link](bouton2);
JCheckBox bouton3 = new JCheckBox("Bouton 3");
[Link](bouton3);

[Link]().add(pannel);
[Link](true);
}
}

38.5.6. Les boutons radio : la classe JRadioButton

Un objet de type JRadioButton représente un bouton radio d'un groupe de boutons . A un instant donné, un seul des boutons radio associés à un
même groupe peut être sélectionné. La classe JRadioButton hérite de la classe AbstractButton.

Un bouton radio possède un libellé et éventuellement une icône qui peut être précisée, pour chacun des états du bouton, en utilisant les
méthodes setIcon(), setSelectedIcon() et setPressedIcon().

Exemple ( code Java 1.1 ) :

import [Link].*;

public class TestJRadioButton1 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300,100);
JPanel pannel = new JPanel();

[Link] 12/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
JRadioButton bouton1 = new JRadioButton("Bouton 1");
[Link](bouton1);
JRadioButton bouton2 = new JRadioButton("Bouton 2");
[Link](bouton2);
JRadioButton bouton3 = new JRadioButton("Bouton 3");
[Link](bouton3);

[Link]().add(pannel);
[Link](true);
}
}

La méthode isSelected() permet de savoir si le bouton est sélectionné ou non.

La classe JRadioButton possède plusieurs constructeurs :

Constructeur Rôle

JRadioButton() Créer un bouton non sélectionné sans libellé

Créer un bouton non sélectionné sans libellé avec l'icône fournie en


JRadioButton(Icon)
paramètre

Créer un bouton sans libellé avec l'icône et l'état fournis en


JRadioButton(Icon, boolean)
paramètres

JRadioButton(String) Créer un bouton non sélectionné avec le libellé fourni en paramètre

JRadioButton(String, boolean) Créer un bouton avec le libellé et l'état fournis en paramètres

Créer un bouton non sélectionné avec le libellé et l'icône fournis en


JRadioButton(String, Icon)
paramètres

JRadioButton(String, Icon, boolean) Créer un bouton avec le libellé, l'icône et l'état fournis en paramètres

Un groupe de boutons radio est encapsulé dans un objet de type ButtonGroup.

Il faut ajouter tous les JRadioButton du groupe en utilisant la méthode add() de la classe ButtonGroup. Lors de la sélection d'un bouton, c'est
l'objet de type ButtonGroup qui se charge de déselectionner le bouton précédemment sélectionné dans le groupe.

Un groupe n'a pas l'obligation d'avoir un bouton sélectionné.

Exemple :

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class TestJRadioButton extends JFrame {


public static void main(String args[]) {
TestJRadioButton app = new TestJRadioButton();
[Link]();
}

public void init() {


[Link]("Test radio boutons");

[Link](JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridLayout(0,1));
Border border = [Link]("Sélection");
[Link](border);
ButtonGroup group = new ButtonGroup();
JRadioButton radio1 = new JRadioButton("Choix 1", true);
JRadioButton radio2 = new JRadioButton("Choix 2");
JRadioButton radio3 = new JRadioButton("Choix 3");
[Link](radio1);
[Link](radio1);
[Link](radio2);
[Link](radio2);
[Link](radio3);
[Link](radio3);
Container contentPane = [Link]();
[Link](panel, [Link]);
[Link](300, 150);
[Link](true);
}
}

[Link] 13/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

Exemple :

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class TestJRadioButton extends JFrame {


public static void main(String args[]) {
TestJRadioButton app = new TestJRadioButton();
[Link]();
}

public void init() {


[Link]("Test radio boutons");
[Link](JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridLayout(0, 1));
Border border = [Link]("Sélection");
[Link](border);

ButtonGroup group = new ButtonGroup();


JRadioButton radio1 = new JRadioButton("Choix 1");
[Link](KeyEvent.VK_1);
[Link]("Choix_1");
[Link](true);

JRadioButton radio2 = new JRadioButton("Choix 2");


[Link](KeyEvent.VK_2);
[Link]("Choix_2");

JRadioButton radio3 = new JRadioButton("Choix 3");


[Link](KeyEvent.VK_3);
[Link]("Choix_3");

[Link](radio1);
[Link](radio1);
[Link](radio2);
[Link](radio2);
[Link](radio3);
[Link](radio3);

Container contentPane = [Link]();


[Link](panel, [Link]);
[Link](300, 150);
[Link](true);
}
}

Lors de la sélection d'un bouton du groupe, il y a plusieurs événements qui peuvent être émis :

Un événement de type Action


Un événement de type Item émis par le bouton sélectionné
Un événement de type Item émis par le bouton désélectionné s'il y en a un

Exemple :

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class TestJRadioButton extends JFrame implements ActionListener, ItemListener {


public static void main(String args[]) {

[Link] 14/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
TestJRadioButton app = new TestJRadioButton();
[Link]();
}

public void init() {


[Link]("Test radio boutons");

[Link](JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridLayout(0, 1));
Border border = [Link]("Sélection");
[Link](border);
ButtonGroup group = new ButtonGroup();

JRadioButton radio1 = new JRadioButton("Choix 1");


[Link](KeyEvent.VK_1);
[Link]("Choix_1");
[Link](true);

JRadioButton radio2 = new JRadioButton("Choix 2");


[Link](KeyEvent.VK_2);
[Link]("Choix_2");

JRadioButton radio3 = new JRadioButton("Choix 3");


[Link](KeyEvent.VK_3);
[Link]("Choix_3");

[Link](radio1);
[Link](radio1);
[Link](radio2);
[Link](radio2);
[Link](radio3);
[Link](radio3);

[Link](this);
[Link](this);
[Link](this);
[Link](this);
[Link](this);
[Link](this);

Container contentPane = [Link]();


[Link](panel, [Link]);
[Link](300, 150);
[Link](true);
}

@Override
public void actionPerformed(ActionEvent e) {
[Link]("Clic sur le bouton : " + [Link]());
}

@Override
public void itemStateChanged(ItemEvent e) {
[Link]("Bouton " + ((JRadioButton) [Link]()).getActionCommand());
if ([Link]() == [Link])
[Link](" deselectionne");
if ([Link]() == [Link])
[Link](" selectionne");
}
}

La méthode getSelection() de la classe ButtonGroup renvoie le modèle du bouton radio sélectionné encapsulé dans un objet de type ButtonModel.

Pour déterminer le bouton sélectionné, il faut parcourir les boutons du groupe et comparer leurs modèles.

Exemple :

public static JRadioButton getBoutonSelectionne(ButtonGroup group) {


JRadioButton result = null;
for (Enumeration e = [Link](); [Link]();) {
JRadioButton bouton = (JRadioButton) [Link]();
if ([Link]() == [Link]()) {
result = bouton;
break;
}
}
return result;
}

38.6. Les composants de saisie de texte


Swing possède plusieurs composants pour permettre la saisie de texte.

[Link] 15/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

38.6.1. La classe JTextComponent

La classe abstraite JTextComponent est la classe mère de tous les composants permettant la saisie de texte.

Les données du composant (le modèle dans le motif de conception MVC) sont encapsulées dans un objet qui implémente l'interface Document.
Deux classes implémentant cette interface sont fournies en standard : PlainDocument pour du texte simple et StyledDocument pour du texte
riche pouvant contenir entre autres plusieurs polices de caractères, des couleurs, des images, ...

La classe JTextComponent possède de nombreuses méthodes dont les principales sont :

Méthode Rôle
void copy() Copier le contenu du texte et le mettre dans le presse papier système
void cut() Couper le contenu du texte et le mettre dans le presse papier système
Document getDocument() Renvoyer l'objet de type Document qui encapsule le texte saisi
String getSelectectedText() Renvoyer le texte sélectionné dans le composant
int getSelectionEnd() Renvoyer la position de la fin de la sélection
int getSelectionStart() Renvoyer la position du début de la sélection
String getText() Renvoyer le texte saisi
Renvoyer une portion du texte débutant à partir de la position donnée
String getText(int, int) par le premier paramètre et la longueur donnée dans le second
paramètre
bool isEditable() Renvoyer un booléen qui précise si le texte est éditable ou non
void paste() Coller le contenu du presse papier système dans le composant
Sélectionner une portion du texte dont les positions de début et de fin
void select(int,int)
sont fournies en paramètres
void setCaretPosition(int) Déplacer le curseur dans le texte à la position précisé en paramètre
void setEditable(boolean) Permet de préciser si les données du composant sont éditables ou non
void setSelectionEnd(int) Modifier la position de la fin de la sélection
void setSelectionStart(int) Modifier la position du début de la sélection
void setText(String) Modifier le contenu du texte

Toutes ces méthodes sont donc accessibles grâce à l'héritage pour tous les composants de saisie de texte proposés par Swing.

38.6.2. La classe JTextField


La classe [Link] est un composant qui permet la saisie d'une seule ligne de texte simple. Son modèle utilise un objet de type
PlainDocument.

Exemple ( code Java 1.1 ) :

import [Link].*;

public class JTextField1 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300, 100);
JPanel pannel = new JPanel();

[Link] 16/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
JTextField testField1 = new JTextField ("mon texte");

[Link](testField1);
[Link]().add(pannel);
[Link](true);
}
}

La propriété horizontalAligment permet de préciser l'alignement du texte dans le composant en utilisant les valeurs [Link] ,
[Link] ou [Link].

38.6.3. La classe JPasswordField

La classe JPasswordField permet la saisie d'un texte dont tous les caractères saisis seront affichés sous la forme d'un caractère particulier ('*' par
défaut). Cette classe hérite de la classe JTextField.

Exemple ( code Java 1.1 ) :

import [Link];

import [Link].*;

public class JPasswordField1 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300, 100);
JPanel pannel = new JPanel();

JPasswordField passwordField1 = new JPasswordField ("");


[Link](new Dimension(100,20 ));

[Link](passwordField1);
[Link]().add(pannel);
[Link](true);
}
}

La méthode setEchoChar(char) permet de préciser le caractère qui sera montré lors de la saisie.

Il ne faut pas utiliser la méthode getText() qui est déclarée deprecated mais la méthode getPassword() pour obtenir la valeur du texte saisi.

Exemple ( code Java 1.1 ) :

import [Link];
import [Link].*;

import [Link].*;

public class JPasswordField2 implements ActionListener {

JPasswordField passwordField1 = null;

public static void main(String argv[]) {


JPasswordField2 jpf2 = new JPasswordField2();
[Link]();
}

public void init() {


JFrame f = new JFrame("ma fenetre");
[Link](300, 100);
JPanel pannel = new JPanel();

passwordField1 = new JPasswordField("");


[Link](new Dimension(100, 20));
[Link](passwordField1);

JButton bouton1 = new JButton("Afficher");


[Link](this);

[Link](bouton1);
[Link]().add(pannel);
[Link](true);
}

public void actionPerformed(ActionEvent e) {

[Link]("texte saisie = " + [Link]([Link]()));


}

Les méthodes copy() et cut() sont redéfinies pour n'émettre qu'un bip. Elles empêchent l'exportation du contenu du champ.

[Link] 17/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
38.6.4. La classe JFormattedTextField

Le JDK 1.4 propose la classe JFormattedTextField pour faciliter la création d'un composant de saisie personnalisé. Cette classe hérite de la classe
JTextField.

38.6.5. La classe JEditorPane


Ce composant permet la saisie de texte riche multilignes. Ce type de texte peut contenir des informations de mise en pages et de formatage. En
standard, Swing propose le support des formats RTF et HTML.

Exemple ( code Java 1.1 ) : affichage de la page de Google avec gestion des hyperliens

import [Link];
import [Link].*;
import [Link].*;

public class JEditorPane1 {

public static void main(String[] args) {


final JEditorPane editeur;
JPanel pannel = new JPanel();

try {
editeur = new JEditorPane(new URL("[Link]
[Link](false);
[Link](new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if ([Link]() == [Link]) {
URL url = [Link]();
if (url == null)
return;
try {
[Link]([Link]());
} catch (Exception ex) {
[Link]();
}
}
}
});

[Link](editeur);
} catch (Exception e1) {
[Link]();
}
JFrame f = new JFrame("ma fenetre");
[Link](500, 300);

[Link]().add(pannel);
[Link](true);

}
}

38.6.6. La classe JTextPane

La suite de cette section sera développée dans une version future de ce document

[Link] 18/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
38.6.7. La classe JTextArea

La classe JTextArea est un composant qui permet la saisie de texte simple en mode multiligne. Le modèle utilisé par ce composant est le
PlainDocument : il ne peut donc contenir que du texte brut sans éléments multiples de formatage.

JTexteArea propose plusieurs méthodes pour ajouter du texte dans son modèle :

soit fournir le texte en paramètre du constructeur utilisé


soit utiliser la méthode setText() qui permet d'initialiser le texte du composant
soit utiliser la méthode append() qui permet d'ajouter du texte à la fin de celui contenu dans le composant
soit utiliser la méthode insert() qui permet d'insérer du texte dans le composant à une position données en caractères

La méthode replaceRange() permet de remplacer la partie de texte occupant les index donnés en paramètres par la chaîne fournie.

La propriété rows permet de définir le nombre de lignes affichées par le composant : cette propriété peut donc être modifiée lors d'un
redimensionnement du composant. La propriété lineCount en lecture seule permet de savoir le nombre de lignes qui composent le texte. Il ne faut
pas confondre ces deux propriétés.

Exemple ( code Java 1.1 ) :

import [Link].*;

public class JTextArea1 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300, 100);
JPanel pannel = new JPanel();

JTextArea textArea1 = new JTextArea ("mon texte");

[Link](textArea1);
[Link]().add(pannel);
[Link](true);
}
}

Par défaut, la taille du composant augmente au fur et à mesure de l'augmentation de la taille du texte qu'il contient. Pour éviter cet effet, il faut
encapsuler le JTextArea dans un JScrollPane.

Exemple ( code Java 1.1 ) :

import [Link];
import [Link].*;

public class JTextArea1 {

public static void main(String argv[]) {

JFrame f = new JFrame("ma fenetre");


[Link](300, 100);
JPanel pannel = new JPanel();
JTextArea textArea1 = new JTextArea ("mon texte");
JScrollPane scrollPane = new JScrollPane(textArea1);
[Link](new Dimension(200,70));
[Link](scrollPane);
[Link]().add(pannel);
[Link](true);
}
}

38.7. Les onglets


La classe [Link] encapsule un ensemble d'onglets. Chaque onglet est constitué d'un titre, d'un composant et éventuellement
d'une image.

Pour utiliser ce composant, il faut :

instancier un objet de type JTabbedPane


créer le composant de chaque onglet
ajouter chaque onglet à l'objet JTabbedPane en utilisant la méthode addTab()

Exemple ( code Java 1.1 ) :

import [Link];

[Link] 19/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
import [Link];

import [Link].*;

public class TestJTabbedPane1 {

public static void main(String[] args) {


JFrame f = new JFrame("Test JTabbedPane");
[Link](320, 150);
JPanel pannel = new JPanel();

JTabbedPane onglets = new JTabbedPane([Link]);

JPanel onglet1 = new JPanel();


JLabel titreOnglet1 = new JLabel("Onglet 1");
[Link](titreOnglet1);
[Link](new Dimension(300, 80));
[Link]("onglet1", onglet1);

JPanel onglet2 = new JPanel();


JLabel titreOnglet2 = new JLabel("Onglet 2");
[Link](titreOnglet2);
[Link]("onglet2", onglet2);

[Link](true);
[Link](onglets);
[Link]().add(pannel);
[Link](true);

}
}

A partir du JDK 1.4, il est possible d'ajouter un raccourci clavier sur chacun des onglets en utilisant la méthode setMnemonicAt(). Cette méthode
attend deux paramètres : l'index de l'onglet concerné (le premier commence à 0) et la touche du clavier associée sous la forme d'une constance
KeyEvent.VK_xxx. Pour utiliser ce raccourci, il suffit d'utiliser la touche désignée en paramètre de la méthode avec la touche Alt.

La classe JTabbedPane possède plusieurs méthodes qui permettent de définir le contenu de l'onglet :

Méthodes Rôles
Permet d'ajouter un nouvel onglet dont le titre et le composant sont
addTab(String, Component) fournis en paramètres. Cette méthode possède plusieurs surcharges
qui permettent de préciser une icône et une bulle d'aide
Permet d'insérer un onglet dont la position est précisée dans le dernier
insertTab(String, Icon, Component, String, index)
paramètre
remove(int) Permet de supprimer l'onglet dont l'index est fourni en paramètre
Permet de préciser le positionnement des onglets dans le composant
setTabPlacement JTabbedPane. Les valeurs possibles sont les constantes TOP, BOTTOM,
LEFT et RIGHT définies dans la classe JTabbedPane.

La méthode getSelectedIndex() permet d'obtenir l'index de l'onglet courant. La méthode setSelectedIndex() permet de définir l'onglet courant.

38.8. Le composant JTree


Le composant JTree permet de présenter des données sous une forme hiérarchique arborescente.

Au premier abord, le composant JTree peut sembler compliqué à mettre en oeuvre mais la compréhension de son mode de fonctionnement peut
grandement faciliter son utilisation.

Il utilise le modèle MVC en proposant une séparation des données (data models) et du rendu de ces données (cell renderers).

Dans l'arbre, les éléments qui ne possèdent pas d'élément fils sont des feuilles (leaf). Chaque élément est associé à un objet (user object) qui va
permettre de déterminer le libellé affiché dans l'arbre en utilisant la méthode toString().

38.8.1. La création d'une instance de la classe JTree


La classe JTree possède 7 constructeurs. Tous ceux qui attendent au moins un paramètre acceptent une collection pour initialiser tout ou partie du
modèle de données de l'arbre :

[Link] 20/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
public JTree();
public JTree(Hashtable value);
public JTree(Vector value);
public JTree(Object[] value);
public JTree(TreeModel model);
public JTree(TreeNode rootNode);
public JTree(TreeNode rootNode, boolean askAllowsChildren);

Lorsqu'une instance de JTree est créée avec le constructeur par défaut, l'arbre obtenu contient des données par défaut.

Exemple ( code Java 1.1 ) :

import [Link];
import [Link];

public class TestJtree extends JFrame {

private [Link] jContentPane = null;


private JTree jTree = null;

private JTree getJTree() {


if (jTree == null) {
jTree = new JTree();
}
return jTree;
}

public static void main(String[] args) {


TestJtree testJtree = new TestJtree();
[Link](true);
}

public TestJtree() {
super();
initialize();
}

private void initialize() {


[Link](300, 200);
[Link](getJContentPane());
[Link]("JFrame");
}

private [Link] getJContentPane() {


if (jContentPane == null) {
jContentPane = new [Link]();
[Link](new [Link]());
[Link](getJTree(), [Link]);
}
return jContentPane;
}
}

Les trois constructeurs qui attendent en paramètre une collection permettent de créer un arbre avec une racine non affichée qui va contenir
comme noeuds fils directs tous les éléments contenus dans la collection.

Exemple ( code Java 1.1 ) :

String[] racine = {"noeud 1","noeud 2","noeud3","noeud 4"};


jTree = new JTree(racine);

Dans ce cas, la racine n'est pas affichée. Pour l'afficher, il faut utiliser la méthode setRootVisible()

Exemple ( code Java 1.1 ) :

[Link](true);

[Link] 21/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

Dans ce cas elle se nomme root et possède un commutateur qui permet de refermer ou d'étendre la racine. Pour supprimer ce commutateur, il
faut utiliser la méthode [Link](false)

L'utilisation de l'une ou l'autre des collections n'est pas équivalente. Par exemple, l'utilisation d'une hashtable ne garantit pas l'ordre des noeuds
puisque par définition cette collection ne gère pas un ordre précis.

Généralement, la construction d'un arbre utilise un des constructeurs qui attend en paramètre un objet de type TreeModel ou TreeNode car ces
deux objets permettent d'avoir un contrôle sur l'ensemble des données de l'arbre. Leur utilisation sera détaillée dans la section consacrée à la
gestion des données de l'arbre.

En fonction du nombre d'éléments et de l'état étendu ou non d'un ou plusieurs éléments, la taille de l'arbre peut varier : il est donc nécessaire
d'inclure le composant JTree dans un composant JScrollPane

Exemple ( code Java 1.1 ) :

...

private JScrollPane jScrollPane = null;

...

private JScrollPane getJScrollPane() {


if (jScrollPane == null) {
jScrollPane = new JScrollPane();
[Link](getJTree());
}
return jScrollPane;
}

...

private [Link] getJContentPane() {


if (jContentPane == null) {
jContentPane = new [Link]();
[Link](new [Link]());
[Link](getJScrollPane(), [Link]);
}
return jContentPane;
}

L'utilisateur peut sélectionner un noeud en cliquant sur son texte ou son icône. Un double clic sur le texte ou l'icône d'un noeud permet de
l'étendre ou le refermer selon son état.

38.8.2. La gestion des données de l'arbre


Chaque arbre commence par un noeud racine. Par défaut, la racine et ses noeuds fils directs sont visibles. Chaque noeud de l'arbre peut avoir
zéro ou plusieurs noeuds fils. Un noeud sans noeud fils est appelé une feuille de l'arbre (leaf)

En application du modèle MVC, le composant JTree ne gère pas directement chaque noeud et la façon dont ceux-ci sont organisés et stockés mais
il utilise un objet dédié de type TreeModel.

Ainsi, comme dans d'autres composants Swing, le composant JTree manipule des objets implémentant des interfaces. Une classe qui encapsule
les données de l'arbre doit implémenter l'interface TreeModel. Chaque noeud de l'arbre doit implémenter l'interface TreeNode.

Pour préciser les données contenues dans l'arbre, il faut créer un objet qui va encapsuler ces données et les passer au constructeur de la classe
Jtree. Cet objet peut être de type TreeNode ou TreeModel. Un TreeModel stocke les données de chaque noeud dans un objet de type TreeNode.

[Link] 22/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
Généralement, le plus simple est de définir un type TreeNode personnalisé. Swing propose pour cela l'objet DefaultMutableTreeNode. il suffit d'en
créer une instance pour stocker les données et l'utiliser lors de l'appel du constructeur de la classe JTree.

La classe DefaultMutableTreeNode implémente l'interface MutableTreeNode qui elle-même hérite de l'interface TreeNode

Exemple ( code Java 1.1 ) :

import [Link];

...

private JTree getJTree() {

if (jTree == null) {
DefaultMutableTreeNode racine = new DefaultMutableTreeNode("Racine de l'arbre");
DefaultMutableTreeNode noeud1 = new DefaultMutableTreeNode("Noeud 1");
[Link](noeud1);
DefaultMutableTreeNode noeud2 = new DefaultMutableTreeNode("Noeud 2");
[Link](noeud2);
jTree = new JTree(racine);
}
return jTree;
}

Dans ce cas, une instance de la classe DefaultTreeModel est créée avec la racine fournie en paramètre du constructeur de la classe JTree.

Une autre solution permet de créer une instance de la classe DefaultTreeModel et de la passer en paramètre du constructeur de la classe JTree.

La méthode setModel() de la classe JTree permet d'associer un modèle de données à l'arbre.

[Link]. L'interface TreeNode

Chaque noeud de l'arbre stocké dans le modèle de données implémente l'interface TreeNode.

Cette interface définit 7 méthodes dont la plupart concernent les relations entre les noeuds :

Méthode Rôle
Enumeration children() renvoie une collection des noeuds fils
boolean getAllowsChildren() Renvoie un booléen qui precise si le noeud peut avoir des noeuds fils
TreeNode getChildAt(int index) Renvoie le noeud fils correspondant à l'index fourni en paramètre
int getChildCount() renvoie le nombre de noeuds fils directs du noeud
int getIndex(TreeNode child) renvoie l'index du noeud passé en paramètre
TreeNode getParent() renvoie le noeud père
boolean isLeaf() renvoie un booléen qui précise si le noeud est une feuille

Chaque noeud ne peut avoir qu'un seul père (hormis le noeud racine qui ne possède pas de père) et autant de noeuds fils que souhaité. La
méthode getParent() permet de renvoyer le noeud père. Elle renvoie null lorsque cette méthode est appelée sur le noeud racine.

La méthode getChildCount() renvoie le nombre de noeuds fils directs du noeud.

La méthode getAllowsChildren() permet de préciser si le noeud peut avoir des noeuds enfants : si elle renvoie false alors le noeud sera toujours
une feuille et ne pourra donc jamais avoir de noeuds fils.

La méthode isLeaf() renvoie un booléen précisant si le noeud est une feuille ou non. Une feuille est un noeud qui ne possède pas de noeud fils.

Les noeuds fils sont ordonnés car l'ordre de représentation des données peut être important dans la représentation de données hiérarchiques. La
méthode getChildAt() renvoie le noeud fils dont l'index est fourni en paramètre de la méthode. La méthode getIndex() renvoie l'index du noeud
fils passé en paramètre.

[Link]. L'interface MutableTreeNode

Les 7 méthodes définies par l'interface TreeNode ne permettent que de lire des valeurs. Pour mettre à jour un noeud, il est nécéssaire d'utiliser
l'interface MutableTreeNode qui hérite de la méthode TreeNode. Elle définit en plus plusieurs méthodes permettant de mettre à jour le noeud.

void insert(MutableTreeNode child, int index);


void remove(int index);
void remove(MutableTreeNode node);
void removeFromParent();
void setParent(MutableTreeNode parent);
void setUserObject(Object userObject);

La méthode insert() permet d'ajouter le noeud fourni en paramètre comme noeud fils à la position précisée par le second paramètre.

Il existe deux surcharges de la méthode remove() qui permettent de déconnecter un noeud fils de son père. La première surcharge attend en
paramètre l'index du noeud fils. La seconde surcharge attend en paramètre le noeud à déconnecter. Dans tous les cas, il est nécessaire d'utiliser
cette méthode sur le noeud père.

La méthode removeFromParent() appelée à partir d'un noeud permet de supprimer le lien entre le noeud et son père.

[Link] 23/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
La méthode setParent() permet de préciser le père du noeud.

La méthode setUserObject() permet d'associer un objet au noeud. L'appel à la méthode toString() de cet objet permettra de déterminer le libellé
du noeud qui sera affiché.

[Link]. La classe DefaultMutableTreeNode

Généralement, les noeuds créés dans le modèle sont des instances de la classe DefaultMutableTreeNode. Cette classe implémente l'interface
MutableTreeNode ce qui permet d'obtenir une instance d'un noeud modifiable.

Le plus souvent, les noeuds fournis en paramètres des méthodes proposées par Swing sont de type TreeNode. Si l'instance du noeud est de type
DefaultTreeNode, il est possible de faire un cast pour accéder à toutes ses méthodes.

La classe propose trois constructeurs dont deux attendent en paramètre l'objet qui sera associé au noeud. L'un des deux attend en plus un
booléen qui permet de préciser si le noeud peut avoir des noeuds fils.

Constructeur Rôle
Créer un noeud sans objet associé. Cette association pourra être
public DefaultMutableTreeNode()
faite avec la méthode setObject()
Créer un noeud en précisant l'objet qui lui sera associé et qui pourra
public DefaultMutableTreeNode(Object userObject)
avoir des noeuds fils
public DefaultMutableTreeNode(Object userObject, boolean
Créer un noeud dont le booléen précise s'il pourra avoir des fils
allowsChildren)

Pour ajouter une instance de la classe DefaultMutableTreeNode dans le modèle de l'arbre, il est possible d'utiliser la méthode insert() de l'interface
MutuableTreeNode ou utiliser la méthode add() de la classe DefaultMutableTreeNode. Celle-ci attend en paramètre une instance du noeud fils à
ajouter. Elle ajoute le noeud après le dernier noeud fils, ce qui évite d'avoir à garder une référence sur la position où insérer le noeud.

Exemple ( code Java 1.1 ) :

DefaultMutableTreeNode racineNode = new DefaultMutableTreeNode();


DefaultMutableTreeNode division1 = new DefaultMutableTreeNode("Division 1");
DefaultMutableTreeNode division2 = new DefaultMutableTreeNode("Division 2");
[Link](division1);
[Link](division2);
[Link](new DefaultTreeModel(racineNode));

Il est aussi possible de définir sa propre classe qui implémente l'interface MutableTreeNode : une possibilité est de définir une classe fille de la
classe DefaultMutableTreeNode.

38.8.3. La modification du contenu de l'arbre

Les modifications du contenu de l'arbre peuvent se faire au niveau du modèle (DefaultTreeModel) ou au niveau du noeud.

La méthode getModel() de la classe JTree permet d'obtenir une référence sur l'instance de la classe TreeModel qui encapsule le modèle de
données.

Il est ainsi possible d'accéder à tous les noeuds du modèle pour les modifier.

Exemple ( code Java 1.1 ) :

jTree = new JTree();


Object noeudRacine = [Link]().getRoot();
((DefaultMutableTreeNode)noeudRacine).setUserObject("Racine de l'arbre");

L'interface TreeModel ne propose rien pour permettre la mise à jour du modèle. Pour cela, il faut utiliser une instance de la classe
DefaultTreeModel.

Elle propose plusieurs méthodes pour ajouter ou supprimer un noeud :

void insertNodeInto(MutableTreeNode child, MutableTreeNode parent, int index)


void removeNodeFromParent(MutableTreeNode parent)

L'avantage de ces deux méthodes est qu'elles mettent à jour le modèle mais aussi qu'elles mettent à jour la vue en appelant respectivement les
méthodes nodesWereInserted() et nodesWereRemoved() de la classe DefaultTreeModel.

Ces deux méthodes sont donc pratiques pour faire des mises à jour mineures mais elles sont peut adaptées pour de nombreuses mises à jour
puisqu'elles déclenchent un événement à chacune de leurs utilisations.

[Link]. Les modifications des noeuds fils

La classe DefaultMutableTreeNode propose plusieurs méthodes pour mettre à jour le modèle à partir du noeud qu'elle encapsule.

void add(MutableTreeNode child)


void insert(MutableTreeNode child, int index)
void remove(int index)
[Link] 24/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
void remove(MutableTreeNode child)
void removeAllChildren()
void removeFromParent()

Toutes ces méthodes sauf la dernière agissent sur un ou plusieurs noeuds fils. Ces méthodes agissent simplement sur la structure du modèle.
Elles ne provoquent pas un affichage par la partie vue de ces changements. Pour cela il est nécessaire d'utiliser une des méthodes suivantes
proposées par la classe DefaultTreeModel :

Méthode Rôle
void reload() rafraichir toute l'arborescence à partir du modèle
rafraichir toute l'arborescence à partir du noeud précisé en
void reload(TreeNode node)
paramètre
pour le noeud précisé, cette méthode rafraichit les noeuds fils
void nodesWereInserted(TreeNode node, int[] childIndices)
ajoutés dont les index sont fournis en paramètre
void nodesWereRemoved(TreeNode node,int[] childIndices, Object[] pour le noeud précisé, cette méthode rafraichit les noeuds fils
removedChildren) supprimés dont les index sont fournis en paramètre
void nodeStructureChanged(TreeNode node) cette méthode est identique à la méthode reload()

[Link]. Les événements émis par le modèle

Il est possible d'enregistrer un listener de type TreeModelListener sur un objet de type DefaultTreeModel.

L'interface TreeModelListener définit quatre méthodes pour répondre à des événements particuliers :

Méthode Rôle

void treeNodesChanged(TreeModelEvent) la méthode nodeChanged() ou nodesChanged() est utilisée


void treeStructureChanged(TreeModelEvent) la méthode reload() ou nodeStructureChanged() est utilisée
void treeNodesInserted(TreeModelEvent) la méthode nodeWhereInserted() est utilisée

void treeNodesRemoved(TreeModelEvent) la méthode nodeWhereRemoved() est utilisée

Toutes ces méthodes ont un objet de type TreeModelEvent qui encapsule l'événement.

La classe TreeModelEvent propose cinq méthodes pour obtenir des informations sur les noeuds impactés par l'événement.

Méthode Rôle
renvoie une instance sur le modèle de l'arbre (généralement un objet
Object getSource()
de type DefaultTreeModel)
TreePath getTreePath() renvoie le chemin du noeud affecté par l'événement
Renvoie la succession de noeuds de la racine au noeud parent des
Object[] getPath()
noeuds impactés
Object[] getChildren()
int[] getChildIndices() retourne les index des noeuds modifiés

Dans la méthode treeStructureChanged(), seules les méthodes getPath() et getTreePath() fournissent des informations utiles en retournant le
noeud qui a été modifié.

Dans la méthode treeNodesChanged(), treeNodesRemoved() et treeNodesInserted() les méthodes getPath() et getTreePath() renvoient le noeud
père des noeuds affectés. Les méthodes getChildIndices() et getChidren() renvoient respectivement un tableau des index des noeuds fils modifiés
et un tableau de ces noeuds fils.

Dans ces méthodes, les méthodes getPath() et getTreePath() renvoient le noeud père des noeuds affectés.

Comme l'objet JTree enregistre ses propres listeners, il n'est pas nécessaire la plupart du temps, d'enregistrer ces listeners hormis pour des
besoins spécifiques.

[Link]. L'édition d'un noeud

Par défaut, le composant JTree est readonly. Il est possible d'autoriser l'utilisateur à modifier le libellé des noeuds en utilisant la méthode
setEditable() avec le paramètre true : [Link](true);

Pour éditer un noeud, il faut

sur un noeud non sélectionné : cliquer rapidement trois fois sur le noeud à modifier
sur un noeud déjà sélectionné : cliquer une fois sur le noeud ou appuyer sur la touche F2

[Link] 25/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
Pour valider les modifications, il suffit d'appuyer sur la touche « Entree ».

Pour annuler les modifications, il suffit d'appuyer sur la touche « Esc »

Il est possible d'enregistrer un listener de type TreeModelListerner pour assurer des traitements lors d'événements liés à l'édition d'un noeud.

L'interface TreeModelListener définit la méthode treeNodesChanged() qui permet de traiter les événements de type TreeModelEvent liés à la
modification d'un noeud.

Exemple ( code Java 1.1 ) :

[Link](true);
[Link]().addTreeModelListener(new TreeModelListener() {

public void treeNodesChanged(TreeModelEvent evt) {


[Link]("TreeNodesChanged");
Object[] noeuds = [Link]();
int[] indices = [Link]();
for (int i = 0; i < [Link]; i++) {
[Link]("Index " + indices[i] + ", nouvelle valeur : "
+ noeuds[i]);
}
}

public void treeStructureChanged(TreeModelEvent evt) {


[Link]("TreeStructureChanged");
}

public void treeNodesInserted(TreeModelEvent evt) {


[Link]("TreeNodesInserted");
}

public void treeNodesRemoved(TreeModelEvent evt) {


[Link]("TreeNodesRemoved");
}

});

[Link]. Les éditeurs personnalisés

Il est possible de définir un éditeur particulier pour éditer la valeur d'un noeud. Un éditeur particulier doit implémenter l'interface TreeCellEditor.

Cette interface hérite de l'interface CellEditor qui définit plusieurs méthodes utiles pour la création d'un éditeur dédié :

Object getCellEditorValue();
boolean isCellEditable(EventObject);
boolean shouldSelectCell(EventObject);
boolean stopCellEditing();
void cancelCellEditing();
void addCellEditorListener( CellEditorListener);
void removeCellEditorListener( CellEditorListener);

L'interface TreeCellEditor ne définit qu'une seule méthode :

Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row);

Cette méthode renvoie un composant qui va permettre l'édition de la valeur du noeud.

La valeur initiale est fournie dans le second paramètre de type Object. Les trois arguments de type booléen suivants permettent respectivement
de savoir si le noeud est sélectionné, est étendu et est une feuille.

Swing propose une implémentation de cette interface dans la classe DefaultCellEditor qui permet de modifier la valeur du noeud sous la forme
d'une zone de texte, d'une case à cocher ou d'une liste déroulante grâce à trois constructeurs :

public DefaultCellEditor(JTextField text); public DefaultCellEditor(JCheckBox box); public DefaultCellEditor(JComboBox combo);

La méthode setCellEditor() de la classe JTree permet d'associer le nouvel éditeur à l'arbre.

Exemple ( code Java 1.1 ) :

[Link](true);
String[] elements = { "Element 1", "Element 2", "Element 3", "Element 4"};
JComboBox jCombo = new JComboBox(elements);
DefaultTreeCellEditor editor = new DefaultTreeCellEditor(jTree,
new DefaultTreeCellRenderer(), new DefaultCellEditor(jCombo));
[Link](editor);

[Link]. La définition des noeuds éditables

Par défaut, si la méthode setEditable(true) est utilisée alors tous les noeuds sont modifiables.
[Link] 26/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
Il est possible de définir les noeuds de l'arbre qui sont éditables en créant une classe fille de la classe JTree et en redéfinissant la méthode
isPathEditable().

Cette méthode est appelée avant chaque édition d'un noeud. Elle attend en paramètre un objet de type TreePath qui encapsule le chemin du
noeud à éditer.

Par défaut, elle renvoie le résultat de l'appel à la méthode isEditable(). Il est d'ailleurs important, lors de la redéfinition de la méthode
isPathEditable(), de tenir compte du résultat de la méthode isEditable() pour s'assurer que l'arbre est modifiable avant de vérifier si le noeud peut
être modifié.

38.8.4. La mise en oeuvre d'actions sur l'arbre

[Link]. Etendre ou refermer un noeud

Pour étendre un noeud et ainsi voir ses fils, l'utilisateur peut double cliquer sur l'icône ou sur le libellé du noeud. Il peut aussi cliquer sur le petit
commutateur à gauche de l'icône.

Enfin, il est possible d'utiliser le clavier pour naviguer dans l'arbre à l'aide des touches flèches haut et bas et des touches flèches droite et gauche
pour respectivement étendre ou refermer un noeud. Lors d'un appui sur la flèche gauche, si le noeud est déjà fermé alors c'est le noeud père qui
est sélectionné. De la même façon, lors d'un appui sur la flèche droite, si le noeud est étendu alors le premier noeud fils est sélectionné.

La touche HOME permet de sélectionner le noeud racine. La touche END permet de sélectionner le noeud qui est la dernière feuille du dernier
noeud. Les touches PAGEUP et PAGEDOWN permettent de parcourir rapidement les noeuds de l'arbre.

Depuis Java 2 version 1.3, la méthode setToggleClickCount() permet de préciser le nombre de clics nécessaires pour étendre ou refermer un
noeud.

La classe JTree propose plusieurs méthodes liées aux actions permettant d'étendre ou de refermer un noeud.

Méthode Rôle

public void expandRow (int row) Etendre le noeud dont l'index est fourni en paramètre

public void collapseRow(int row) Refermer le noeud dont l'index est fourni en paramètre

Etendre le noeud encapsulé dans la classe TreePath fournie en


public void expandPath(TreePath path)
paramètre

Refermer le noeud encapsulé dans la classe TreePath fournie en


public void collapsePath(TreePath path)
paramètre

Renvoie un booléen qui précise si le noeud dont l'index est fourni en


public boolean isExpanded(int row)
paramètre est étendu

Renvoie un booléen qui précise si le noeud dont l'index est fourni en


public boolean isCollapsed (int row)
paramètre est refermé

Renvoie un booléen qui précise si le noeud encapsulé dans la classe


public boolean isExpanded(TreePath path)
TreePath fournie en paramètre est étendu

Renvoie un booléen qui précise si le noeud encapsulé dans la classe


public boolean isCollapsed (TreePath path)
TreePath fournie en paramètre est refermé

Par défaut, le noeud racine est étendu.

Les méthodes expandRow() et expandPath() ne permettent que d'étendre les noeuds fils directs du noeud sur lesquel elles sont appliquées. Pour
étendre les noeuds sous-jacents il est nécessaire d'écrire du code pour réaliser l'opération sur chaque noeud concerné de façon récursive.

Pour refermer tous les noeudsx et ne laisser que le noeud racine, il faut utiliser la méthode collapseRow() en lui passant 0 comme paramètre
puisque le noeud racine est toujours le premier noeud.

Exemple ( code Java 1.1 ) :

[Link](0);

La classe JTree propose deux méthodes pour forcer un noeud à être visible : scrollPathToVisible() et scrollRowToVisible(). Celles-ci ne peuvent
fonctionner que si le composant JTree est inclus dans un conteneur JScrollPane pour permettre au composant de scroller.

Exemple ( code Java 1.1 ) :

[Link](new TreeExpansionListener() {
public void treeExpanded(TreeExpansionEvent evt) {
[Link]("treeExpanded : path=" + [Link]());
[Link]([Link]());
}

[Link] 27/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

[Link]. La détermination du noeud sélectionné

Pour déterminer le noeud sélectionné, il suffit d'utiliser la méthode getLastSelectedPathComponent() de la classe JTree et de caster la valeur
retournée dans le type du noeud, généralement de type DefaultMutableTreeNode. La méthode getObject() du noeud permet d'obtenir l'objet
associé au noeud. Si l'objet associé est simplement une chaîne de caractères ou si la valeur nécessaire est simplement le libellé du noeud, il suffit
d'utiliser la méthode toString().

Exemple ( code Java 1.1 ) : un bouton qui précise lors d'un clic le noeud sélectionné

...
private JButton getJButton() {
if (jButton == null) {
jButton = new JButton();
[Link](new [Link]() {
public void actionPerformed([Link] e) {
[Link]("actionPerformed()");
[Link]("Noeud sélectionné : "
+ [Link]().toString());
}
});
}

[Link]. Le parcours des noeuds de l'arbre

Il peut être nécessaire de parcourir tout ou partie des noeuds de l'arbre pour par exemple faire une recherche dans l'arborescence.

Si l'arbre est composé de noeuds de type DefaultMutableTreenode alors l'interface TreeNode propose plusieurs méthodes pour obtenir une
énumération des noeuds. L'ensemble, ou seulement une partie des données, peut être parcouru dans les deux sens et selon deux types de
présentation des valeurs.

Enumeration preorderEnumeration();
Enumeration postorderEnumeration();
Enumeration breadthFirstEnumeration();
Enumeration depthFirstEnumeration();

Dans l'exemple ci-dessous, l'arborescence suivante est utilisée :

Exemple ( code Java 1.1 ) : un bouton qui précise lors d'un clic le noeud sélectionné

Enumeration e = ((DefaultMutableTreeNode)[Link]().getRoot()).preorderEnumeration();
while ([Link]()) {
[Link]([Link]() + " ");
}

Résultat :

preorder postorder breadthFirst depthFirst


Racine de l'arbre blue Racine de l'arbre blue
colors violet colors violet
blue red sports red
violet yellow food yellow
red colors blue colors
yellow basketball violet basketball
sports soccer red soccer
basketball football yellow football
soccer hockey basketball hockey
football sports soccer sports
hockey hot dogs football hot dogs
food pizza hockey pizza
hot dogs ravioli hot dogs ravioli
pizza bananas pizza bananas
ravioli food ravioli food
bananas Racine de l'arbre bananas Racine de l'arbre

[Link] 28/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

La méthode pathFromAncestorEnumeration(TreeNode ancestor) renvoie une énumération des noeuds entre le noeud sur lequel la méthode est
appelée et le noeud fourni en paramètre. Ainsi le noeud fourni en paramètre doit obligatoirement être un noeud fils direct ou indirect du noeud
sur lequel la méthode est appelée. Dans le cas contraire, une exception de type IllegalArgumentException est levée.

38.8.5. La gestion des événements

Il est possible d'attacher des listeners pour répondre aux événements liés à la sélection d'un élément ou l'extension ou la refermeture d'un noeud.

[Link]. La classe TreePath

Durant son utilisation, le composant JTree ne gère pas directement les noeuds du modèle de données. La manipulation de ces noeuds se fait via
un index ou une instance de la classe TreePath.

L'utilisation de l'index est assez délicate car seul le noeud racine de l'arbre possède toujours le même index 0. Pour les autres noeuds, la valeur
de l'index dépend de l'état étendu/refermé de chaque noeud puisque seuls les noeuds affichés possèdent un index. Il est donc préférable d'utiliser
la classe TreePath.

Le modèle de données utilise des noeuds mais l'interface de l'arbre utilise une autre représentation sous la forme de la classe TreePath.

La classe DefaultMutableTreeNode est la représentation physique d'un noeud, la classe TreePath est la représentation logique. Elle encapsule le
chemin du noeud dans l'arborescence.

Cette classe contient plusieurs méthodes :

public Object getLastPathComponent();


public Object getPathComponent(int index);
public int getPathCount();
public Object[] getPath();
public TreePath getParentPath();
public TreePath pathByAddingChild(Object child);
public boolean isDescendant(TreePath treePath)

La méthode getPath() renvoie un tableau d'objets contenant chaque noeud qui compose le chemin encapsulé par la classe TreePath.

La méthode getLastPathComponent() renvoie le dernier noeud du chemin.

La méthode getPathCount() renvoie le nombre de noeuds qui composent le chemin.

La méthode getPathComponent() permet de renvoyer le noeud dont l'index dans le chemin est fourni en paramètre. L'élément avec l'index 0 est
toujours le noeud racine de l'arbre.

La méthode getParentPath() renvoie une instance de la classe TreePath qui encapsule le chemin vers le noeud père du chemin encapsulé.

La méthode pathByAddingChild() renvoie une instance de la classe TreePath qui encapsule le chemin issu de l'ajout d'un noeud fils fourni en
paramètre.

La méthode idDescendant() renvoie un booléen qui précise si le chemin passé en paramètre est un descendant du chemin encapsulé.

La classe TreePath ne permet pas de gérer le contenu de chaque noeud mais uniquement son chemin dans l'arborescence. Pour accéder au noeud
à partir de son chemin, il faut utiliser la méthode getLastPathComponent(). Pour obtenir un noeud inclus dans le chemin, il faut utiliser la
getPathComponent() ou getPath(). Toutes ces méthodes renvoient un objet ou un tableau de type Object. Il est donc nécessaire de réaliser un
cast vers le type de noeud utilisé, généralement de type DefaultMutableTreeNode.

A partir d'un noeud de type DefaultMutableTreeNode, il est possible d'obtenir l'objet TreePath encapsulant le chemin du noeud. La méthode
getPath() permet d'obtenir un tableau d'objets de type TreeNode qu'il suffit de passer au constructeur de la classe TreePath.

Exemple ( code Java 1.1 ) :

TreeNode[] chemin = [Link]();


TreePath path = new TreePath(chemin);

[Link]. La gestion de la sélection d'un noeud

La gestion de la sélection de noeud dans un composant JTree est déléguée à un modèle de sélection sous la forme d'une classe qui implémente
l'interface TreeSelectionModel. Par défaut, le composant JTree utilise une instance de la classe DefaultTreeSelectionModel.

Le modèle de sélection peut être configuré selon trois modes :

SINGLE_TREE_SELECTION: un seul noeud peut être sélectionné.


CONTIGUOUS_TREE_SELECTION: plusieurs noeuds peuvent être sélectionnés à condition d'être contigus.
DISCONTIGUOUS_TREE_SELECTION: plusieurs noeuds peuvent être sélectionnés de façon continue et/ou discontinue (c'est le mode par
défaut).

Pour empêcher la sélection d'un noeud dans l'arbre, il faut supprimer son modèle de sélection en passant null à la méthode setSelectionModel().

Exemple ( code Java 1.1 ) :

JTree jTree = new JTree()[Link](null);

La sélection d'un noeud peut être réalisée par l'utilisateur ou par l'application : le modèle de sélection s'assure que celle-ci est réalisée en
respectant le mode de sélection du modèle.

L'utilisateur peut utiliser la souris pour sélectionner un noeud ou appuyer sur la touche Espace sur le noeud courant pour le sélectionner. Il est
possible de sélectionner plusieurs noeuds en fonction du mode en maintenant la touche CTRL enfoncée. Avec la touche SHIFT, il est possible selon
le mode de sélectionner tous les noeuds entre un premier noeud sélectionné et le noeud courant.

La sélection d'un noeud génère un événement de type TreeSelectionEvent.

[Link] 29/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
Le dernier noeud sélectionné peut être obtenu en utilisant les méthodes getLeadSelectionPath() ou getLeadSelectionRow().

Par défaut la sélection d'un noeud entraine l'extension des noeuds ascendants correspondant afin de les rendre visibles. Pour empêcher ce
comportement, il faut utiliser la méthode setExpandSelectedPath() en lui fournissant la valeur false en paramètre.

public void setExpandsSelectedPaths(boolean cond);

Les classes DefaultTreeSelectionModel et JTree possèdent plusieurs méthodes pour gérer la sélection de noeuds. Certaines de ces méthodes sont
communes à ces deux classes.

Méthode Rôle

int getSelectionMode() renvoie le mode de sélection

void setSelectionMode(int mode) mettre à jour le mode de sélection

renvoie le premier noeud de la sélection courante ou null si aucun


Object getLastSelectedPathComponent() noeud n'est sélectionné
JTree uniquement

TreePath getAnchorSelectionPath() JTree uniquement

void setAnchorSelectionPath(TreePathpath) JTree uniquement

TreePath getLeadSelectionPath() renvoie le dernier path ajouté à la sélection ou identifié comme tel

setLeadSelectionPath() fait de newPath le dernier Path ajouté

int getMaxSelectionRow() Renvoie le plus grand index de la sélection

int getMinSelectionRow() Renvoie le plus petit index de la sélection

int getSelectionCount() Renvoie le nombre de noeuds inclus dans la sélection

TreePath getSelectionPath() Renvoie le chemin du premier élément sélectionné

TreePath[] getSelectionPaths() Renvoie un tableau des chemins des noeuds inclus dans la sélection

int[] getSelectionRows() Renvoie un tableau des index des noeuds inclus dans la sélection

Renvoie un booléen si le noeud dont le chemin est fourni en


Boolean isPathSelected (TreePath path)
paramètre est inclus dans la sélection

Renvoie un booléen si le noeud dont l'index est fourni en paramètre


Boolean isRowSelected(int row)
est inclus dans la sélection

boolean isSelectionEmpty() Renvoie un booléen qui précise si la sélection est vide

void clearSelection() Vide la sélection

Enlève de la sélection les noeuds dans l'intervalle des index fournis


void removeSelectionInterval (int row0, int row1)
en paramètre

Enlève de la sélection le noeud dont le chemin est fourni en


void removeSelectionPath(TreePath path)
paramètre

Enlève de la sélection le noeud dont l'index est fourni en paramètre


void removeSelectionRow (int row)
JTree uniquement

void removeSelectionRows(int[] rows) Enlève de la sélection les noeuds dont les index sont fournis en
paramètre
JTree uniquement

[Link] 30/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

Ajouter à la sélection les noeuds dont l'intervalle des index est


void addSelectionInterval(int row0, int row1)
fourni en paramètre

Ajouter à la sélection le noeud dont le chemin est fourni en


void addSelectionPath(TreePath path)
paramètre

Ajouter à la sélection les noeuds dont les chemins sont fournis en


addSelectionPaths(TreePath[] path)
paramètre

void addSelectionRow(int row) Ajouter à la sélection le noeud dont l'index est fourni en paramètre

Ajouter à la sélection les noeuds dont les index sont fournis en


void addSelectionRows(int[] row)
paramètre

Définir la sélection avec les noeuds dont les index sont fournis en
void setSelectionInterval(int row0, int row1) paramètre
JTree uniquement

Définir la sélection avec le noeud dont le chemin est fourni en


setSelectionPath(TreePath path)
paramètre

Définir la sélection avec les noeuds dont les chemins sont fournis
void setSelectionPaths (TreePath[] path)
en paramètre

Définir la sélection avec le noeud dont l'index est fourni en


void setSelectionRow(int row)
paramètre

Définir la sélection avec les noeuds dont les index sont fournis en
void setSelectionRows(int[] row) paramètre
JTree uniquement

[Link]. Les événements lies à la sélection de noeuds

Lors de la sélection d'un noeud, un événement de type TreeSelectionEvent est émis. Pour traiter cet événement, le composant doit enregistrer un
listener de type TreeSelectionListener.

L'interface TreeSelectionListener définit une seule méthode :

public void valueChanged(TreeSelectionEvent evt)

Exemple ( code Java 1.1 ) :

[Link](new [Link]() {
public void valueChanged([Link] e) {

DefaultMutableTreeNode noeud = (DefaultMutableTreeNode) jTree


.getLastSelectedPathComponent();
if (noeud == null)
return;
[Link]("valueChanged() : " + noeud);
}
});

La classe TreeSelectionEvent possède plusieurs méthodes pour obtenir des informations sur la sélection.

Méthode Rôle

public TreePath[] getPaths() Renvoie un tableau des chemins des noeuds sélectionnés

Renvoie true si le noeud sélectionné est ajouté à la sélection.


public boolean isAddedPath (TreePath path)
Renvoie false si le noeud sélectionné est retiré de la sélection

TreePath getPath() Renvoie le chemin du premier noeud sélectionné

Renvoie true si le premier noeud sélectionné est ajouté à la sélection.


boolean isAddedPath()
Renvoie false si le premier noeud sélectionné est retiré de la sélection

TreePath getOldLeadSelection() Renvoie l'ancien lead path

[Link] 31/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

TreePath getNewLeadSelection() Renvoie le leader actuel de la sélection

Un listener de type TreeSelectionListener est enregistré en utilisant la méthode addTreeSelectionListener() de la classe JTree.

Exemple ( code Java 1.1 ) :

[Link](new TreeSelectionListener() {

public void valueChanged(TreeSelectionEvent e) {

Object obj = [Link]();


[Link]("getLastSelectedPathComponent=" + obj);
[Link]("getPath=" + [Link]());
[Link]("getNewLeadSelectionPath="
+ [Link]());
[Link]("getOldLeadSelectionPath="
+ [Link]());
TreePath[] paths = [Link]();

for (int i = 0; i < [Link]; i++) {


[Link]("Path " + i + "=" + paths[i]);
}
}
});

Un événement de type TreeSelectionEvent n'est émis que si un changement intervient dans la sélection : lors d'un clic sur un noeud, celui-ci est
sélectionné et un événement est émis. Lors d'un nouveau clic sur ce même noeud, le noeud est toujours sélectionné mais l'événement n'est pas
émis puisque la sélection n'est pas modifiée.

Dans un listener pour gérer les événements de la souris, il est possible d'utiliser la méthode getPathForLocation() pour déterminer le chemin d'un
noeud à partir des coordonnées de la souris qu'il faut lui fournir en paramètre.

La méthode getPathForLocation() renvoie null si l'utilisateur clique en dehors d'un noeud dans l'arbre.

Exemple ( code Java 1.1 ) :

[Link](new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
TreePath path =
[Link]([Link](), [Link]());
if (path != null) {
[Link]("path= " + [Link]());
}
}
});

Plusieurs autres méthodes peuvent aussi être utilisées dans ce contexte.

Méthode Rôle

Retourne le chemin du noeud le plus proche des coordonnées


TreePath getClosestPathForLocation(int x, int y)
fournies en paramètre

Retourne l'index du noeud le plus proche des coordonnées fournies


int getClosestRowForLocation(int x, int y)
en paramètre

Renvoie un objet de type Rectangle qui représente la surface du


Rectangle getPathBounds(TreePath path)
noeud dont le chemin est fourni en paramètre

Retourne le chemin du noeud dont la surface contient les


TreePath getPathForLocation(int x, int y) coordonnées fournies en paramètre. Renvoie null si ces coordonnées
ne correspondent à aucun noeud

TreePath getPathForRow(int row) Renvoie le chemin du noeud dont l'index est fourni en paramètre

Renvoie un objet de type Rectangle qui représente la surface du


Rectangle getRowBounds(int row)
noeud dont l'index est fourni en paramètre

int getRowForLocation(int x, int y) Renvoie l'index du noeud à la position fournie

[Link]. Les événements lorsqu'un noeud est étendu ou refermé

A chaque fois qu'un noeud est étendu ou refermé, un événement de type TreeExpansionEvent est émis. Il est possible de répondre à ces
événements en mettant en place un listener de type TreeExpansionListener.

L'interface TreeExpansionListener propose deux méthodes :

[Link] 32/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
public void treeExpanded(TreeExpansionEvent event) public void treeCollapsed(TreeExpansionEvent event)

La classe TreeExpansionEvent possède une propriété source qui contient une référence sur le composant JTree à l'origine de l'événement et une
propriété path qui contient un objet de type TreePath encapsulant le chemin du noeud à l'origine de l'événement.

Les valeurs de ces deux propriétés peuvent être obtenues avec leurs getters respectifs : getSource() et getPath().

Exemple ( code Java 1.1 ) :

[Link](new TreeExpansionListener() {

public void treeExpanded(TreeExpansionEvent evt) {


[Link]("expand, path=" +
[Link]());
}

public void treeCollapsed(TreeExpansionEvent evt) {


[Link]("collapse, path=" +
[Link]());
}

});

Un seul événement est généré à chaque fois qu'un noeud est étendu ou refermé : il n'y a pas d'événements émis pour les éventuels noeuds fils
qui sont étendus ou refermés suite à l'action.

[Link]. Le contrôle des actions pour étendre ou refermer un noeud

Il peut être utile de recevoir un événement avant qu'un noeud ne soit étendu ou refermé. Un listener de type TreeWillExpandListener() peut être
mis en place pour recevoir un événement de type TreeExpansionEvent lors d'une tentative pour étendre ou refermer un noeud.

L'interface TreeWillExpandListener définit deux méthodes :

public void treeWillCollapse(TreeExpansionEvent evt) throws ExpandVetoException;


public void treeWillExpand(TreeExpansionEvent evt) throws ExpandVetoException;

Les deux méthodes peuvent lever une exception de type ExpandVetoException. Cette exception est levée si, pendant l'exécution d'une de ces
méthodes, des conditions sont remplies pour empêcher l'action demandée par l'utilisateur. Si l'exception n'est pas levée à la fin des traitements
de la méthode alors l'action est réalisée.

Exemple ( code Java 1.1 ) : empécher tous les noeuds étendus de se refermer

[Link](new TreeWillExpandListener() {

public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {


throw new ExpandVetoException(event);
}

public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {


}

});

38.8.6. La personnalisation du rendu

Le rendu du composant JTree dépend bien sûr dans un premier temps du look and feel utilisé mais il est aussi possible de personnaliser plus
finement le rendu des noeuds du composant.

Il est possible de préciser la façon dont les lignes reliant les noeuds sont rendues via une propriété client nommée lineStyle. Cette propriété peut
prendre trois valeurs :

Valeur Rôle

Angled Une ligne à angle droit relie chaque noeud fils à son noeud père

None Aucune ligne n'est affichée entre les noeuds

Horizontal Une simple ligne horizontale sépare les noeuds enfants du noeud racine

Pour préciser la valeur de la propriété que le composant doit utiliser, il faut utiliser la méthode putClientProperty() qui attend deux paramètres
sous forme de chaînes de caractères :

le nom de la propriété
sa valeur

Exemple ( code Java 1.1 ) :

jTree = new JTree(racine);


[Link]("[Link]","Horizontal");

[Link] 33/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

None Angled Horizontal

Il est possible de modifier l'apparence de la racine de l'arbre grâce à deux méthodes de la classe JTree : setRootVisible() et
setShowsRootHandles().

La méthode setRootVisible() permet de préciser avec son booléen en paramètre si la racine est affichée ou non.

Exemple ( code Java 1.1 ) :

JTree jtree = new JTree();


[Link](false);
[Link](true);

[Link]. Personnaliser le rendu des noeuds

Il est possible d'obtenir un contrôle total sur le rendu de chaque noeud en définissant un objet qui implémente l'interface TreeCellRenderer.
Attention, le rendu personnalisé est parfois dépendant du look & feel utilisé.

L'interface TreeCellRenderer ne définit qu'une seule méthode :

Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean
hasFocus)

Cette méthode envoie un composant qui va encapsuler le rendu du noeud. Le premier argument de type JTree encapsule le composant JTree lui-
même. L'argument de type Object encapsule le noeud dont le rendu doit être généré.

La méthode getCellRenderer() renvoie un objet qui encapsule le TreeCellRenderer. Il est nécessaire de réaliser un cast vers le type de cet objet.

Swing propose une classe de base DefaultTreeCellRenderer pour le rendu. Elle propose plusieurs méthodes pour permettre de définir le rendu.

Méthode Rôle

Permet de définir la couleur de fond du noeud lorsqu'il n'est pas


void setBackgroundNonSelectionColor(Color)
sélectionné

Permet de définir la couleur de fond du noeud lorsqu'il est


void setBackgroundSelectionColor(Color)
sélectionné

Permet de définir la couleur de la bordure du noeud lorsqu'il est


void setBorderSelectionColor(Color) sélectionné. Il n'est pas possible de définir une bordure pour un
noeud sélectionné

Permet de définir la couleur du texte du noeud lorsqu'il n'est pas


void setTextNonSelectionColor(Color)
sélectionné

Permet de définir la couleur du texte du noeud lorsqu'il est


void setTextSelectionColor(Color)
sélectionné

Permet de définir la police de caractère utilisé pour afficher le texte


void setFont(Font)
du noeud

Permet de définir l'icône associée au noeud lorsque celui-ci est


void setClosedIcon(Icon)
fermé

Permet de définir l'icône associée au noeud lorsque celui-ci est


void setOpenIcon(Icon)
étendu

void setLeafIcon(Icon) Permet de définir l'icône associée au noeud lorsque celui-ci est une
feuille

[Link] 34/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

Un composant ne peut avoir qu'une seule instance de type TreeCellRenderer. Cette instance sera donc appelée pour définir le rendu de chaque
noeud.

Exemple ( code Java 1.1 ) :

TreeCellRenderer cellRenderer = [Link]();


if (cellRenderer instanceof DefaultTreeCellRenderer) {
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer)cellRenderer;
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
}

Résultat :

Pour modifier les icônes utilisées par les différents éléments de l'arbre, il faut utiliser les méthodes setOpenIcon(), setClosedIcon() et
setLeafIcon().

Méthode Rôle

setOpenIcon() précise l'icône pour un noeud ouvert

setClosedIcon() précise l'icône pour un noeud fermé

setLeafIcon() précise l'icône pour une feuille

Pour simplement supprimer l'affichage de l'icône, il suffit de passer null à la méthode concernée.

Exemple ( code Java 1.1 ) :

DefaultTreeCellRenderer monRenderer = new DefaultTreeCellRenderer();


[Link](null);
[Link](null);
[Link](null);

Pour préciser une image, il faut créer une instance de la classe ImageIcon encapsulant l'image et la passer en paramètre de la méthode
concernée.

Exemple ( code Java 1.1 ) :

private Icon ourvertIcon = new ImageIcon("images/[Link]");


private Icon fermeIcon = new ImageIcon("images/[Link]");
private Icon feuilleIcon = new ImageIcon("images/[Link]");
...
DefaultTreeCellRenderer treeCellRenderer = new DefaultTreeCellRenderer();
[Link](ouvertIcon);
[Link](fermeIcon);
[Link](feuilleIcon);

Il est aussi possible de définir une classe qui hérite de la classe DefaultTreeCellRenderer. Cette classe propose une implémentation par défaut de
l'interface TreeCellRenderer. Comme elle hérite de la classe JLabel, elle possède déjà de nombreuses méthodes pour assurer le rendu du noeud
sous la forme d'un composant de type étiquette.

Exemple ( code Java 1.1 ) :

import [Link];
import [Link];

import [Link];
import [Link];

public class MonTreeCellRenderer extends DefaultTreeCellRenderer {

public Component getTreeCellRendererComponent(JTree tree, Object value,


boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {

[Link](tree,value, selected, expanded,


leaf, row,hasFocus);

[Link] 35/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
setBackgroundNonSelectionColor([Link]);
setBackgroundSelectionColor([Link]);
setTextSelectionColor([Link]);
setTextNonSelectionColor([Link]);

return this;
}
}

Une fois la classe de type DefaultTreeCellRenderer instanciée, il faut utiliser la méthode setCellRenderer() de la classe JTree pour indiquer à l'arbre
d'utiliser cette classe pour le rendu.

Exemple ( code Java 1.1 ) :

[Link](new MonTreeCellRenderer());

La création d'une classe fille de la classe DefaultTreeCellRenderer ne fonctionne correctement qu'avec les look and feel Metal et Windows car le
look and feel Motif définit son propre Renderer.

[Link]. Les bulles d'aides (Tooltips)

Le composant JTree ne propose pas de support pour les bulles d'aide en standard. Pour permettre à un composant JTree d'afficher une bulle
d'aide, il faut :

enregistrer le composant JTree auprès du ToolTipManager


définir le contenu de la bulle d'aide dans le Renderer

L'enregistrement du composant auprès du ToolTipManager se fait en utilisant la méthode registerComponent() sur l'instance partagée.

Exemple ( code Java 1.1 ) :

[Link]().registerComponent(jTree);
((JLabel)[Link]()).setToolTipText("Arborescence des données");

L'inconvénient de cette méthode est que la bulle d'aide est toujours la même quelque soit la position de la souris sur tous les noeuds du
composant. Pour assigner une bulle d'aide particulière à chaque noeud, il est nécessaire d'utiliser la méthode setToolTipText() dans la méthode
getTreeCellRendererComponent() d'une instance fille de la classe DefaultTreeCellRenderer

Exemple ( code Java 1.1 ) :

[Link](new DefaultTreeCellRenderer() {

public Component getTreeCellRendererComponent(JTree tree, Object value,


boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {

[Link](tree, value, selected, expanded, leaf, row,


hasFocus);
setToolTipText([Link]());

return this;
}
});

[Link]().registerComponent(jTree);

38.9. Les menus


Les menus de Swing proposent certaines caractéristiques intéressantes en plus de celles proposées par un menu standard :

les éléments de menu peuvent contenir une icône


les éléments de menu peuvent être de type bouton radio ou case à cocher
les éléments de menu peuvent avoir des raccourcis clavier (accelerators)

Les menus sont mis en oeuvre dans Swing avec un ensemble de classe :

JMenuBar : encapsule une barre de menus


JMenu : encapsule un menu
JMenuItem : encapsule un élément d'un menu
JCheckBoxMenuItem : encapsule un élément d'un menu sous la forme d'une case à cocher
JRadioButtonMenuItem : encapsule un élément d'un menu sous la forme d'un bouton radio
JSeparator : encapsule un élément d'un menu sous la forme d'un séparateur
JPopupMenu : encapsule un menu contextuel

Toutes ces classes héritent de façon directe ou indirecte de la classe JComponent.

[Link] 36/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

Les éléments de menus cliquables héritent de la classe JAbstractButton.

JMenu hérite de la classe JMenuItem et non pas l'inverse car chaque JMenu contient un JMenuItem implicite qui encapsule le titre du menu.

La plupart des classes utilisées pour les menus implémentent l'interface MenuElement. Cette interface définit des méthodes pour la gestion des
actions standards de l'utilisateur. Ces actions sont gérées par la classe MenuSelectionManager.

Exemple :

package [Link];

import [Link].*;
import [Link].*;
import [Link].*;

public class TestMenuSwing1 extends JMenuBar {

public TestMenuSwing1() {

// Listener générique qui affiche l'action du menu utilisé

ActionListener afficherMenuListener = new ActionListener() {


public void actionPerformed(ActionEvent event) {
[Link]("Elément de menu [" + [Link]()
+ "] utilisé.");
}
};

// Création du menu Fichier

JMenu fichierMenu = new JMenu("Fichier");


JMenuItem item = new JMenuItem("Nouveau", 'N');
[Link](afficherMenuListener);
[Link](item);
item = new JMenuItem("Ouvrir", 'O');
[Link](afficherMenuListener);
[Link](item);
item = new JMenuItem("Sauver", 'S');
[Link](afficherMenuListener);
[Link](1);
[Link](item);
item = new JMenuItem("Quitter");
[Link](afficherMenuListener);
[Link](item);

// Création du menu Editer

JMenu editerMenu = new JMenu("Editer");


item = new JMenuItem("Copier");
[Link](afficherMenuListener);
[Link]([Link]('C', [Link]()
.getMenuShortcutKeyMask(), false));
[Link](item);
item = new JMenuItem("Couper");
[Link](afficherMenuListener);
[Link]([Link]('X', [Link]()
.getMenuShortcutKeyMask(), false));
[Link](item);
item = new JMenuItem("Coller");
[Link](afficherMenuListener);
[Link]([Link]('V', [Link]()
.getMenuShortcutKeyMask(), false));
[Link](item);

// Création du menu Divers

JMenu diversMenu = new JMenu("Divers");


JMenu sousMenuDiver1 = new JMenu("Sous menu 1");

[Link](afficherMenuListener);
item = new JMenuItem("Sous menu 1 1");
[Link](item);
[Link](afficherMenuListener);
JMenu sousMenuDivers2 = new JMenu("Sous menu 1 2");
item = new JMenuItem("Sous menu 1 2 1");
[Link](item);
[Link](sousMenuDivers2);

[Link](sousMenuDiver1);
item = new JCheckBoxMenuItem("Validé");
[Link](item);

[Link] 37/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
[Link](afficherMenuListener);
[Link]();
ButtonGroup buttonGroup = new ButtonGroup();
item = new JRadioButtonMenuItem("Cas 1");
[Link](item);
[Link](afficherMenuListener);
[Link](item);
item = new JRadioButtonMenuItem("Cas 2");
[Link](item);
[Link](afficherMenuListener);
[Link](item);
[Link]();
[Link](item = new JMenuItem("Autre",
new ImageIcon("about_32.png")));
[Link](afficherMenuListener);

// ajout des menus à la barre de menus

add(fichierMenu);
add(editerMenu);
add(diversMenu);
}

public static void main(String s[]) {


JFrame frame = new JFrame("Test de menu");
[Link](JFrame.EXIT_ON_CLOSE);
[Link](new TestMenuSwing1());
[Link](new Dimension(250, 200));
[Link]();
[Link](true);
}
}

Résultat :

38.9.1. La classe JMenuBar


La classe JMenuBar encapsule une barre de menus qui contient zéro ou plusieurs menus.

La classe JMenuBar utilise la classe DefaultSingleSelectionModel comme modèle de données : un seul de ces menus peut être activé à un instant
T.

Pour ajouter des menus à la barre de menus, il faut utiliser la méthode add() de la classe JMenuBar qui attend en paramètre l'instance du menu.

Pour ajouter la barre de menus à une fenêtre, il faut utiliser la méthode setJMenuBar() d'une instance des classes JFrame, JInternalFrame, JDialog
ou JApplet.

Comme la classe JMenuBar hérite de la classe JComponent, il est aussi possible d'instancier plusieurs JMenuBar et de les insérer dans un
gestionnaire de positionnement comme n'importe quel composant. Ceci permet aussi de placer le menu à sa guise.

Exemple :

...
public static void main(String s[]) {
JFrame frame = new JFrame("Test de menu");
[Link](JFrame.EXIT_ON_CLOSE);
TestMenuSwing1 menu = new TestMenuSwing1();
[Link]().add(menu, [Link]);
[Link](new Dimension(250, 200));
[Link]();
[Link](true);
}
...

Résultat :

[Link] 38/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

Swing n'impose pas d'avoir un unique menu par fenêtre : il est possible d'avoir plusieurs menus dans une même fenêtre.

Exemple :

...
public static void main(String s[]) {
JFrame frame = new JFrame("Test de menu");
[Link](JFrame.EXIT_ON_CLOSE);
[Link](new TestMenuSwing1());
TestMenuSwing1 menu = new TestMenuSwing1();
[Link]().add(menu, [Link]);
[Link](new Dimension(250, 200));
[Link]();
[Link](true);
}
...

La classe JMenuBar ne possède qu'un seul constructeur sans paramètre.

Les principales méthodes de la classe JMenuBar sont :

Méthodes Rôle

JMenu add(JMenu) Ajouter un menu à la barre de menus

JMenu getMenu(int) Obtenir le menu dont l'index est fourni en paramètre

int getMenuCount() Obtenir le nombre de menus de la barre de menus

MenuElement[] getSubElements() Obtenir un tableau de tous les menus

boolean isSelected() Retourner true si un composant du menu est sélectionné

Cette méthode n'est pas implémentée et lève systématiquement une


void setMenuHelp (JMenu)
exception

38.9.2. La classe JMenuItem


La classe JMenuItem encapsule les données d'un élément de menu (libellé et/ou image). Elle hérite de la classe AbstractButton. Le comportement
est similaire mais différent de celui d'un bouton : avec la classe JMenuItem, le composant est considéré comme sélectionné dès que le curseur de
la souris passe dessus.

Les éléments de menus peuvent être associés à deux types de raccourcis clavier :

les accelerators : ils sont hérités de JComponent : ce sont des touches (par exemple les touches de fonctions) ou des combinaisons de
touches avec les touches shift, Ctrl ou Alt qui sont affichées à la droite du libellé de l'élément du menu
les mnemonics : ils apparaissent sous la forme d'une lettre soulignée. Ils sont utilisables seulement sur certaines plate-formes (par exemple
en combinaison avec la touche Alt sous Windows).

La méthode setAccelerator() permet d'associer un accelerator à un élément de type JMenuItem.

Un mnemonic peut être associé à un JMenuItm de deux façons :

soit dans la surcharge du constructeur prévue à cet effet

[Link] 39/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
soit en utilisant la méthode setMnemonic()

Le mnemonic correspond à un caractère qui doit obligatoirement être contenu dans le libellé.

Un élément de menu peut contenir uniquement une image ou être composé d'un libellé et d'une image. Une image peut être associée à un
JMenuItem de deux façons :

soit dans une des surcharges du constructeur prévues à cet effet


item = new JMenuItem("Autre", new ImageIcon("about_32.png"));
item = new JMenuItem(new ImageIcon("about_32.png"));

soit en utilisant la méthode setIcon


[Link](new ImageIcon("about_32.png"));

38.9.3. La classe JPopupMenu

La classe JPopupMenu encapsule un menu flottant qui n'est pas rattaché à une barre de menus mais à un composant.

La création d'un JPopMenu est similaire à la création d'un JMenu.

Il est préférable d'ajouter un élément de type JMenuItem grâce à la méthode add() de la classe JPopupMenu mais on peut aussi ajouter
n'importe quel élément qui hérite de la classe Component en utilisant une surcharge de la méthode add().

Il est possible d'ajouter un élément à un index précis en utilisant la méthode insert().

La méthode addSeparator() permet d'ajouter un élément séparateur.

Pour afficher un menu flottant, il faut ajouter un listener sur l'événement déclenchant et utiliser la méthode show() de la classe JPopupMenu.

Exemple :

package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class TestMenuSwing2 extends JMenuBar {

public JPopupMenu popup;

public TestMenuSwing2() {

JMenuItem item = null;

// Listener générique qui affiche l'action du menu utilisé

ActionListener afficherMenuListener = new ActionListener() {


public void actionPerformed(ActionEvent event) {
[Link]("Elément de menu [" + [Link]()
+ "] utilisé.");
}
};

popup = new JPopupMenu();


item = new JMenuItem("Copier");
[Link](afficherMenuListener);
[Link](item);
item = new JMenuItem("Couper");
[Link](afficherMenuListener);
[Link](item);

public void processMouseEvent(MouseEvent e) {


}

public static void main(String s[]) {


final JFrame frame = new JFrame("Test de menu divers");
final JTextField texte = new JTextField();
[Link](JFrame.EXIT_ON_CLOSE);
final TestMenuSwing2 tms = new TestMenuSwing2();
[Link](texte);

[Link](new MouseAdapter() {

public void mouseClicked(MouseEvent e) {


[Link]("mouse clicked");
afficherPopup(e);
}

public void mousePressed(MouseEvent e) {


[Link]("mouse pressed");
afficherPopup(e);
}

public void mouseReleased(MouseEvent e) {


[Link]("mouse released");
afficherPopup(e);
}

[Link] 40/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
private void afficherPopup(MouseEvent e) {
if ([Link]()) {
[Link](texte, [Link](), [Link]());
}
}
});

[Link](new Dimension(250, 200));


[Link]();
[Link](true);
}
}

Le plus simple pour être multiplate-forme est de tester sur tous les événements de la souris ceux qui permettent l'affichage du menu flottant. Ce
test est réalisé grâce à la méthode isPopupTrigger() de la classe MouseEvent.

La propriété invoker encapsule le composant à l'origine de l'affichage du menu déroulant.


La propriété borderPaint indique si la bordure du menu déroulant doit être dessinée.
La propriété visible indique si le menu déroulant est affiché.
La propriété location indique les coordonnées d'affichage du menu déroulant

Un objet de type JPopupMenu peut émettre des événements de type PopupMenuEvent. Ceux-ci sont traités par un listener de type
PopupMenuListener qui définit trois méthodes :

Méthode Rôle
méthode appelée avant que l'affichage du menu déroulant ne soit
popupMenuCanceled()
annulé
popoupMenuWillBecomeInvisible() méthode appelée avant que le menu déroulant ne devienne invisible
méthode appelée avant que le menu déroulant ne devienne visible.
Cette méthode permet de personnaliser l'affichage des éléments du
popoupMenuWillBecomeVisible()
menu en fonction du contexte (exemple : rendre actif ou non
certains éléments du menu)

38.9.4. La classe JMenu

La classe JMenu encapsule un menu qui est attaché à un objet de type JMenuBar ou à un autre objet de type JMenu. Dans ce second cas, l'objet
est un sous menu.

Il est possible d'ajouter un élément sous la forme d'un objet de type JMenuItem, Component ou Action en utilisant la méthode add(). Chaque
élément du menu possède un index.

La méthode addSeparator() permet d'ajouter un élément de type séparateur.


La méthode remove() permet de supprimer un élément du menu en fournissant en paramètre l'instance de l'élément ou son index. Si la
suppression réussie, les index des éléments suivants sont décrémentés d'une unité.

La classe JMenu possède plusieurs propriétés :

Propriété Rôle
popupMenu JPopupMenu qui encapsule les éléments du menu
propriété en lecture seule qui précise si le menu est attaché à un
topLevelMenu JMenuBar. La valeur false indique que le menu est un sous-menu
attaché à un autre menu
itemCount indique le nombre d'éléments du menu (incluant les séparateurs)
delay précise le temps en millisecondes avant l'affichage du menu
menuComponentCount indique le nombre de composants du menu
tearOff ne pas utiliser cette propriété qui lève une exception de type Error

La méthode getMenuComponent() permet d'obtenir le composant du menu dont l'index est fourni en paramètre. La méthode getItem() permet
d'obtenir le JMenuItem dont l'index est fourni en paramètre.

La méthode menuComponents() renvoie un tableau des composants du menu.

La méthode isMenuComponent() renvoie un booléen qui précise si le composant fourni en paramètre est inclus dans les éléments du menu.

Un événement de type MenuEvent est émis lorsque le titre du menu est cliqué. Un listener de type MenuListener permet de s'abonner à ces
événements. L'interface MenuListener définie trois méthodes qui possèdent un paramètre de type MenuEvent :

Méthodes Rôle
menuCanceled() invoquée lorsque le menu est effacé
menuDeselected() invoquée lorsque le titre du menu est désélectionné
menuSelected() invoquée lorsque le titre du menu est sélectionné

38.9.5. La classe JCheckBoxMenuItem


Cette classe encapsule un élément du menu qui contient une case à cocher.

Elle possède de nombreux constructeurs qui permettent de préciser le texte, une icône et l'état de la case à cocher.

La propriété state() permet de connaître ou de définir l'état de la case à cocher.

[Link] 41/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

38.9.6. La classe JRadioButtonMenuItem


Cette classe encapsule un élément de menu qui contient un bouton radio. A un instant donné, un seul des boutons radio associés à un même
groupe peut être sélectionné.

La définition de ce groupe se fait en utilisant la classe ButtonGroup. C'est d'ailleurs cette classe qui propose la méthode getSelected() pour
connaître le bouton radio sélectionné dans le groupe.

Exemple :

...
[Link]();
ButtonGroup buttonGroup = new ButtonGroup();
item = new JRadioButtonMenuItem("Cas 1");
[Link](item);
[Link](afficherMenuListener);
[Link](item);
item = new JRadioButtonMenuItem("Cas 2");
[Link](item);
[Link](afficherMenuListener);
[Link](item);
[Link]();
...

38.9.7. La classe JSeparator


La méthode addSeparator() des classes JMenu et JPopupMenu instancie un objet de type JSeparator et l'ajoute à la liste des éléments du menu.

La classe JSeparator encapsule un séparateur dans un menu.

Remarque : L'utilisation de cette classe ne se limite pas aux menus car elle peut aussi être utilisée comme un composant de l'interface.

Exemple :

package [Link];

import [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class TestMenuSwing3 extends JPanel {

public TestMenuSwing3() {
super(true);

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));


Box box1 = new Box(BoxLayout.X_AXIS);
Box box2 = new Box(BoxLayout.X_AXIS);
Box box3 = new Box(BoxLayout.X_AXIS);
Box box4 = new Box(BoxLayout.X_AXIS);
Box box5 = new Box(BoxLayout.X_AXIS);
[Link](new JButton("Bouton 1"));
[Link](new JButton("Bouton 2"));
[Link](new JButton("Bouton 3"));
[Link](new JSeparator());
[Link](new JTextField(""));
[Link](new JSeparator());
[Link](new JButton("Bouton 4"));
[Link](new JButton("Bouton 5"));
[Link](new JButton("bouton 6"));
add(box1);
add(box2);
add(box3);
add(box4);
add(box5);
}

public static void main(String s[]) {


JFrame frame = new JFrame("Test separator");
[Link](JFrame.EXIT_ON_CLOSE);
[Link](new TestMenuSwing3());
[Link](new Dimension(250, 200));
[Link]();
[Link](true);
}
}

Résultat :

[Link] 42/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux

38.10. L'affichage d'une image dans une application.


Pour afficher une image dans une fenêtre, il y a plusieurs solutions.

La plus simple consiste à utiliser le composant JLabel qui est capable d'afficher du texte mais aussi une image

Exemple :

package [Link];

import [Link];
import [Link];
import [Link];
import [Link];

public class MonApp extends JFrame {

private static final long serialVersionUID = 1L;

public MonApp(String titre) {


super(titre);
[Link](JFrame.EXIT_ON_CLOSE);
init();
}

private void init()


{
JLabel label = new JLabel(new ImageIcon("[Link]") );
[Link](label, [Link]);
[Link]();
}

public static void main(String[] args) {


MonApp app = new MonApp("Afficher image");
[Link](true);
}
}

Dans l'exemple ci-dessus, le fichier contenant l'image doit être à la racine des fichiers class : aucun chemin n'est précisé donc c'est le chemin
relatif au répertoire d'exécution de l'application qui est retenu. Il est possible de préciser un chemin absolu mais cela limite les possibilités de
déploiement de l'application.

C:\MonApp\src>javac com/jmdoudoux/test/[Link]

C:\MonApp\src>java [Link]

Il est possible de définir un composant personnalisé qui hérite de la classe JPanel qui va se charger d'afficher l'image.

Historiquement, c'est la classe [Link] qui peut être utilisée pour charger une image.

Exemple :

package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

/**
* Composant qui affiche une image
*/
public class AfficheImage extends Panel {

private static final long serialVersionUID = 1L;


private Image image;

public AfficheImage(String filename) {


image = [Link]().getImage("./[Link]");

[Link] 43/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
try {
MediaTracker mt = new MediaTracker(this);
[Link](image, 0);
[Link]();
} catch (Exception e) {
[Link]();
}
[Link](new Dimension([Link](this), image
.getHeight(this)));
}

public void paint(Graphics g) {


[Link](image, 0, 0, null);
}
}

L'inconvénient d'utiliser la classe Toolkit pour charger une image est que ce chargement se fait de façon asynchrone. Il faut alors utiliser une
instance de la classe MediaTracker pour patienter le temps du chargement de l'image et ainsi pouvoir déterminer sa taille pour la reporter sur la
taille du composant.

A partir de Java 1.4, il est aussi possible d'utiliser la classe [Link] pour simplifier le code qui charge l'image.

Exemple :

package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

/**
* Composant qui affiche une image
*/
public class AfficheImage extends Panel {

private static final long serialVersionUID = 1L;


private BufferedImage image;

public AfficheImage(String nomFichier) {

try {
image = [Link](new File(nomFichier));
[Link](new Dimension([Link](),
[Link]()));
} catch (IOException ie) {
[Link]();
}
}

public void paint(Graphics g) {


[Link](image, 0, 0, null);
}
}

Il suffit alors d'utiliser le composant dans la fenêtre

Exemple :

package [Link];
import [Link];
import [Link];

public class MonApp extends JFrame {

private static final long serialVersionUID = 1L;

public MonApp(String titre) {


super(titre);
[Link](JFrame.EXIT_ON_CLOSE);
init();
}

private void init()


{
AfficheImage afficheImage = new AfficheImage("[Link]");
[Link](new BorderLayout());
[Link](afficheImage, [Link]);
[Link]();
}

public static void main(String[] args) {


MonApp app = new MonApp("Afficher image");
[Link](true);
}
}

Malheureusement, ces deux solutions ne fonctionnent pas si l'application est packagée sous la forme d'une archive qui contient l'image car l'API
[Link] n'est pas capable de lire une ressource dans l'archive jar. Il faut utiliser le classloader pour charger l'image sous la forme d'une ressource.
L'avantage de cette solution c'est qu'elle fonctionne que l'application soit packagée ou non.

Exemple :

package [Link];

import [Link];

[Link] 44/45
01/11/2019 Cours Java et Eclipse de J.M. Doudoux
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

/**
* Composant qui affiche une image
*/
public class AfficheImage extends Panel {

private static final long serialVersionUID = 1L;


private Image image;

public AfficheImage(String filename) {


[Link] url = [Link]().getResource("[Link]");
image = [Link]().getImage(url);
try {
MediaTracker mt = new MediaTracker(this);
[Link](image, 0);
[Link]();
} catch (Exception e) {
[Link]();
}
[Link](new Dimension([Link](this), image
.getHeight(this)));
}

public void paint(Graphics g) {


[Link](image, 0, 0, null);
}
}

Le fichier contenant l'image doit être accessible par le classloader dans le classpath, par exemple :

[ Précédent ] [ Sommaire ] [ Suivant ] [Télécharger ] [Accueil ]

72 commentaires

Copyright (C) 1999-2016 Jean-Michel DOUDOUX. Vous pouvez copier, redistribuer et/ou modifier ce document selon les termes de la Licence
de Documentation Libre GNU, Version 1.1 ou toute autre version ultérieure publiée par la Free Software Foundation; les Sections Invariantes
étant constitués du chapitre Préambule, aucun Texte de Première de Couverture, et aucun Texte de Quatrième de Couverture. Une copie de
la licence est incluse dans la section GNU FreeDocumentation Licence. La version la plus récente de cette licence est disponible à l'adresse :
GNU Free Documentation Licence.

Responsables bénévoles de la rubrique Java : Mickael Baron - Robin56 - Contacter par email

Nous contacter Participez Hébergement Informations légales Partenaire : Hébergement Web


© 2000-2019 - [Link]

[Link] 45/45

Vous aimerez peut-être aussi