Aller au contenu

Programmation Java Swing/Composants

Un livre de Wikilivres.


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.

Quelques composants Swing dans une fenêtre

Divers composants

[modifier | modifier le wikicode]

Cette 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

[modifier | modifier le wikicode]

Les 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

[modifier | modifier le wikicode]

En 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.

Comme 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.

La 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

[modifier | modifier le wikicode]

La 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

[modifier | modifier le wikicode]

Certaines 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 | modifier le wikicode]
  • La méthode void setVisible(boolean b) permet de changer la visibilité du composant. La méthode boolean 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éthode boolean 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 classe JTextComponent (classes JTextArea, JTextField, JFormattedTextField, JPasswordField, JEditorPane, JTextPane, ...). La méthode boolean 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);

Pour 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
			}
		});
	}
}

Ce 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-classe Icon et définit l'icône à partir d'une image de classe Image.
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

[modifier | modifier le wikicode]

Un 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.

Ce 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

Un 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

[modifier | modifier le wikicode]

Un 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().

Une zone de saisie de texte.

Une zone d'affichage ou de saisie de texte formaté.

Une 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 ».

Un 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();

Une liste déroulante de choix (un seul choix possible).

Une 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.

Champ de saisie avec boutons d'incrémentation et de décrémentation (nombre, items dans une liste prédéfinie, ...).

Sélection d'une valeur numérique par glissement d'un curseur sur une ligne.

Barre de progression.

Arborescence de nœuds pour les données structurées.

Table de données.

Une 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.

Un 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

Un 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 de JViewport en utilisant la méthode setViewport.
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 de JViewport en utilisant la méthode setColumnHeader.
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 de JViewport en utilisant la méthode setRowHeader.
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( ... ) et setHorizontalScrollBarPolicy( ... ) :
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)
component
Composant à placer.