Les gestionnaires de mise en forme
Pour chaque conteneur (fenêtre, panneau, boîte de dialogue, etc.), Java permet de choisir un gestionnaire de mise en forme 1 responsable de la disposition des composants. Nous avons déjà eu l’occasion d’employer des gestionnaires de type FlowLayout ou BorderLayout, sans toutefois en approfondir toutes les propriétés. Nous allons maintenant examiner en détail les différents gestionnaires de mise en forme proposés par Java. Outre les deux que nous avons déjà rencontrés, nous étudierons :
- CardLayout : il permet de disposer des composants suivant une pile, à la manière d’un paquet de cartes, un seul composant étant visible à la fois ;
- GridLayout : il permet de disposer les composants suivant une grille régulière, chaque composant ayant la même taille ;
- BoxLayout : il permet de disposer des composants suivant une même ligne ou une même colonne, mais avec plus de souplesse que le précédent ;
- GridBagLayout : comme GridLayout, il permet de disposer les composants suivant une
grille, mais ceux-ci peuvent occuper plusieurs cellules ; en outre, on peut imposer diverses
« contraintes » indiquant comment la taille des cellules peut être modifiée au fil de l’exécution.
- En anglais Layout manager. On dit aussi gestionnaire de disposition.
Les gestionnaires de mise en forme
Le gestionnaire BorderLayout
Le gestionnaire BorderLayout dispose les composants suivant l’un des quatre bords du conteneur ou au centre.Les composants déposés sur l’un des bords ont une épaisseur fixe, et le composant déposé au centre occupe l’espace laissé libre. Tant qu’un bord n’est pas occupé par un composant,l’espace correspondant est utilisable par le composant central. On choisit l’emplacement d’un composant en fournissant en argument de la méthode add l’une des constantes entières suivantes (on peut utiliser indifféremment le nom de constante ou sa valeur) :Le paramètre de placement d’un composant avec BorderLayoutSi aucune valeur n’est précisée à la méthode add, le composant est placé au centre.Par défaut, les composants sont espacés de 5 pixels. On peut demander un intervalle différentau moment de la construction du gestionnaire, comme dans cet exemple appliqué à un conteneur nommé conteneur :conteneur.setLayout (new BorderLayout (10, 20)) ; Ici, on obtiendra entre les composants un intervalle horizontal de 10 pixels et un intervallevertical de 20 pixels.On peut également agir sur cet intervalle après construction en utilisant les méthodessetHgap ou setVgap de la classe BorderLayout. Dans ce cas, il est nécessaire de conserver laréférence au gestionnaire, comme dans cet exemple :
BorderLayout g = new BorderLayout() ;
…..
g.setHgap (15) ; // intervalle horizontal entre composants de 15 pixels
g.setVgap (8) ; // intervalle vertical entre composants de 8 pixels
…..
conteneur.setLayout(g) ;
Voici un petit programme d’illustration. Il place un bouton dans chacune des cinq zones du contenu (getContentPane()) d’une fenêtre, lequel dispose par défaut d’un gestionnaire BorderLayout. Différents exemples d’exécution montrent ensuite comment évolue la disposition des boutons lorsque l’utilisateur retaille la fenêtre. On remarquera que les zones des bords conservent une taille fixe.Constante symbolique Valeur Emplacement correspondant
BorderLayout.NORTH
BorderLayout.SOUTH
BorderLayout.EAST
BorderLayout.WEST
BorderLayout.CENTER
« North »
« South »
« East »
« West »
« Center »
En haut
En bas
A droite
A gauche
Au centre
1 – Le gestionnaire BorderLayout
import javax.swing.* ;
import java.awt.* ;
class MaFenetre extends JFrame
{ public static int NBOUTONS = 5 ;
public MaFenetre ()
{ setTitle (« Exemple BorderLayout ») ;
setSize (300, 180) ;
Container contenu = getContentPane() ;
boutons = new JButton[NBOUTONS] ;
for (int i=0 ; i<NBOUTONS ; i++)
{ boutons[i] = new JButton (« Bouton » + i) ;
}
contenu.add(boutons[0]) ; // au centre par defaut
contenu.add(boutons[1], BorderLayout.NORTH) ;
contenu.add(boutons[2], BorderLayout.SOUTH) ;
contenu.add(boutons[3], BorderLayout.WEST) ;
contenu.add(boutons[4], BorderLayout.EAST) ;
}
private JButton boutons[] ;
}
public class Layout1
{ public static void main (String args[])
{ MaFenetre fen = new MaFenetre() ;
fen.setVisible(true) ;
}
}
2 Le gestionnaire FlowLayout
Comme nous l’avons vu, le gestionnaire FlowLayout dispose les composants les uns à lasuite des autres, sur une même ligne. Lorsqu’une ligne ne possède plus suffisamment deplace, l’affichage se poursuit sur la ligne suivante.Contrairement à ce qui se produisait avec BorderLayout, la taille des composants est respectée. Celle-ci est définie par défaut suivant la nature et le contenu du composant. Par exemple,la longueur des libellés ainsi que la police utilisée pourront influer sur la taille d’un bouton,d’une étiquette ou d’une boîte de liste.On peut toujours imposer une taille à un composant en utilisant la méthode setPreferredSize(on lui fournit un objet de type Dimension dont le constructeur reçoit en argument deuxentiers correspondant à la largeur et à la hauteur voulues). Nous en avons déjà rencontré unexemple avec des boutons au paragraphe 7.3 du chapitre 11 ainsi qu’un exemple avec despanneaux au paragraphe 4.3 du chapitre 15 (par défaut, les panneaux sont de très petitetaille).Lors de la construction d’un gestionnaire FlowLayout, on peut spécifier un paramètre d’alignement d’une ligne de composants par rapport aux bords verticaux de la fenêtre. Pour cela,on utilise l’une des constantes entières suivantes (on peut prendre indifféremment le nom deconstante ou sa valeur) :
Le paramètre d’alignement d’un FlowLayout
Par exemple, avec :conteneur.setLayout (new FlowLayout (FlowLayout.CENTER)) ;les composants seront centrés sur les différentes lignes.Notez que ce choix est fait une fois pour toutes à la construction : toutes les lignes de composants suivront toujours le même alignement.Enfin, toujours lors de la construction, on peut spécifier un intervalle entre les composants(par défaut, il est de 5 pixels, dans les deux directions). Dans ce cas, il faut aussi spécifier leparamètre d’alignement en premier argument, comme dans cet exemple :
conteneur.setLayout (new FlowLayout (FlowLayout.RIGHT, 10, 15)) ;
Constante symbolique Valeur Alignement correspondant de la ligne de composants
FlowLayout.LEFT
FlowLayout.RIGHT
FlowLayout.CENTER
« Left »
« Right »
« Center »
A gauche (valeur par défaut)
A droite
Au centre
Le gestionnaire FlowLayout
Les méthodes setHgap et setVgap, présentées pour BorderLayout, peuvent également être utilisées après la construction. Dans ce cas, il faut conserver la référence au gestionnaire, comme dans cet exemple :
FlowLayout g = new FlowLayout() ;
…..
g.setHgap (15) ; // intervalle horizontal entre composants de 15 pixels
g.setVgap (8) ; // intervalle vertical entre composants de 8 pixels
…..
conteneur.setLayout(g) ;
Voici un petit programme d’illustration. Il place huit1 boutons dans une fenêtre. On utilise un gestionnaire FlowLayout, avec un alignement centré, un intervalle horizontal de 15 pixels et un intervalle vertical de 5 pixels. Les libellés des boutons ont été définis de telle sorte que leur longueur ne soit pas la même pour tous les boutons. Différents exemples d’exécution montrent ensuite comment évolue la disposition des boutons lorsque l’utilisateur retaille la fenêtre.
import javax.swing.* ;
import java.awt.* ;
class MaFenetre extends JFrame
{ public static int NBOUTONS = 8 ;
public MaFenetre ()
{ setTitle (« Exemple FlowLayout ») ;
setSize (350, 180) ;
Container contenu = getContentPane() ;
contenu.setLayout (new FlowLayout(FlowLayout.CENTER, 10, 5)) ;
boutons = new JButton[NBOUTONS] ;
int n = 1 ;
for (int i=0 ; i<NBOUTONS ; i++)
{ boutons[i] = new JButton (« Bouton » + n) ;
n *= 10 ;
contenu.add(boutons[i]) ;
}
}
private JButton boutons[] ;
}
public class Layout2
{ public static void main (String args[])
{ MaFenetre fen = new MaFenetre() ;
fen.setVisible(true) ;
}
}
- Cette valeur, définie par la constante symbolique NBOUTONS, est facilement modifiable.
Exemple d’utilisation d’un gestionnaire FlowLayout
Remarque
En combinant des gestionnaires aussi simples que BorderLayout et FlowLayout, on peut aboutir à des présentations élaborées. En effet, parmi les composants disposés par un gestionnaire, on peut trouver un ou plusieurs conteneurs (souvent des panneaux) qui pourront posséder leur propre gestionnaire. Nous avons rencontré un exemple de ce type au paragraphe 7 du chapitre 12.
Le gestionnaire CardLayout
Le gestionnaire CardLayout permet de disposer des composants suivant une pile, de telle façon que seul le composant supérieur soit visible à un moment donné. Des méthodes permettent de parcourir la pile ou encore de se placer sur un composant donné. A la création d’un tel gestionnaire, on peut préciser des « retraits » entre le composant et le conteneur, par exemple : CardLayout pile = new CardLayout (30, 20) ; // 30 pixels de part et d’autre,
// 20 pixels en haut et en bas
Le choix de ce gestionnaire pour un conteneur nommé conteneur se fait classiquement :
conteneur.setLayout (pile) ;
En général, il sera nécessaire de conserver la référence à l’objet gestionnaire (ici pile) ; on ne pourra pas se contenter d’écrire directement :
conteneur.setLayout (new CardLayout (30, 20)) ;
Lors de l’ajout d’un composant donné compo au conteneur concerné, on doit obligatoirement fournir, en second argument de add, une chaîne servant à identifier le composant1 au sein du conteneur, par exemple :
conteneur.add (compo, « un certain composant ») ;
Notez que, même si cette identification n’est pas nécessaire à la suite du programme, l’argument correspondant doit être fourni (on peut utiliser une chaîne vide). Dans le cas contraire,
on obtiendra une erreur d’exécution.Par défaut, le composant visible est le premier ajouté au conteneur. On peut faire apparaître un autre composant de la pile, de l’une des façons suivantes (notez que la référence au conteneur est utile) :
pile.next (conteneur) ; // affiche le composant suivant
pile.previous (conteneur) ; // affiche le composant précédent
pile.first (conteneur) ; // affiche le premier composant
pile.last (conteneur) ; // affiche le dernier composant
Enfin, on peut faire apparaître un composant d’identification donnée à l’aide de la méthode show, par exemple : pile.show (conteneur, « un certain composant ») ; // affiche le composant
// identifié par la chaîne « un certain composant »
Voici un petit programme d’illustration. Il crée une pile de huit boutons dans un premier panneau. Un second panneau contient des boutons permettant de parcourir la pile à l’aide des
fonctions next, previous, first et last.
import javax.swing.* ; import java.awt.* ;
import java.awt.event.* ; import javax.swing.event.* ;
class MaFenetre extends JFrame implements ActionListener
{ public static int NBOUTONS = 8 ;
public MaFenetre ()
{ setTitle (« Exemple CardLayout ») ; setSize (400, 180) ;
Container contenu = getContentPane() ;
panCard = new JPanel() ; // panneau pour la pile
contenu.add (panCard) ;
panCom = new JPanel() ; // panneau pour les boutons de parcours de la pile
contenu.add (panCom, « South ») ;
- Ne confondez pas cette chaîne avec le libellé qui figure sur certains composants, tels que les boutons, même si, dans ce cas, on utilise souvent le même texte pour les deux.
/* creation de la pile de boutons */
pile = new CardLayout (30, 10) ;
panCard.setLayout (pile) ;
boutons = new JButton[NBOUTONS] ;
for (int i=0 ; i<NBOUTONS ; i++)
{ boutons[i] = new JButton (« Bouton » + i) ;
panCard.add(boutons[i], « Bouton ») ; // identification obligatoire ici
}
/* creation des boutons de parcours de la pile */
prec = new JButton (« precedent ») ; panCom.add (prec) ;
prec.addActionListener(this) ;
suiv = new JButton (« suivant ») ; panCom.add (suiv) ;
suiv.addActionListener(this) ;
prem = new JButton (« premier ») ; panCom.add (prem) ;
prem.addActionListener(this) ;
der = new JButton (« dernier ») ; panCom.add (der) ;
der.addActionListener(this) ;
}
public void actionPerformed (ActionEvent e)
{ JButton source = (JButton)e.getSource() ;
if (source == prec) pile.previous (panCard) ;
if (source == suiv) pile.next (panCard) ;
if (source == prem) pile.first (panCard) ;
if (source == der) pile.last (panCard) ;
}
private JButton boutons[] ;
private JPanel panCard, panCom ;
private CardLayout pile ;
private JButton prec, suiv, prem, der ;
}
public class Layout3
{ public static void main (String args[])
{ MaFenetre fen = new MaFenetre() ; fen.setVisible(true) ;
}
}