Programmation Java Swing/Gestion de la disposition des composants

La disposition des composants n'est pas définie directement par le conteneur mais par le gestionnaire de disposition des composants (Layout manager en anglais).

Informations utilisées et contrainte associée

modifier

Le gestionnaire peut utiliser différentes informations fournies par le composant :

Dimension getPreferredSize()
La taille préférée du composant, qui dépend en général de son contenu et du moteur de rendu utilisé.
Dimension getMinimumSize()
La taille minimale du composant. C'est la taille en dessous de laquelle le composant est jugé non utilisable (pas assez de place pour tout afficher, ...).
Dimension getMaximumSize()
La taille maximale du composant.

Les gestionnaires de disposition ne respectent pas tous les trois contraintes précédentes définies par le composant.

Le code typique de création d'un conteneur avec gestionnaire de disposition est le suivant :

// Créer le conteneur et lui associer le gestionnaire de disposition Conteneur c = new Conteneur() c.setLayout(new GestionnaireDeDisposition(arguments...));

// Ajouter les composants avec une contrainte de disposition c.add(composant, contrainte);

Exemple :

JPanel p_main = new JPanel();
p_main.setLayout(new BorderLayout());

// Titre en haut (au nord)
JLabel label_titre = new JLabel("Titre ici");
p_main.add(label_titre, BorderLayout.NORTH);

// Panel de vue des données au centre
JPanel p_view = new JPanel();
p_main.add(p_view, BorderLayout.CENTER);

// Panel des boutons en bas (au sud)
JPanel p_boutons = new JPanel();
p_main.add(p_boutons, BorderLayout.SOUTH);

Gestionnaires de disposition prédéfinis

modifier

Les interfaces java.awt.LayoutManager et java.awt.LayoutManager2 sont définies par une variété de classes définissant différentes façon de disposer les composants :

FlowLayout
Les composants sont dimensionnés à leur taille préférée, et disposés en ligne, avec passage à la ligne suivante dès que la largeur restante ne suffit plus. Les lignes peuvent être justifiées à gauche, à droite ou centrées dans le contenant.
 
Exemple de boutons alignés avec FlowLayout.
new FlowLayout() // composants alignés à gauche par défaut
new FlowLayout(FlowLayout.LEFT) // composants alignés à gauche
new FlowLayout(FlowLayout.RIGHT) // composants alignés à droite
new FlowLayout(FlowLayout.CENTER) // composants centrés
L'alignement peut aussi prendre en compte le sens de lecture de gauche à droite ou de droite à gauche, leading pour le début (gauche / droite) et trailing pour la fin (droite / gauche) :
new FlowLayout(FlowLayout.LEADING) // composants alignés en début de ligne
new FlowLayout(FlowLayout.TRAILING) // composants alignés en fin de ligne
Le constructeur peut prendre deux paramètres supplémentaires, espacement horizontal et vertical, pour spécifier l'espacement entre les composants et entre le conteneur et les composants :
new FlowLayout(FlowLayout.RIGHT, 10, 5) // composants alignés à droite espacés de 10 pixels en horizontal et 5 en vertical.
BorderLayout
Le conteneur est divisé verticalement en trois zones, de haut en bas : nord (BorderLayout.NORTH), centrale et sud (BorderLayout.SOUTH). La partie centrale est elle-même divisée horizontalement en trois zones, de gauche à droite : ouest (BorderLayout.WEST), centre (BorderLayout.CENTER) et est (BorderLayout.EAST).
 
Le constructeur peut prendre deux paramètres, espacement horizontal et vertical, pour spécifier l'espacement entre les composants :
new BorderLayout() // composants non espacés
new BorderLayout(10, 5) // composants espacés de 10 pixels en horizontal et 5 en vertical.
GridLayout
Les composants sont dimensionnés selon la taille du conteneur divisée en colonnes et lignes dont le nombre et l'espacement est indiqué à l'appel du constructeur. Les composants sont positionnés dans l'ordre de leur ajout au conteneur, de gauche à droite en partant de la ligne supérieure.
GridBagLayout
Les composants sont dimensionnés à leur taille préférée si la contrainte associée le permet. La contrainte associée est de classe GridBagConstraint et définit la position dans la grille, le nombre de cellules occupées, et les contraintes de taille et d'alignement du composant dans la cellule.
CardLayout
Les composants sont dimensionnés à la taille du conteneur, et un seul des composants n'est visible à la fois. Cette disposition est utilisée pour implémenter les onglets.
GroupLayout
Les composants sont dimensionnés à leur taille préférée si possible, et groupés ensemble soit parallèlement, soit séquentiellement, en vertical et en horizontal. Cela signifie que les composants sont ajoutés deux fois par le gestionnaire. Ils ne sont pas ajoutés directement au conteneur.
BoxLayout
Les composants sont dimensionnés à leur taille préférée si possible, et alignés verticalement ou horizontalement. L'alignement selon l'autre axe est définie par l'alignement préférée du composant. Ce gestionnaire tient compte également de la taille minimale et maximale de chaque composant.

Le gestionnaire de disposition doit être assigné au conteneur soit en le passant au constructeur, soit en appelant la méthode setLayout après construction du conteneur. Exemple:

JPanel p_main = new JPanel(new BorderLayout());

Pour BoxLayout, l'utilisation de la méthode setLayout est obligatoire car le constructeur a besoin de l'instance du conteneur :

JPanel p_main = new JPanel();
p_main.setLayout(new BoxLayout(p_main, BoxLayout.Y_AXIS));
// L'appel à setLayout doit se faire avec le même conteneur que celui passé à BoxLayout
// sinon l'exception suivante est levée :
//     java.awt.AWTError: BoxLayout can't be shared

Disposition par défaut des conteneurs

modifier

Un conteneur possède un gestionnaire de disposition par défaut.

JPanel
FlowLayout est le gestionnaire de disposition par défaut.
JTabbedPane
CardLayout est le gestionnaire de disposition utilisé car ce conteneur est une vue à onglets. Les onglets sont visibles en haut du conteneur par défaut, et cliquable par l'utilisateur pour changer l'onglet visible.