3. Un exemple complet.▲
Nous allons maintenant développer une simple interface utilisateur pas à pas. L'interface que nous avons choisie est un simple « Explorateur de dossiers », comme nous retrouvons dans Firefox. Voyons en images ce que nous devons réaliser.
Il est toujours important de bien savoir ce à quoi nous désirons arriver avant de commencer. Non pas qu'il soit compliqué d'adapter une interface, mais réfléchir sur une interface est bien plus efficace avec un crayon, une gomme sur une feuille de papier que dans un IDE quelconque. A gauche nous voyons notre interface à sa taille minimale. A droite, nous l'avons agrandie pour observer comment les composants de celle-ci se redimensionnent. Nous pouvons voir que seulement deux composants sont redimensionnés : l'arbre contenant la structure de fichier et la zone qui permet de saisir le nom du dossier. Nous pouvons également remarquer que les boutons Ok et Cancel ont toujours la même taille et qu'ils restent groupés à droite. Le bouton Make New Folder quant à lui reste aligné à gauche.
Il n'est pas toujours évident de savoir par où commencer. Nous, nous commencerons par nos trois étapes du début de ce tutoriel.
1- Initialisation d'un container avec le GridBagLayout.
Avouons que ceci est assez élémentaire. Le code pourrait se résumer à :
/* 1- Initialisation du container. */
mainFrame.setLayout
(
new
GridBagLayout
(
));
2- Création et initialisation des composants.
Ceci est toujours très simple comme étape. Nous avons sur notre interface :
- Trois boutons : Make new folder - Ok et Cancel.
- Deux étiquettes : Choose Download Folder et Folder.
- Un champ de saisie.
- Une arborescence pour afficher les dossiers.
Au total, sept composants à créer et initialiser. Nous allons commencer par les étiquettes.
JLabel chooseLabel =
new
JLabel
(
"Choose Download Folder :"
);
JLabel folderLabel =
new
JLabel
(
"Folder :"
);
Continuons avec le champ de saisie.
JTextField folderTextField =
new
JTextField
(
);
Jusqu'ici, toujours aucun soucis. Continuons avec les boutons. Trois boutons, dont deux ayant les mêmes largeurs.
JButton makeNewFolderButton =
new
JButton
(
"Make New Folder"
);
JButton okButton =
new
JButton
(
"Ok"
);
JButton cancelButton =
new
JButton
(
"Cancel"
);
Pour que les boutons Ok et Cancel ont la même taille, nous devons leur préciser une même taille préférée et minimale. Les tailles du bouton makeNewFolder seront initialisées par Swing.
okButton.setPreferredSize
(
cancelButton.getPreferredSize
(
));
okButton.setMinimumSize
(
cancelButton.getMinimumSize
(
));
Il ne nous reste plus que l'arborescence centrale. Le composant JTree étant capable d'afficher une telle arborescence, nous allons l'utiliser dans notre interface. Mais, rappelons-nous que celui-ci doit être placé dans un JScrollPane, pour pouvoir avoir les barres de défilement lorsque celles-ci sont nécessaires.
JTree folderTree =
new
JTree
(
);
JScrollPane scrollPane =
new
JScrollPane
(
folderTree);
Notre deuxième étape est ainsi terminée.
3- Ajout de ces composants en spécifiant les bonnes contraintes.
Maintenant que nous avons créé nos composants et que nous les avons initialisés, nous allons les ajouter un à un à notre container. Nous allons les ajouter du haut vers le bas. Le premier composant à traiter est donc notre étiquette " Choose Download Folder".
Chacune des contraintes est commentée dans le code directement. Prenez donc le temps d'y jeter un coup d'oeil.
GridBagConstraints gbc =
new
GridBagConstraints
(
);
gbc.gridx =
gbc.gridy =
0
; // la grille commence en (0, 0)
gbc.gridwidth =
GridBagConstraints.REMAINDER; // seul composant de sa colonne, il est donc le dernier.
gbc.gridheight =
1
; // valeur par défaut - peut s'étendre sur une seule ligne.
gbc.anchor =
GridBagConstraints.LINE_START; // ou BASELINE_LEADING mais pas WEST.
gbc.insets =
new
Insets
(
10
, 15
, 0
, 0
); // Marge à gauche de 15 et marge au dessus de 10.
/* - les attributs ipadx, ipdady, weightx et weighty valent tous 0 (valeur par défaut).
* - l'attribut fill est à NONE, car on ne souhaite pas de redimentionnement pour cette étiquette. */
mainFrame.add
(
chooseLabel, gbc);
Passons ensuite à la zone qui servira d'arborescence.
/* réutilisons le même objet <code>gbc</code>. */
/* positionnons notre composant suivant (notre JScrollPane) sur la ligne suivante. */
gbc.gridx =
0
;
gbc.gridy =
1
;
/* ce qui suit est inutile, nous avions déjà définie des valeurs pareilles pour le composant précédent.
* cependant, il est toujours bon d'avoir toute les étapes dans un premier exemple. */
gbc.gridwidth =
GridBagConstraints.REMAINDER;
gbc.gridheight =
1
; // valeur par défaut.
/* Nous pouvons le voir sur l'image à réaliser. Ce composant s'étend sur tout l'espace qu'il recoit aussi bien
* horizontalement que verticalement.
* Remarquons que c'est souvent le cas pour ce genre de composant de les laissez s'étendre un maximum possible dans
* le container en récupérant l'espace supplémentaire.
*/
gbc.weightx =
1.
;
gbc.weighty =
1.
;
gbc.fill =
GridBagConstraints.BOTH;
gbc.anchor =
GridBagConstraints.LINE_START; // pas WEST.
/* Marge à gauche de 15 (gardons la même que précédemment)
* Marge au dessus de 30 et
* Marge à droite de 10. */
gbc.insets =
new
Insets
(
30
, 15
, 0
, 10
);
mainFrame.add
(
scrollPane, gbc);
Viens ensuite l'étiquette 'Folder' et une zone de saisie.
/* le composant suivant à placer est notre étiquette.
* Réutilisons encore le même objet gbc.*/
gbc.gridx =
0
;
gbc.gridy =
2
;
/* une seule cellule sera disponible pour ce composant. */
gbc.gridwidth =
1
;
gbc.gridheight =
1
;
/* Nous devons supprimer les poids que nous avons spécifiés précédemment, et supprimer
* le redimentionnement. */
gbc.weightx =
0.
;
gbc.weighty =
0.
;
gbc.fill =
GridBagConstraints.NONE;
/* Maintenant, nous voyons sur notre interface que le composant n'est pas le seul sur sa ligne.
* Un champ de saisie le suit. Pour aligner correctement les étiquettes et les champs de saisie,
* la ligne d'écriture nous facilite le travail. Nous allons l'utiliser ici. */
gbc.anchor =
GridBagConstraints.BASELINE_LEADING; // pas LINE_START ni WEST !!
/* Une petite marge autour du composant. Attention à toujours indiquer les mêmes marges à gauche, sinon les
* composants ne sont plus alignés. */
gbc.insets =
new
Insets
(
10
, 15
, 0
, 0
);
mainFrame.add
(
folderLabel, gbc);
/* passons au composant suivant: le champ de saisie. */
gbc.gridx =
1
; /* une position horizontalement à droite de l'étiquette */
gbc.gridy =
2
; /* sur la même ligne que l'étiquette */
gbc.gridwidth =
GridBagConstraints.REMAINDER; /* il est le dernier composant de sa ligne. */
gbc.gridheight =
1
; /* une seule cellule verticalement suffit */
/* Le composant peut s'étendre sur tout l'espace qui lui est attribué horizontalement. */
gbc.fill =
GridBagConstraints.HORIZONTAL;
/* Alignons ce composant sur la même ligne d'écriture que son étiquette. */
gbc.anchor =
GridBagConstraints.BASELINE;
/* Une petite marge autour du composant. Remarquons que nous n'avons pas spécifié de marge au dessus du
* composant. Comme nous avons décidé d'alginer ce composant sur la même ligne d'écriture que l'étiquette,
* la marge du haut sera calculée en interne pour s'aligner correctement avec l'étiquette. */
gbc.insets =
new
Insets
(
0
, 15
, 0
, 10
);
mainFrame.add
(
folderTextField, gbc);
Il ne nous reste plus que nos boutons.
/* Nous pouvons passé aux boutons. */
gbc.gridy =
3
; /* nouvelle ligne */
gbc.gridx =
0
; /* première colonne, nous allons placé notre bouton "make new folder" */
/* Reprenons l'image. Nous voyons que le bouton est plus large que l'étiquette située au dessus de lui et
* que le champ de saisie commence avant le bord gauche du bouton. Nous précisons donc deux cellules
* horizontalement.
*/
gbc.gridwidth =
2
;
gbc.gridheight =
1
; /* une seule cellule verticalement suffit */
/* Nous allons alignerles boutons sur leur ligne d'écriture également.*/
gbc.anchor =
GridBagConstraints.BASELINE_LEADING;
/* Aucun redimentionnement possible. Le bouton garde toujours soit sa taille minimum soit préférée. */
gbc.fill =
GridBagConstraints.NONE;
/* Les attributs weightx, weighty sont tout deux à 0.*/
/* Une petite marge autour du composant.*/
gbc.insets =
new
Insets
(
10
, 15
, 10
, 10
);
mainFrame.add
(
makeNewFolderButton, gbc);
/* bouton suivant. */
/* le bouton précédent peut s'étendre sur deux cellules horizontalement. Celui-ci commence en 2. */
gbc.gridx =
2
; /* pour les dubitatifs, gridy vaut toujours 3 ;-) */
gbc.gridwidth =
GridBagConstraints.RELATIVE; // le bouton est l'avant dernier composant de sa ligne.
/* nous allons, sur ce bouton, définir un poids pour que celui-ci s'éloigne le plus du bouton précédent.*/
gbc.weightx =
1.
;
gbc.anchor =
GridBagConstraints.BASELINE_TRAILING; // Pas LINE_END, ni EAST.
gbc.insets =
new
Insets
(
0
, 0
, 0
, 0
);
mainFrame.add
(
okButton, gbc);
/* notre dernier bouton. */
gbc.gridx =
3
;
gbc.weightx =
0.
; /* remettons le poids à zéro. */
gbc.insets =
new
Insets
(
0
, 3
, 0
, 10
);
mainFrame.add
(
cancelButton, gbc);
Une fois terminé, voici à quoi ressemble notre interface.