Programmation Java Swing/Composants
De manière générale, un composant dans une interface graphique possède une zone rectangulaire permettant d'afficher une ou plusieurs informations et permet à l'utilisateur d'interagir avec lui en utilisant la souris ou le clavier.
Divers composants
modifierCette section liste brièvement quelques composants Swing décrits plus en détails dans les sections suivantes. Les composants Swing sont nombreux, seuls les plus courants seront décrits ici.
- JLabel
- Ce composant permet d'afficher du texte et une icône.
- JButton
- Ce composant (bouton) permet de déclencher une action par un clic de souris.
- JToggleButton
- Bouton basculant entre deux états.
- JTextfield
- Un champ de saisie de texte simple.
- JPasswordField
- Un champ de saisie de mot de passe dont les caractères sont cachés.
- JTextArea
- Une zone de saisie de texte.
- JTextPane
- Une zone d'affichage ou de saisie de texte formaté.
- JCheckBox
- Une case à cocher.
- JRadioButton
- Un item sélectionnable parmi un groupe.
- JComboBox
- Une liste déroulante de choix (un seul choix possible).
- JList
- Une liste d'items, un ou plusieurs items sélectionnable.
- JSpinner
- Champ de saisie avec boutons d'incrémentation et de décrémentation (nombre, items dans une liste prédéfinie, ...).
- JSlider
- Sélection d'une valeur numérique par glissement d'un curseur sur une ligne.
- JProgressBar
- Barre de progression.
- JTree
- Arborescence de nœuds pour les données structurées.
- JTable
- Table de données.
- JScrollbar
- Une barre de défilement.
- JPanel
- Un conteneur générique.
- JScrollPane
- Un conteneur permettant de faire défiler le contenu du composant (la vue) lorsque sa taille dépasse les limites du conteneur.
- JSplitPane
- Un conteneur avec deux composants séparés par un mince composant diviseur dont la position est réglable à la souris. Ce diviseur contient par défaut deux boutons permettant de cacher l'un des deux composants pour afficher l'autre sur toute la surface du conteneur.
Architecture logicielle
modifierLes composants Swing utilisent l'architecture MVC (modèle vue contrôleur) :
- La vue (view en anglais) contient la présentation de l'interface graphique.
- La vue est gérée par le composant Swing, par exemple : JTable, JTree...
- Le modèle (model en anglais) contient et gère les données à afficher.
- Le modèle est associé au composant : JTableModel, JTreeModel...
- Le contrôleur (controller en anglais) contient la logique concernant les actions effectuées par l'utilisateur.
- Le rôle du contrôleur est réparti entre le code du composant définissant un comportement interne et les écouteurs d'évènements définis par l'application.
Taille et position
modifierEn général et par défaut, la taille et la position des composants dans un conteneur sont définies par un gestionnaire de disposition des composants.
Elles ne peuvent donc être modifiées qu'en cas d'absence de gestionnaire de disposition (setLayout(null)
).
Cependant, il est recommandé d'utiliser l'un des gestionnaires de disposition des composants pré-existants.
Position
modifierComme en AWT, la position d'un composant est définie par deux coordonnées x et y, qui peuvent être représentées par un objet de classe java.awt.Point
. Cette classe comporte deux champs publics x
et y
de type entier (int
).
void setLocation(int x, int y)
|
Cette méthode définit les coordonnées horizontales et verticales (respectivement) du coin supérieur gauche du composant. Les coordonnées sont relatives au conteneur ; c'est à dire que (0,0) correspond au bord supérieur gauche du conteneur, éventuellement espacé de la largeur du bord du conteneur. |
void setLocation(Point p)
|
Cette méthode définit les coordonnées en utilisant un objet de classe java.awt.Point .
|
Point getLocation()
|
Cette méthode retourne la position du composant. |
Taille
modifierLa taille d'un composant est définie par la largeur (width en anglais) et la hauteur (height en anglais), qui peuvent être représentées par un objet de classe java.awt.Dimension
. Cette classe comporte deux champs publics width
et height
de type entier (int
).
void setSize(int width, int height)
|
Cette méthode définit la taille du composant. |
void setLocation(Dimension size)
|
Cette méthode définit la taille en utilisant un objet de classe java.awt.Dimension .
|
Dimension getSize()
|
Cette méthode retourne la taille du composant. |
Utiliser un objet au lieu de spécifier directement les valeurs permet de réutiliser les mêmes valeurs pour d'autres composants, ou pour définir la taille minimales, maximales et préférées d'un composants, ou de réutiliser les valeurs retournées par un composant.
Taille et position
modifierLa taille et la position peuvent être définies en une fois en utilisant les méthodes ci-dessous, soit en spécifiant les 4 valeurs, soit en utilisant un objet de classe java.awt.Rectangle
. Cette classe comporte quatre champs publics de type entier (int
) : x
et y
pour la position, et width
et height
pour la taille.
void setBounds(int x, int y, int width, int height)
|
Cette méthode définit la taille et la position du composant. |
void setBounds(Rectangle bounds)
|
Cette méthode définit la taille et la position en utilisant un objet de classe java.awt.Rectangle .
|
Rectangle getBounds()
|
Cette méthode retourne la taille et la position du composant. |
Propriétés d'apparence
modifierCertaines propriétés communes aux composants changent leur apparence :
void setBackground(Color c)
/Color getBackground()
- Couleur de fond du composant.
void setForeground(Color c)
/Color getForeground()
- Couleur de premier plan, utilisée pour le texte.
void setFont(Font f)
/Font getFont()
- Police de caractères par défaut pour le texte.
void setText(String s)
/String getText()
- Texte affiché (label, bouton, champ de saisie, ...).
void setBorder(Border b)
/Border getBorder()
- Ajoute un espace autour du composant pour y dessiner une bordure. La classe
BorderFactory
définit des méthodes statiques permettant de créer des bordures. void setTooltipText(String s)
/String getTooltipText()
- Texte affiché temporairement au survol de la souris sur le composant.
Propriétés de comportement (état)
modifier- La méthode
void setVisible(boolean b)
permet de changer la visibilité du composant. La méthodeboolean isVisible()
retourne l'état de visibilité du composant. - La méthode
void setEnabled(boolean b)
permet de désactiver/griser (false
) ou (ré)activer (true
) un composant. La méthodeboolean isEnabled()
retourne l'état d'activation du composant. - La méthode
void setEditable(boolean b)
permet de désactiver (false
) ou (ré)activer (true
) la modification de la valeur dans un champ de saisie dérivant de la classeJTextComponent
(classesJTextArea
,JTextField
,JFormattedTextField
,JPasswordField
,JEditorPane
,JTextPane
, ...). La méthodeboolean isEditable()
retourne l'état d'activation de modification de la valeur.
Suite à la réactivation d'un champ texte, soit par la méthode void setEnabled(true)
, soit par la méthode void setEditable(true)
, il peut arriver que le curseur n'apparaisse pas, même quand le focus est sur le champ.
La solution, après réactivation, est de rendre visible le curseur explicitement :
textinput.getCaret().setVisible(true);
Composants
modifierPour tester rapidement les composants des sections qui suivent, voici un code source Java créant une fenêtre de test.
package org.wikibooks.fr.swing;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
/**
* Fenêtre pour tester les composants.
* @author fr.wikibooks.org
*/
public class FenetreTestComposants extends JFrame
{
public FenetreTestComposants()
{
// Configurer la fenêtre
setTitle("Composants");
setSize(new Dimension(600,400)); // Taille initiale de la fenêtre
setLocation(new Point(200, 100)); // Position initiale de la fenêtre
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Création du panel pour le contenu de la fenêtre
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
// Copier/Écrire ici le code pour créer le composant comme celui donné dans les sections suivantes.
// ...
// composant = new ... ( ... );
// ...
contentPane.add(composant); // remplacer "composant" par le nom de la variable utilisée.
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
FenetreTestComposants frame = new FenetreTestComposants(); // Créer
frame.setVisible(true); // Afficher
}
});
}
}
JLabel
modifierCe composant permet d'afficher du texte et une icône.
// Convention : l_ pour label
// Un label pour le nom de l'application :
JLabel l_nom_app = new JLabel("Apprentissage Java Swing sur fr.wikibooks.org");
// Les lignes suivantes sont optionnelles mais permettent de configurer le composant
l_nom_app .setFont(new Font("Tahoma", Font.BOLD, 36)); // Police "Tahoma", en gras, 36 pixels
Dans la fenêtre de test, une largeur de 600 pixels ne suffit pas à afficher tout le texte. Le composant coupe le texte avant 600 pixels et affiche des points de suspension.
Pour afficher un texte sur plusieurs lignes, l'utilisation de caractère de retour à la ligne \n
ou \r
n'ont aucun effet.
Il faut utiliser un format HTML :
// Convention : l_ pour label
// Un label pour le nom de l'application :
JLabel l_nom_app = new JLabel("<html>Apprentissage Java Swing<br>sur fr.wikibooks.org</html>");
// Les lignes suivantes sont optionnelles mais permettent de configurer le composant
l_nom_app .setFont(new Font("Tahoma", Font.BOLD, 36)); // Police "Tahoma", en gras, 36 pixels
Le constructeur a trois paramètres optionnels :
JLabel(String text, Icon icon, int horizontalAlignment)
.
text
- Texte affiché, aucun si absent.
icon
- Image affichée, aucune si absent. Si le texte est aussi spécifié, l'image est à gauche du texte par défaut.
- La classe
ImageIcon
est une sous-classeIcon
et définit l'icône à partir d'une image de classeImage
. horizontalAlignment
- Alignement du contenu :
SwingConstants.LEFT // À gauche
SwingConstants.CENTER // Centré
SwingConstants.RIGHT // À droite
SwingConstants.LEADING // En début de ligne (gauche / droite)
SwingConstants.TRAILING // En fin de ligne (droite / gauche)
Quand un texte et une image sont affichés, l'image est à gauche du texte par défaut.
La méthode setHorizontalTextPosition(int textPosition)
permet de choisir la position du texte relativement à l'image :
SwingConstants.LEFT // À gauche
SwingConstants.CENTER // Centré
SwingConstants.RIGHT // À droite
SwingConstants.LEADING // Du côté du début de ligne (gauche / droite)
SwingConstants.TRAILING // Du côté de la fin de ligne (droite / gauche)
Label activant un composant
modifierUn label peut être utilisé pour activer le composant associé. Par exemple, mettre le focus sur un champ de saisie quand l'utilisateur tape la touche mnémonique associée au label.
setDisplayedMnemonic(int key)
- Spécifier un code de touche mnémonique à afficher.
setLabelFor(Component c)
- Spécifier le composant associé au label.
JButton
modifierCe composant permet de déclencher une action par un clic de souris.
// Convention : b_ pour button
JButton b_configurer = new JButton("Configurer...");
b_configurer.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{ configurer(); }
});
// N.B. : Définir la méthode configurer() appelée par le bouton dans la classe
JTextfield
modifierUn champ de saisie de texte simple.
La classe JTextfield
hérite de JTextComponent
définissant les méthodes pour les champs de saisie.
// Convention : tf_ pour text field
JTextField tf_titre_livre = new JTextField();
// Ajouter une bulle d'information pour l'utilisateur s'affichant au survol de la souris :
tf_titre_livre.setToolTipText("Titre d'un livre");
String livre = "Programmation Java Swing";
tf_titre_livre.setText(livre); // Initialiser la valeur dans le champ de saisie
// Plus tard, lors d'une action :
livre = tf_titre_livre.getText(); // Récupérer la valeur du champ saisie par l'utilisateur
JPasswordField
modifierUn champ permettant la saisie d'un mot de passe, cachant les caractères tapés.
La classe JPasswordField
hérite de JTextComponent
définissant les méthodes pour les champs de saisie.
Cette classe possède donc les mêmes méthodes que JTextfield
.
// Convention : pf_ pour password field
JPasswordField pf_connexion = new JPasswordField(); // Mot de passe de connexion
// Ajouter une bulle d'information pour l'utilisateur s'affichant au survol de la souris :
pf_connexion.setToolTipText("Entrez le mot de passe de connexion");
pf_connexion.setText(""); // Initialiser la valeur dans le champ de saisie
// Plus tard, lors d'une action :
// String mot = pf_connexion.getText(); // Récupérer la valeur du champ saisie par l'utilisateur
// Obsolète, ne pas utiliser dans les applications sécurisées, voir ci-dessous.
char[] mot = pf_connexion.getPassword(); // Récupérer la valeur du champ saisie par l'utilisateur
// Comme mentionné dans la documentation de la méthode getPassword(),
// pour plus de sécurité, il est recommandé d'effacer le contenu
// du tableau retourné après usage en le remplissant de zéro.
Arrays.fill(mot, '\0');
// Ceci n'est pas possible avec le type String immuable, expliquant pourquoi
// il ne faut pas utiliser la méthode getText().
JTextArea
modifierUne zone de saisie de texte.
JTextPane
modifierUne zone d'affichage ou de saisie de texte formaté.
JCheckBox
modifierUne case à cocher.
// Convention : cb_ pour check box
cb_resume = new JCheckBox("Avec résumé");
// Ajouter une bulle d'information pour l'utilisateur s'affichant au survol de la souris :
cb_resume.setToolTipText("Générer un résumé du livre");
cb_resume.setSelected(true); // Initialiser la case : cochée [X]
cb_resume.setSelected(false); // ou non cochée [ ]
// Plus tard, lors d'une action :
boolean avec_resume = cb_resume.isSelected(); // Récupérer l'état choisi par l'utilisateur
Ce composant gère deux états, mais pas d'état intermédiaire (coché partiellement ou indéterminé). Mais il est possible de créer un composant ayant ce troisième état : voir le chapitre avancé « Créer une case à cocher à trois états ».
JRadioButton
modifierUn bouton radio, permettant de sélectionner un item parmi plusieurs dans un groupe.
La classe JRadioButton
possède plusieurs constructeurs qui permettent d'initialiser le texte affiché, l'image d'icône, et l'état initial (booléen, sélectionné ou non).
new JRadioButton(String text, Icon icon, boolean selected)
- Tous les paramètres sont optionnels.
new JRadioButton(Action action)
- Paramétrage avec une action.
La classe ButtonGroup
n'est pas un composant mais représente un groupe de boutons abstraits (JRadioButton, JToggleButton, ...) dont seul l'un d'entre eux peut être sélectionné à la fois.
La sélection de l'un d'eux entraîne la dé-sélection des autres.
Exemple :
// Convention : bg_ pour button group
ButtonGroup bg_theme = new ButtonGroup();
// Convention : rb_ pour radio button
JRadioButton rb_theme_clair = new JRadioButton("Thème clair");
bg_theme.add(rb_theme_clair); // Ajout au groupe
JRadioButton rb_theme_sombre = new JRadioButton("Thème sombre");
bg_theme.add(rb_theme_sombre); // Ajout au groupe
JRadioButton rb_theme_sepia = new JRadioButton("Thème sépia");
bg_theme.add(rb_theme_sepia); // Ajout au groupe
Gestion de sélection :
bg_theme.clearSelection(); // Tous dé-sélectionnés
// Sélectionner un bouton radio :
rb_theme_clair.setSelected(true);
// Connaître l'état de sélection :
boolean avec_theme_clair = rb_theme_clair.isSelected();
JComboBox
modifierUne liste déroulante de choix (un seul choix possible).
JList
modifierUne liste d'items, un ou plusieurs items sélectionnable.
Le constructeur accepte un tableau d'objets (leur méthode toString()
est appelé pour le texte à afficher) ou un modèle de liste JListModel
.
L'utilisation d'un modèle de liste est recommandée quand la liste des items est modifiable par l'utilisateur.
final Object[] JOURS = { "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche" };
// Indice : 0 1 2 3 4 5 6
// Convention : ls_ pour list
JList ls_jours = new JList(JOURS);
Ce composant a plusieurs modes de sélection :
- un seul item sélectionnable :
// Mode de sélection : un seul ls_jours.setselectionMode(ListSelectionModel.SINGLE_SELECTION); ls_jours.setSelectedIndex(2); // Mercredi // Plus tard, durant une action : int index_jour = ls_jours.getSelectedIndex();
- un seul intervalle continu sélectionnable :
// Mode de sélection : un seul intervalle ls_jours.setselectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); ls_jours.setSelectionInterval(2, 4); // Du mercredi au vendredi inclus // Plus tard, durant une action : int[] indexs_jour = ls_jours.getSelectedIndices();
- plusieurs intervalles sélectionnables :
// Mode de sélection : plusieurs intervalles ls_jours.setselectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // Soit tous les indices : ls_jours.setSelectedIndices(new int[]{0,1,2, 4,5}); // Lundi, mardi, mercredi, vendredi, samedi // Soit les intervalles : ls_jours.setSelectionInterval(0, 2); // Du lundi au mercredi inclus ls_jours.addSelectionInterval(4, 5); // et ajouter du vendredi au samedi inclus // Plus tard, durant une action : int[] indexs_jour = ls_jours.getSelectedIndices();
La taille de la liste est déterminée par le nombre d'items. Ce composant ne gère pas le défilement. Il faut l'englober dans un composant JScrollPane pour gérer le défilement d'une longue liste dans un espace plus réduit.
JSpinner
modifierChamp de saisie avec boutons d'incrémentation et de décrémentation (nombre, items dans une liste prédéfinie, ...).
JSlider
modifierSélection d'une valeur numérique par glissement d'un curseur sur une ligne.
JProgressBar
modifierBarre de progression.
JTree
modifierArborescence de nœuds pour les données structurées.
JTable
modifierTable de données.
JScrollbar
modifierUne barre de défilement.
Ce composant est rarement utilisé directement car il est de bas niveau et est utilisé notamment par JScrollPane qui gère la vue partielle, le défilement et les entêtes.
JPanel
modifierUn conteneur générique, comme le contentPane
de la fenêtre de test.
Un panel, comme sa classe de base java.awt.Container
, peut contenir tout type de composant, y compris d'autres panels.
L'imbrication de panels permet de subdiviser un panel en plusieurs panels indépendant et réutilisables ayant leur propre configuration (gestionnaire de disposition, couleur de fond, ...).
// Convention : p_ pour panel
JPanel p_outils = new JPanel(); // un panel pour les outils de l'application
// Configuration :
p_outils.setBorder(new EmptyBorder(5, 5, 5, 5)); // bordure vide de 5 pixels dans les 4 directions
p_outils.setLayout(new FlowLayout()); // gestionnaire de disposition
JScrollPane
modifierUn conteneur permettant de faire défiler le contenu du composant (la vue) lorsque sa taille dépasse les limites du conteneur. Ce type de panel est notamment utilisé avec les listes ayant plus de 3 ou 5 items, les tables, les arborescences, les panels ayant un contenu occupant une grande surface.
Ce composant comporte en fait neufs zones illustrées ci-dessous :
Coin
supérieur gauche |
Entête de colonne
|
Coin
supérieur droit |
Entête de ligne
|
Partie principale du composant |
Barre de défilement vertical
|
Coin
inférieur gauche |
Barre de défilement horizontal |
Coin
inférieur droit |
- Partie principale du composant
- Il s'agit en général du composant lui-même, dont la vue suit le défilement horizontal et vertical des barres situées en bas et à droite respectivement.
- Le composant affiché est celui passé au constructeur :
new JScrollPane(table_pages) // Pour la table des pages
- Il peut être spécifié ou modifié après construction en utilisant la méthode
setViewportView
:// Convention : sp_ pour scroll pane JScrollPane sp_pages = new JScrollPane(); sp_pages.setViewportView(table_pages); // configurer la vue (view) du JViewport
- Les trois zones de vues avec défilement (principal, entête de colonne, entête de ligne) sont en fait encapsulées dans un
JViewport
qui gère l'affichage partiel. Il est possible de spécifier un autre type deJViewport
en utilisant la méthodesetViewport
.
- Entête de colonne
- Un entête toujours affiché en haut, mais pouvant être défilé horizontalement pour suivre le contenu principal.
- Il peut s'agir d'un composant quelconque. Cependant, pour les tables, il s'agit souvent de l'entête des colonnes de la table que l'on obtient par appel de la méthode
getTableHeader
:sp_pages.setColumnHeaderView(table_pages.getTableHeader()); // configurer l'entête de colonne
- Les trois zones de vues avec défilement (principal, entête de colonne, entête de ligne) sont en fait encapsulées dans un
JViewport
qui gère l'affichage partiel. Il est possible de spécifier un autre type deJViewport
en utilisant la méthodesetColumnHeader
.
- Entête de ligne
- Un entête toujours affiché à gauche, mais pouvant être défilé verticalement pour suivre le contenu principal.
- Il s'agit d'un composant quelconque :
sp_pages.setRowHeaderView(p_row); // configurer l'entête de ligne
- Les trois zones de vues avec défilement (principal, entête de colonne, entête de ligne) sont en fait encapsulées dans un
JViewport
qui gère l'affichage partiel. Il est possible de spécifier un autre type deJViewport
en utilisant la méthodesetRowHeader
.
- Barres de défilement
- Les barres de défilement sont affichées quand nécessaire par défaut. Ce comportement peut être modifié soit en spécifiant le mode pour les barres verticales et horizontales au constructeur, ou en appelant les méthodes
setVerticalScrollBarPolicy( ... )
etsetHorizontalScrollBarPolicy( ... )
:
setVerticalScrollBarPolicy( ... )
setHorizontalScrollBarPolicy( ... )
Quand afficher la barre de défilement vertical / horizontal : ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED
Quand nécessaire (contenu plus large que la zone de vue). ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
Jamais (vue tronquée et non défilable). ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
Toujours.
- Coins
- Il peut y avoir jusqu'à quatre coins affichés, qui sont par défaut vides. Il est possible d'y placer des composants de petite taille, en général décoratifs seulement, afin de combler le vide.
setCorner(String key, Component component)
- key
- Nom du coin où placer le composant. Ce nom doit être l'un de ceux listés ci-dessous :
- Coin absolu :
ScrollPaneConstants.UPPER_LEFT_CORNER // supérieur gauche
ScrollPaneConstants.UPPER_RIGHT_CORNER // supérieur droit
ScrollPaneConstants.LOWER_LEFT_CORNER // inférieur gauche
ScrollPaneConstants.LOWER_RIGHT_CORNER // inférieur
- Coin relatif au sens de lecture :
ScrollPaneConstants.UPPER_LEADING_CORNER // supérieur début de ligne (gauche/droit)
ScrollPaneConstants.UPPER_TRAILING_CORNER // supérieur fin de ligne (droit/gauche)
ScrollPaneConstants.LOWER_LEADING_CORNER // inférieur début de ligne (gauche/droit)
ScrollPaneConstants.LOWER_TRAILING_CORNER // inférieur fin de ligne (droit/gauche)
- Coin absolu :
- component
- Composant à placer.