DESS MINT |
Programmation Orientée Objets, langage Java
|
2000-2001 |
Henri Garreta
|
La disposition des composants dans les conteneurs est gérée par les LayoutManager.
Par défaut, le LayoutManager associé à un cadre est un BorderLayout, qui distingue cinq zones dans le conteneur : le nord, le sud, l'est, l'ouest et le centre. Sauf indication contraire, les composants sont tous au centre, et on ne voit que le dernier placé. Voici une expérience (le fond du cadre est coloré en rouge afin de l'apercevoir entre les composants lorsque ces derniers laissent des interstices) :
import java.awt.*; public class FenetreEdiPol extends Frame { public static final int LARGEUR = 400; public static final int HAUTEUR = 250; public FenetreEdiPol(String titre) { super(titre); setSize(LARGEUR, HAUTEUR); setBackground(Color.red); add(new Button("Premier bouton")); add(new Button("Second bouton")); add(new Button("Troisieme bouton")); show(); } }
Résultat obtenu :
Fig. 3 - Les uns sur les autres, on ne voit que le dernier !
Ce n'est pas très satisfaisant. Nouvel essai :
public class FenetreEdiPol extends Frame { public static final int LARGEUR = 400; public static final int HAUTEUR = 250; public FenetreEdiPol(String titre) { super(titre); setSize(LARGEUR, HAUTEUR); setBackground(Color.red); add(new Button("Premier bouton"), BorderLayout.NORTH); add(new Button("Second bouton"), BorderLayout.WEST); add(new Button("Troisieme bouton")); show(); } }
résultat obtenu (observez comment (1) l'ordre d'ajout et (2) le contenu de chaque bouton déterminent leur largeur et hauteur) :
Fig. 4 - Les uns à côté des autres, c'est mieux
Par défaut, le BorderLayout associé à notre cadre est crée implicitement par la classe de base, Frame. En le créant explicitement dans la classe dérivée nous avons l'occasion de définir l'écartement horizontal (ici 4 pixels) et vertical (ici 8 pixels) entre les composants :
public class FenetreEdiPol extends Frame { public static final int LARGEUR = 400; public static final int HAUTEUR = 250; public FenetreEdiPol(String titre) { super(titre); setSize(LARGEUR, HAUTEUR); setBackground(Color.red); setLayout(new BorderLayout(4, 8)); add(new Button("Premier bouton"), BorderLayout.NORTH); add(new Button("Second bouton"), BorderLayout.WEST); add(new Button("Troisieme bouton")); show(); } }
résultat obtenu :
Fig. 5 - Un peu d'écartement permet de voir le fond
L'espace laissé aux bords du conteneur est donné par la fonction getInsets, définie dans la classe Frame. Rédéfinir cette fonction est une manière d'augmenter l'espacement. Dans l'exemple suivant, on laisse 5 pixels tout autour du conteneur :
public class FenetreEdiPol extends Frame { public static final int LARGEUR = 400; public static final int HAUTEUR = 250; public FenetreEdiPol(String titre) { super(titre); setSize(LARGEUR, HAUTEUR); setBackground(Color.red); setLayout(new BorderLayout(4, 8)); add(new Button("Premier bouton", BorderLayout.NORTH)); add(new Button("Second bouton", BorderLayout.WEST)); add(new Button("Troisieme bouton")); show(); } public Insets getInsets() { Insets n = super.getInsets(); return new Insets(n.top + 5, n.left + 5, n.bottom + 5, n.right + 5); } }
Nouvelle apparence :
Fig. 6 - On peut aussi laisser un peu de marge au bord
Un FlowLayout dispose les composants par lignes, de la gauche vers la droite et du haut vers le bas. Par défaut, les composants sont centrés dans chaque ligne. Exemple :
public class FenetreEdiPol extends Frame { public static final int LARGEUR = 400; public static final int HAUTEUR = 250; public FenetreEdiPol(String titre) { super(titre); setSize(LARGEUR, HAUTEUR); setBackground(Color.red); setLayout(new FlowLayout()); add(new Button("Un")); add(new Button("Deux")); add(new Button("Trois")); show(); } }
Résultat obtenu :
Fig. 7 - FlowLayout, tout à fait autre chose
On peut aligner les composants autrement qu'au centre de la ligne :
public class FenetreEdiPol extends Frame { public static final int LARGEUR = 400; public static final int HAUTEUR = 250; public FenetreEdiPol(String titre) { super(titre); setSize(LARGEUR, HAUTEUR); setBackground(Color.red); setLayout(new FlowLayout(FlowLayout.LEFT)); add(new Button("Un")); add(new Button("Deux")); add(new Button("Trois")); show(); } }
le résultat obtenu est sans surprise :
Fig.8 - Cadrage à gauche
Un GridLayout organise le conteneur en une matrice rectangulaire. Dans l'exemple suivant, on dispose 35 boutons (des Button, c'est plus vite fait que des Panel) dans une grille de 5 lignes et 7 colonnes :
public class FenetreEdiPol extends Frame { public static final int LARGEUR = 400; public static final int HAUTEUR = 250; public FenetreEdiPol(String titre) { super(titre); setSize(LARGEUR, HAUTEUR); setLayout(new GridLayout(5, 7)); for (int i = 0; i < 35; i++) { Button p = new Button(new Integer(i).toString()); p.setBackground(i % 2 == 0 ? Color.red : Color.green); add(p); } show(); } }
Le résultat est... coloré :
Fig. 9 - Beau, hein ?
Pour obtenir d'autres arrangements on est amenés à "empiler" les gestionnaires de disposition. Dans l'exemple suivant (utilisé dans EdiPol), un gestionnaire BorderLayout est employé pour disposer un (gros) panneau en haut et une bande étroite en bas de la fenêtre. Ensuite, un gestionnaire GridLayout permet de diviser le gros panneau en deux moitiés de même taille :
public class FenetreEdiPol extends Frame { public static final int LARGEUR = 400; public static final int HAUTEUR = 250; public FenetreEdiPol(String titre) { super(titre); setSize(LARGEUR, HAUTEUR); Panel p1, p2, p3, p4; (p1 = new Panel()).setBackground(Color.yellow); (p2 = new Panel()).setBackground(Color.green); (p3 = new Panel()).setBackground(Color.red); (p4 = new Panel()).setBackground(Color.blue); p1.setLayout(new GridLayout(1, 2)); p1.add(p3); p1.add(p4); add(p1, "Center"); add(p2, "South"); show(); } }
Résultat :
Fig. 10 - Un GridLayout (horizontalement) par-dessus un BorderLayout (centre+sud)
[ On consultera la documentation officielle pour des informations sur les autres sortes de LayoutManager : CardLayout, GridBagLayout ]
Enfin, notez aussi qu'on peut se passer de tout LayoutManager ; il faut alors gérer soi-même le positionnement des composants :
public class FenetreEdiPol extends Frame { public static final int LARGEUR = 400; public static final int HAUTEUR = 250; public FenetreEdiPol(String titre) { super(titre); setSize(LARGEUR, HAUTEUR); setBackground(Color.red); setLayout(null); // pas de LayoutManager, merci! Button bouton; add(bouton = new Button("Un")); bouton.setLocation(290, 30); bouton.setSize(100, 25); add(bouton = new Button("Deux")); bouton.setBounds(290, 60, 100, 25); // comme setLocation + setSize add(bouton = new Button("Trois")); bouton.setBounds(290, 90, 100, 25); show(); } }
Résultat :
Fig. 11a - Fait à la main...
L'ennui de cette manière de faire est la gestion du repositionnement. Si on ne fait rien, la fenêtre supporte mal les changements de taille ou de forme :
Fig 11b - ... c'est plus difficile à maintenir !
Fin du document annexe