# Programmation Java Swing/Composants

* Introduction
* Composants
** Arbre
* Fenêtres
* Menus
* Actions
* Types de données et constantes
* Gestion de la disposition des composants
* Gestion des évènements
* Gestion des actions asynchrones
* Apparence de l'interface
* Contenu en HTML
* Créer un composant
** Une case à cocher à trois états
** Dessin d'un composant
** Dessin d'une étoile
** Dessin de texte et effets
* Créer une image
* Introduction
* Composants
** Arbre
* Fenêtres
* Menus
* Actions
* Types de données et constantes
* Gestion de la disposition des composants
* Gestion des évènements
* Gestion des actions asynchrones
* Apparence de l'interface
* Contenu en HTML
* Créer un composant
** Une case à cocher à trois états
** Dessin d'un composant
** Dessin d'une étoile
** Dessin de texte et effets
* Créer une image
[ Modifier le sommaire ]
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

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

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

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.

### Position

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

### Taille

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

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

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)

* 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 :

## Composants

Pour tester rapidement les composants des sections qui suivent, voici un code source Java créant une fenêtre de test.

## JLabel

Ce composant permet d'afficher du texte et une icône.
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 :
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

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.

## JButton

Ce composant permet de déclencher une action par un clic de souris.

## JTextfield

Un champ de saisie de texte simple. La classe JTextfield hérite de JTextComponent définissant les méthodes pour les champs de saisie.

## JPasswordField

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.

## JTextArea

Une zone de saisie de texte.

## JTextPane

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

## JCheckBox

Une case à cocher.
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

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 :
Gestion de sélection :

## JComboBox

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

## JList

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

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

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, ...).

## JScrollPane

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.