# Programmation Java Swing/Fenêtres

* 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 ]
Les fenêtres Swing dérivent de celles disponibles avec AWT :
* JFrame (sous-classe de Frame) représente une fenêtre d'application.
* JDialog (sous-classe de Dialog) représente une fenêtre de dialogue.
* JWindow (sous-classe de Window) représente une fenêtre générique.
* JInternalFrame (pas d'équivalent AWT) représente une fenêtre interne à l'intérieur d'une zone multi-documents gérée par la classe JDesktopPane.
* JApplet (sous-classe de Applet) représente une fenêtre intégrée dans une page HTML d'un navigateur web. Ce type de fenêtre ne se rencontre plus beaucoup car pour des raisons de sécurité, Java est désactivé par défaut sur tous les navigateurs récents. De plus les applets sont déclarées obsolètes depuis Java 9 en 2017, et supprimées de Java depuis la version 11.

## Points communs

Les différents types de fenêtres Swing cités précédemment ont une structure commune et des méthodes communes.
L'exemple ci-dessous crée une fenêtre d'application avec un titre, contenant un label affichant du texte.

### Titre et icône

Une fenêtre possède un titre (méthode setTitle(String)) et une icône (méthode setIconImage(Image)). Par défaut, l'icône est la même que celle de la fenêtre propriétaire.

### Composition

Chaque fenêtre comporte un panel racine (classe JRootPane) qui gère la composition des éléments suivants :
* Le panneau frontal (Glass pane en anglais) est affiché au premier plan. Il est généralement utilisé pour afficher une animation de chargement de la fenêtre, une progression d'une longue opération en cours.
* Le panneau de contenu (Content pane) contient les composants ajoutés à la fenêtre (bouton, label, ...).
* La barre de menu (JMenuBar) définit les listes d'actions utilisables. Elle est affichée en haut de la fenêtre.
La barre de menu et le panneau de contenu sont gérés par un panneau de classe JLayeredPane permettant de gérer la superposition de composants.

### Taille et position

La taille et la position d'une fenêtre sont gérées avec les mêmes méthodes que celles des composants. Il n'y a pas de gestionnaire de disposition pour les fenêtres, car aucun conteneur ne les contient (hormis JInternalFrame et JApplet).
La taille et la position de la fenêtre définies par l'application peuvent ensuite être modifiées par l'utilisateur en déplaçant et en redimensionnant la fenêtre. Les méthodes setMinimumSize(Dimension) et setMaximumSize(Dimension) définissent les limites du redimensionnement. La méthode setPreferredSize(Dimension) héritée de la classe Component n'a pas de sens pour les fenêtres.

### Menu

Les fenêtres de type javax.swing.JFrame et javax.swing.JDialog peuvent avoir une barre de menus.
Voir le chapitre suivant sur les menus pour plus de détails.

## Fenêtre d'application

La fenêtre d'application est celle qui définie la vue principale d'une application. Une application peut en avoir plusieurs (Par exemple, une fenêtre par fichier ouvert). Les applications les plus simples n'ont qu'une seule fenêtre principale.
La classe javax.swing.JFrame définit une fenêtre d'application.

### Action de fermeture

La méthode setDefaultCloseOperation(int operation) définit l'action effectuée quand l'utilisateur clique le bouton de fermeture de la fenêtre. L'argument peut avoir l'une des valeurs suivantes définies dans l'interface WindowConstants implémentée par la classe JFrame :

#### DO_NOTHING_ON_CLOSE

    Ne rien faire, et appeler les gestionnaires d'évènements des fenêtres (WindowListener) enregistrés.

#### HIDE_ON_CLOSE

    Cacher la fenêtre puis appeler les gestionnaires d'évènements des fenêtres (WindowListener) enregistrés.

#### DISPOSE_ON_CLOSE

    Cacher et libérer la fenêtre puis appeler les gestionnaires d'évènements des fenêtres (WindowListener) enregistrés.

#### EXIT_ON_CLOSE

    Terminer l'application en appelant System.exit(0). Les gestionnaires d'évènements des fenêtres ne sont pas appelés.
Par défaut, la valeur est HIDE_ON_CLOSE. Tout changement provoque un évènement de changement de propriété dont le nom est "defaultCloseOperation".
Quand la dernière fenêtre est libérée (dispose), l'application peut se terminer.
Quand l'application doit faire confirmer la fermeture par l'utilisateur (par exemple en cas de données non sauvegardées), il est nécessaire de définir l'action de fermeture à rien (DO_NOTHING_ON_CLOSE) et d'ajouter un écouteur d'évènements des fenêtres (interface WindowListener implémentée par la classe vide WindowAdapter).
Dans le constructeur de la classe de fenêtre principale :
Dans la classe de fenêtre principale :
La méthode confirmerAction ci-dessus est réutilisable pour les actions provoquant une perte des données non sauvegardées :
* La fermeture de la fenêtre principale,
* L'action quitter (menu / bouton),
* Charger un fichier (si la même fenêtre est réutilisée),
* Créer un nouveau fichier (si la même fenêtre est réutilisée),

### États de la fenêtre

La méthode setExtendedState(int state) permet de modifier l'état de la fenêtre, et la méthode int getExtendedState permet de récupérer l'état actuel :

#### NORMAL

    Affichage normal,

#### ICONIFIED

    Fenêtre icônifiée sur le bureau ou réduite dans la barre des tâches,

#### MAXIMIZED_HORIZ

    Fenêtre affichée sur toute la largeur de l'écran,

#### MAXIMIZED_VERT

    Fenêtre affichée sur toute la hauteur de l'écran,

#### MAXIMIZED_BOTH

    Fenêtre affichée sur tout l'écran (combine les deux états précédents).

### Icône de fenêtre

L'icône de la fenêtre d'application est visible, selon le système d'exploitation, dans le coin du bord de la fenêtre (sous Windows, en haut à gauche en 16x16 pixels), dans la barre des tâches (taille variable : 16x16, 48x48, 64x64, ...), dans le sélecteur de fenêtres (sous Windows avec AltTab ↹ ou ⊞Tab ↹). L'icône de la fenêtre d'application peut aussi être utilisée par les boîtes de dialogue ayant la fenêtre comme propriétaire (owner) passé au constructeur.
Deux méthodes existent :
* La méthode setIconImage(java.awt.Image image) définit une image comme icône. Cette image est redimensionnée selon la taille nécessaire. Il est donc recommandé d'utiliser une image de grande résolution (64x64 pixels minimum) afin d'éviter un agrandissement produisant des blocs de pixels. Celle-ci doit donc aussi pouvoir être réduite sans perte de visibilité.
* La méthode setIconImages(java.util.List<java.awt.Image> images) permet de définir une liste d'images. Selon la taille d'icône du contexte (exemple : 16x16 pour l'icône du bord de fenêtre, 64x64 pour la barre des tâches, ...), une image suffisamment grande est sélectionnée et redimensionnée si nécessaire. Cette méthode est recommandée si l'icône change en fonction de la taille, pour par exemple y mettre moins d'éléments pour les plus petites tailles d'icône.
La méthode setIconImage(java.awt.Image image) est en fait un appel à la méthode setIconImages(java.util.List<java.awt.Image> images) en lui passant une liste contenant une seule image.
En général, l'icône est une image stockée dans le même répertoire que les classes de l'application, dans un format supporté par ImageIO (PNG, GIF). Exemple pour une image stockée dans le même répertoire que la classe de la fenêtre :
Pour une liste d'icônes :

## Fenêtre de dialogue

Une fenêtre de dialogue est une fenêtre temporaire ouverte sur une action spécifique permettant de dialoguer avec l'utilisateur pour lui fournir et lui demander une ou plusieurs informations : entrer les champs d'une nouvelle entité à ajouter dans une table, sélectionner un fichier, sélectionner une couleur, afficher un message d'erreur, demander une confirmation de suppression...

### Fenêtres de dialogue prédéfinies

Swing possède des classes ou méthodes permettant d'utiliser des fenêtres de dialogue prédéfinies.

#### JOptionPane

    La classe JOptionPane définit une fenêtre de dialogue simple permettant d'afficher un message avec une icône prédéfinie associée (information, question, avertissement, erreur...), avec éventuellement un champ de saisie, et de 1 à 3 boutons pour divers choix possible de réponse.
    Cette classe possède différentes méthodes statiques pour créer et afficher ces fenêtres.

#### JColorChooser

    La classe JColorChooser définit une fenêtre de dialogue pour sélectionner une couleur.

#### JFileChooser

    La classe JFileChooser définit une fenêtre de dialogue pour sélectionner un fichier ou un répertoire.

### Fenêtre de dialogue de type message : JOptionPane

La classe JOptionPane définit une fenêtre de dialogue simple permettant d'afficher un message avec une icône prédéfinie associée, pouvant avoir un champ de saisie selon le type, et proposant plusieurs choix de bouton.

#### Simple notification de message

Ce type de fenêtre affiche simplement le message et possède un bouton OK pour fermer la fenêtre, et utilise la méthode showMessageDialog.
Exemple :
* La méthode showMessageDialog ne retourne aucune valeur.
* frame est la fenêtre (Frame ou JFrame) par dessus laquelle le message est affiché. Si la référence est null, une fenêtre est créée.
* Le message affiché dans la fenêtre est spécifié avant le titre.
* Le dernier argument spécifie le type de message, définissant l'icône affichée en face du message :
Il existe deux variantes de la méthode showMessageDialog :
* Sans les deux derniers arguments de titre ("Message" par défaut) et type (JOptionPane.INFORMATION_MESSAGE par défaut).
* Avec un cinquième argument permettant d'afficher une icône personnalisée de type xjava.swing.Icon.

#### Message en HTML

Il est possible d'utiliser le format HTML pour formater le message affiché. Pour cela, il faut encadrer le message dans une balise <html> et ne pas utiliser de caractères de contrôle dans le message ; par exemple "\n" qui doit être remplacé par <br/>.
Exemple :
Pour plus de détails sur le formatage en HTML et les limitations, voir le chapitre sur le contenu en HTML.

#### Fenêtre de confirmation

Ce type de fenêtre affiche le message et propose plusieurs boutons de confirmation pour fermer la fenêtre, et utilise la méthode showConfirmDialog.
Exemple :
Les variantes de la méthode sont :

##### int showConfirmDialog(Component parent, String message)

    Titre "Select an option", boutons Oui, Non et Annuler ;

##### int showConfirmDialog(Component parent, String message, String title, int optionType)

    Titre et boutons spécifiés ;

##### int showConfirmDialog(Component parent, String message, String title, int optionType, int messageType)

    Type de message spécifié également ;

##### int showConfirmDialog(Component parent, String message, String title, int optionType, int messageType, Icon icon)

    Avec icône personnalisée.
* optionType définit les boutons disponibles :
** JOptionPane.YES_NO_OPTION : Boutons Oui et Non ;
** JOptionPane.YES_NO_CANCEL_OPTION : Boutons Oui, Non et Annuler ;
** JOptionPane.OK_CANCEL_OPTION : : Boutons OK et Annuler.
* La méthode retourne le choix de l'utilisateur :
** JOptionPane.OK_OPTION : Bouton OK cliqué ;
** JOptionPane.YES_OPTION : Bouton Oui cliqué ;
** JOptionPane.NO_OPTION : Bouton Non cliqué ;
** JOptionPane.CANCEL_OPTION : Bouton Annuler cliqué ;
** JOptionPane.CLOSED_OPTION : Fenêtre fermée sans choix (à considérer comme Annuler ou Non).

#### Fenêtre de saisie

Ce type de fenêtre utilise la méthode showInputDialog et affiche le message et un champ de saisie ou une liste de choix, et les boutons OK et Cancel pour fermer la fenêtre.
Exemple :
La méthode retourne la valeur sélectionnée ou entrée par l'utilisateur, ou null si l'utilisateur a choisi d'annuler.

#### Panel de dialogue interne

Les méthodes vu précédemment ont toutes une variante pour afficher un panel de dialogue interne, dont le nom est celui de la méthode où show est remplacé par showInternal :
* showInternalConfirmDialog,
* showInternalMessageDialog,
* showInternalInputDialog,
* showInternalOptionDialog.

### Fenêtre de sélection de couleur : JColorChooser

La fenêtre de sélection de couleur permet de choisir une couleur parmi une palette prédéfinie ou en spécifiant les composantes RVB ou TSL.
Les arguments de la méthode showDialog de la classe JColorChooser sont :
* la fenêtre principale sur laquelle la fenêtre de dialogue s'affiche,
* le titre de la fenêtre de dialogue,
* la couleur initiale.
La méthode retourne la couleur sélectionnée de classe java.awt.Color ou null si l'utilisateur a annulé.
Exemple : Sélection de la couleur de fond :

### Fenêtre de sélection de fichier ou répertoire : JFileChooser

La classe JFileChooser définit une fenêtre permettant de sélectionner un ou plusieurs fichiers, ou un répertoire.
Exemple : Sélection pour ouvrir un fichier.
Exemple : Sélection pour enregistrer un fichier.
Pour conserver le répertoire courant à chaque réouverture, il vaut mieux que l'instance de la classe JFileChooser soit déclarée dans la classe et construit par le constructeur.

#### Fichier présélectionné

Avant l'affichage, on peut changer le répertoire courant et/ou le fichier sélectionné :

#### Sélectionner plusieurs fichiers

Il est possible d'autoriser la sélection de plusieurs fichiers :

#### Sélectionner un fichier ou un répertoire

Le mode de sélection permet de choisir si l'utilisateur peut sélectionner un fichier, un répertoire ou les deux :

#### Filtres de fichier

La fenêtre de sélection possède deux types de filtre de classe javax.swing.filechooser.FileFilter :
* Un filtre général pour ne pas afficher certains fichiers à l'utilisateur,
* Une liste de filtre que l'utilisateur peut choisir pour afficher différents types de fichiers.
Le filtre général de la vue est configuré en appelant la méthode setFileFilter(FileFilter filter). Exemple :
Les filtres sélectionnables sont ajoutés un par un en appelant la méthode addChoosableFileFilter(FileFilter filter). Exemple :
Vous pouvez utiliser la sous-classe javax.swing.filechooser.FileNameExtensionFilter pour les filtres basés sur l'extension de fichier. Le constructeur prend en paramètre la description du filtre suivie de la liste des extensions de nom des fichiers acceptés :

#### Ajouter une prévisualisation

La fenêtre de sélection de fichiers peut afficher un composant accessoire pour, par exemple, afficher un aperçu du fichier sélectionné (image, ...). Pour ajouter un tel composant, il faut utiliser la méthode setAccessory(Component newAccessory).
Exemple : Une vue de prévisualisation d'image :
Une instance de cette classe s'ajoute en appelant les deux méthodes ci-dessous :