Tous les systèmes d'exploitation moderne sont maintenant
dotés d'interfaces graphiques. Pour assurer l'indépendance de JAVA par rapport
à la plate-forme, les concepteurs aurait pu concevoir des composants graphiques
spécifiques. Ils ont préféré réutiliser les composants de la machine client
au moyen d'interfaces implantés dans la machine virtuelle du navigateur. La
gestion des composants graphiques est basée sur la notion de conteneurs
qui sont des espaces graphiques destinés à recevoir plusieurs composants comme
des boutons, des cases à cocher ... dont la mise en place graphique est
fonction d'un protocole de mise en page. En effet, selon les systèmes
d'exploitation, la taille et l'aspect de ces composants varient et il se pose
le problème de leur positionnement.
La classe Applet dérive
de la classe Panel qui est une extension de la classe abstraite Container.
La classe Panel (panneau) représente des conteneurs qui sont placés dans un
espace graphique existant pouvant être un autre Panel : une applet étant
un Panel peut donc contenir d'autres Panels (système récursif).
Avant
d'examiner au chapitre suivant les composants graphiques gérés par JAVA, nous
allons maintenant examiner les différents gestionnaires de mise en page associés
aux conteneurs.
C'est la mise en page par défaut (elle est utilisée quand aucun protocole
n'est précisé). Dans cette mise en page "glissante", les composants graphiques sont ajoutés
les uns après les autres de gauche à droite avec un saut de ligne quand il n'y
a plus de place à droite. L'aspect final dépend donc de la taille de la fenêtre
de l'applet.
Les trois constructeurs possibles possèdent la syntaxe :
FlowLayout(
), FlowLayout(int align) et FlowLayout(int align, int dx, int
dy). dx et dy précisent l'écartement des composants en x et y.
Les constantes FlowLayout.LEFT = 0, FlowLayout.CENTER
= 1 (défaut) et FlowLayout.RIGHT = 2 précisent l'alignement (align) dans une
ligne.
Dans l'exemple suivant, on utilise comme composants un tableau de 4 boutons. La taille des boutons est fonction de la fonte utilisée : il est donc essentiel de définir celle-ci. La valeur de la constante pos est passée à l'applet par une balise <param>. On peut constater l'évolution de l'aspect final en fonction de la taille de l'applet. Remarquez aussi que seule la surface des composants masque la zone de dessin.
import java.applet.*;
import
java.awt.*;
public class layflow extends
Applet
{ Button bt[] = new Button[4]; //déclaration
des boutons
Font
font= new Font("TimesRoman",0,12);
FlowLayout fl; //déclaration
du gestionnaire
int
p;
public void init()
{ setBackground(Color.lightGray);
setFont(font);
p
= Integer.parseInt(getParameter("pos")); //récupération
de pos
fl
= new FlowLayout(p,15,8); //création
du gestionnaire
setLayout(fl);
//mise
en place
for
(int i=0; i<5; i++){
bt[i]=new
Button(" Bouton "+(i+1)); //création
des boutons
add(bt[i]);}}
// méthode add( ) pour la mise
en place des boutons
public void paint(Graphics
g)
{ g.setFont(font);
g.drawString("Test
de flowLayout avec pos = "+p, 40, 100);
g.drawLine(0,0,size().width,size().height);}
}
|
|
|
|
Dans tous les cas de mise en place simple avec peu de composants il faut utiliser ce gestionnaire.
La mise en place glissante offre peu de possibilité pour les mises en page complexes. Le protocole de spécification par les bords BorderLayout décompose le conteneur en 5 zones (précisées par les constantes North, South, East, West et Center) qui peuvent recevoir chacune un seul composant. Le constructeur BorderLayout(int dx, int dy) permet de préciser l'espace entre les composants selon x et y. Les dimensions des composants sont fonctions des dimensions du container mais leurs positions sont maintenant définies. L'exemple ci-dessous indique comment utiliser ce gestionnaire.
import java.applet.*;
import
java.awt.*;
public class layborder extends
Applet
{ Button bt[]=new Button[5];
Font font= new Font("TimesRoman",0,12);
BorderLayout
fl;
public void init()
{ setBackground(Color.lightGray);
setFont(font);
fl
= new BorderLayout(10,30);//création
du gestionnaire
setLayout(fl);
for
(int i=0; i<5; i++)
bt[i]=new
Button(" Bouton "+(i+1));//création
des boutons
add("North",bt[0]); add("South",bt[1]);//mise
en place
add("East",bt[2]); add("West",bt[3]);
add("Center",bt[4]); }
public void paint(Graphics
g)
{ g.setFont(font);
g.drawString("Test
de BorderLayout",40,110);
g.drawLine(0,0,size().width,size().height);}
}
Avec cet exemple simpliste ce protocole semble peu intéressant puisque chaque
composant graphique occupe toute la place qui lui est offerte. C'est ici que l'on peut
faire intervenir la récursivité des protocoles : un conteneur
est lui-même un composant graphique qui peut contenir d'autres conteneurs.
Le conteneur le mieux adapté est le panneau (Panel). Avec cette technique, il
est possible de concevoir des mises en page d'applets assez complexes avec un
code relativement simple.
Ainsi dans l'exemple suivant, nous allons placer
des composants dans le haut et dans le bas de l'applet en utilisant deux objets
panneaux dotés chacun de son propre gestionnaire de mise en page. Pour
la mise en place des boutons dans chaque panneau, on utilise la méthode add(
) de l'instance de Panel utilisée.
import java.applet.*;
import
java.awt.*;
public class layborder2 extends
Applet
{ Button bt[]=new Button[5];
Font
font= new Font("TimesRoman",0,12);
Font bold=
new Font("TimesRoman",1,14);
Panel Panor=new
Panel(), Pasud=new Panel(); //création
des Panels
BorderLayout
fl= new BorderLayout(10,30); //Protocole
principal
public void
init()
{ setBackground(Color.lightGray);
setFont(font);
//fonte pour les composants
setLayout(fl);
add("North",Panor); add("South",Pasud);
//ajout des panneaux
Panor.setLayout(new
FlowLayout(1,20,5)); //protocole
du panneau supérieur
Pasud.setLayout(new
FlowLayout(2,30,10)); //protocole
du panneau inférieur
for
(int i=0; i<5; i++) //création
des boutons
bt[i]=new
Button(" Bouton "+(i+1));
for (int
i=0; i<3; i++) Panor.add(bt[i]); //mise
en place des boutons du haut
for
(int i=3; i<5; i++) Pasud.add(bt[i]);}
public void paint(Graphics
g)
{ g.setFont(bold); //fonte
pour l'applet
g.drawString("Test
de BorderLayout avec Panels",40,80);
g.drawLine(0,0,size().width,size().height);}
}
Attention : Les Panels ainsi mis en place limitent la surface de dessin de l'applet !
Ce protocole définit une grille dont chaque cellule peut contenir un
composant graphique. Les composants sont ajoutés de gauche à droite ligne par
ligne. Utilisé seul ce gestionnaire n'a pas beaucoup d'intérêt. Par contre utilisé
avec un protocole BorderLayout et des panneaux, il permet des mises en page
intéressantes. Il existe deux constructeurs GridLayout( int lig, int col)
et GridLayout( int lig, int col, int dx, int dy); lig indique
le nombre de lignes de la grille et col son nombre de colonnes; dx
et dy précisent l'écartement entre les composants.
Dans l'exemple
suivant, on met en place dans un panneau Pasud un autre panneau PasuW doté d'un
protocole Grid Layout qui va contenir 10 boutons. Il est en effet impossible
de placer directement ce protocole dans Pasud car alors les composants occuperaient
toute la largeur offerte. La surface en dessous du trait horizontal n'est plus
disponible pour le dessin (elle est occupée par le panneau Pasud) mais peut elle peut éventuellement
contenir des composants.
import java.applet.*;
import java.awt.*;
public class laygrid extends Applet
{ Button bt[]=new Button[3];
Button bu[]=new Button[10];
Font font= new Font("TimesRoman",0,14);
Font bold= new Font("TimesRoman",1,12);
Panel Panor=new Panel(),
Pasud=new Panel();
Panel PasuW=new Panel(); //container
pour les boutons bu
BorderLayout fl= new BorderLayout(10,10);
public void init()
{ setBackground(Color.lightGray);
Panor.setFont(font); Pasud.setFont(bold);
//choix des fontes
setLayout(fl);
add("North",Panor); add("South",Pasud);
Panor.setLayout(new
FlowLayout(1,20,5)); //protocoles
des panneaux
Pasud.setLayout(new
FlowLayout(0,5,5)); //principaux
Pasud.add(PasuW);
//1
panneau dans un autre
PasuW.setLayout(new
GridLayout(4,3,5,5));
//avec
son gestionnaire (une grille de 4 lignes de 3 colonnes)
for
(int i=0; i<3; i++) //création
des boutons bt
bt[i]=new
Button(" Bouton "+(i+1));
for
(int i=0; i<10; i++) //création
des boutons bu
bu[i]=new
Button(" "+i+" ");
for
(int i=0; i<3; i++) Panor.add(bt[i]); //et
mise en place
for
(int i=1; i<10; i++) PasuW.add(bu[i]);
PasuW.add(bu[0]);}
public void paint(Graphics
g)
{ g.setFont(font);
g.drawString("Test
de GridLayout avec Panels",20,70);
g.drawLine(0,118,320,118);
//pour contrôle de la
zone utile
g.drawLine(0,size().height,size().width,0);}
}
Il existe également le gestionnaire CardLayout qui ne peut afficher qu'un seul composant à la fois (en général un panneau qui va posséder ses propres composants).Ce gestionnaire est doté de méthodes first( ), last( ), previous( ) et shows( ) qui permettent de naviguer entre les cartes. Ceci suppose la mise en place de boutons de navigation sur chaque carte.
Enfin pour les situations complexes, existe le protocole
GridBagLayout qui fonctionne avec des contraintes précisées par la classe
GridBagConstraints. Dans ce gestionnaire chaque composnt est inséré dans
un conteneur et on lui associe une contrainte qui précise son emplacement dans
une grille, sa taille...
Ce protocole est très lourd à mettre en oeuvre et
je ne le décrirai pas car il existe (à mon avis) une méthode beaucoup plus facile
à mettre en application dans les applets qui est la méthode sans gestionnaire.
Dans une applet, la taille de la fenêtre est imposée par les paramètres
width et height de la balise <applet>. Il est donc possible de prévoir
l'aspect final de l'applet dans le navigateur si la taille des composants est
connue. Il existe pour les composants la méthode reshape(int ox, int oy,
int large, int haut) qui permet d'imposer au composant sa position (ox,
et oy) et ses
dimensions (large et haut) à condition qu'un gestionnaire de mise en page ne soit pas actif.
Comme par défaut JAVA utilise un protocole FlowLayout, il faut commencer par
déclarer que celui-ci est inactif au moyen de l'instruction FlowLayout fl
= null. On peut ensuite placer les composants dans la fenêtre aux endroits
souhaités. Cette technique suppose que la fonte utilisée pour les composants
soit définie dès le départ. Comme exemple, on va reprendre le cas précédent.
On peut constater que cette technique est beaucoup plus souple au niveau du
positionnement des composants. On peut aussi constater qu'aucun panneau ne vient
masquer la surface de l'applet.
Remarque : depuis la version 1.1, la méthode reshape(
) a été remplacée par la méthode setBounds( ) qui possède les
mêmes arguments (en fait seul le nom de la méthode a changé).
import java.applet.*;
import
java.awt.*;
public class laynull extends
Applet
{ Button bt[]=new Button[3];
Button bu[]=new Button[10];
Font
font= new Font("TimesRoman",0,14);
Font bold= new Font("TimesRoman",1,12);
FlowLayout
fl= null; //essentiel
public void init()
{ setBackground(Color.lightGray);
setLayout(fl);
//essentiel
for
(int i=0; i<3; i++){
bt[i]=new Button("Bouton
"+(i+1));//création
add(bt[i]);
//ajout
bt[i].setFont(font);
//fonte du composant
bt[i].reshape(20+100*i,5,80,22);}
//mise en place
setFont(bold);
//fonte par défaut pour
les composants à venir
for
(int i=0; i<10; i++)
bu[i]=new Button("
"+i+" ");//création
int k=0;
for
(int l=80; l<150; l+=30){
for (int
c=0; c<3; c++){
k++;
add(bu[k]);
//ajout
bu[k].reshape(100+30*c,l,25,25);}}//mise
en place
add(bu[0]);
bu[0].reshape(130,170,25,25);}
public void paint(Graphics
g)
{ g.setFont(font);
g.drawString("Test
sans gestionnaire",20,60);
g.drawLine(0,size().height,size().width,0);}
}