Vous êtes sur la page 1sur 17

Ejemplo de uso del GridBagLayout

El GridBagLayout es uno de los Layout de java ms potentes, pero tambin es el que ms


cuesta entender.
Vamos a construir una ventana en la que situamos determinados componentes (botones) en
determinadas posiciones usando el GridBagLayout. Puedes ver los fuentes de ejemplo y
applets funcionando pinchando en algunas de las imgenes que se ven durante la explicacin.

Concepto de layout
A la hora de hacer "ventanitas" en java, un componente es cualquiera de los botones,
etiquetas, listas, mens, etc que podemos colocar en la ventana. Hay determinados
componentes que no tienen un aspecto claro y que nicamente estn destinados a contener a
los dems y se les llama contenedores. Por ejemplo, si una ventana contiene dos botones, la
ventana en si misma en otro componente java que recibe el nombre de contenedor. Otro
ejemplo, si te fijas en la barra de herramientas de tu navegador (echa el ojo un poco para
arriba), vers que est llena de botones-iconos. La barra de herramientas en s misma es otro
contenedor (aunque posiblemente no sea de java, sino del internet explorer o netscape).
Cmo se distribuyen los botones dentro de la ventana?. Todos los contenedores en java
tienen en su interior una clase, de nombre genrico "layout", que es la encargada de distribuir
los botones dentro del contenedor. Por ejemplo, la clase FlowLayout se encarga de hacer que
los botones vayan todos seguidos de izquierda a derecha, como sera el caso de tu barra de
herramientas del navegador. El GridLayout los coloca en forma de matriz, etc, etc.
Cualquier contenedor java tiene una clase layout por defecto, pero la podemos cambiar con el
mtodo setLayout().
En java hay disponibles varios layout como los mencionados anteriormente, la mayora de
ellos son muy sencillos de usar. Basta ponerlos y nos dan pocas opciones para configurar.
Esto es vlido para ventanas sencillas con una distribucin de botones no muy compleja. Por
ejemplo, la barra de herramientas del navegador o el teclado de una calculadora, en el que
todos los botones sean del mismo tamao.
Para ventanas ms complejas estos layout simples se quedan escasos. Java nos proporciona
un layout bastante potente, aunque bastante complejo de usar cuando no se comprende bien:
el GridBagLayout. Este layout ser suficiente para hacer casi cualquier distribucin de botones
en una ventana, por compleja que parezca, pero debemos entender bien su funcionamiento
para que el resultado final se parezca a lo que queremos.

En este tutorial vamos a hacer una ventanita con unos botones usando el GridBagLayout y
vamos a ver paso a paso cmo usarlo. La ventana que pretendemos obtener es la de la
siguiente figura:

Pincha la imagen para ver el applet que produce esta ventana y sus cdigo fuente.
Juega a estirar la ventana para ver el comportamiento de los componentes en su interior.
Tiene un rea de texto que ocupa casi toda la ventana. Un "Boton 1" en la parte superior
derecha, un "Boton 2" en la derecha hacia el medio, el "Boton 3" en la equina inferior
izquierda, el "Boton 4" en la esquina inferior derecha y un campo de texto entre estos dos
ltimos botones.
Vamos a ello.

Hacer una rejilla adecuada


El primer paso es dibujar la ventana que queremos (a los ms espabilados les bastar con
hacerse una idea mental). Es importante dibujarla ms o menos estirada, para tener claro si
los botones deben hacerse grandes o no. Por ejemplo, en la figura anterior, los botones deben
mantener su tamao aunque estiremos la ventana, sin embargo el area de texto debe crecer
con la ventaa y el campo de texto slo debe crecer horizontalmente.
Luego, sobre el dibujo, hay que trazar unas lineas horizontales y verticales, para tratar de
delimitar una rejilla en la que iran colocados los botones. Para trazar esta rejilla y que luego el
cdigo no nos salga muy complicado conviene tener en cuenta lo siguiente:

Debemos tratar de meter los componentes en las


celdas. Cada componente debe ocupar una o ms
celdas. Dos componentes no pueden ocupar la misma
celda.

No es necesario que las celdas de la rejilla sean todas


del mismo tamao ni es necesario que un componente
ocupe una celda completa.

Para que no se lie el cdigo, conviene que el


componente ocupe toda la celda, o bien que est
centrado en la misma, o bien pegado al centro de uno
de los bordes de la celda o a una esquina de la
misma. Vaya, que no pongamos una celda enorme
con un componente dentro a tres cuartos de la parte
derecha y medio septimo de la parte de arriba.

Un ejemplo de rejilla para nuestra ventana puede ser la de la siguiente figura:

Vamos con las lneas verticales:

La primera en el borde izquierdo de la ventana.

La segunda entre el boton 3 y el campo de texto.

La tercera entre el campo de texto y el boton 4.

La ltima en el borde derecho de la ventana.

Estas lneas son casi obligadas, puesto que el boton 3, el campo de texto y el boton 4 nos las
limitan. No importa que una de ellas pase por enmedio del area de texto, smplemente
haremos que esta ocupe dos columnas. Estas lneas nos limitan tres columnas que hemos
numerado como 0, 1 y 2. Vamos ahora con las lneas horizontales.

La primera por la parte de arriba de la ventana

La segunda puede pasar por cualquier sitio entre el


boton 1 y el boton 2.

La tercera pasa justo por debajo del area de texto y


por encima de boton 3, campo de texto y boton 4

La ltima por el borde inferior de la ventana.

Como hemos dicho, la segunda puede pasar por cualquier lado entre los dos botones. Para
que no se nos complique el cdigo y segn dijimos arriba, cogiendo la segunda lnea pegando
por arriba al botn 2 (como hemos hecho en el dibujo), ya tenemos al boton 2 ocupando la
parte superior de su celda. Tambin podamos haberla pegado al botn 1, as el botn 2
estara ms o menos en el centro de su celda. Lo que complicara luego el cdigo sera poner
la lnea entre ambos botones, por lo que el boton 2 quedara a 1/3 de la parte superior de su
celda.
Podemos trazar ms lineas si queremos, como otras lineas horizontales que pasen por debajo
de boton 1 y boton 2, pero no son necesarias. Tampoco importara mucho hacerlas ni se iba a
complicar excesivamente el cdigo.
Resumiendo, nuestro area de texto ocupa cuatro celdas, los botones una cada uno y el campo
de texto otra. Boton 1 y 2 no ocupan toda la celda, pero estn en la parte superior de la
misma.

Nuestra primera aproximacin


Vamos a hacer nuestro primer cdigo para obtener la ventana. Nuestra ventana ser
un JFrame, as que hacemos una clase que herede de JFrame y le ponemos
elGridBagLayout.
classVentanaextendsJFrame
{
publicVentana()

{
super("Ejemplo1");//El
ttulo
this.getContentPane().setLayout(new
GridBagLayout());//Leponemosel
GridBagLayout
...
}
}
Lo del getContentPane() es porque en realidad la ventana no es el contenedor, sino un
componente que lleva internamente la ventana y que se puede obtener a travs de este
mtodo. Es a este componente al que debemos aadirle el layout y los componentes
(botoncitos y dems).
Ahora debemos empezar a aadir componentes. Tenemos por un lado el mtodo add() con un
slo parmetro.
JTextAreaareaTexto=newJTextArea("Area
texto");
this.getContentPane().add(areaTexto);
Esta llamada aade el rea de texto, dejando al GridBagLayout total libertad para decidir
dnde y cmo ponerlo. No es lo que queremos. Necesitamos el mtodo add() que admite un
segundo parmetro. Este segundo parmetro le indica al layout dnde y cmo colocar el
componente. El segundo parmetro es un Object, lo que quiere decir que podriamos meter
cualquier cosa. Evidentemente esto no es asi, debemos meter algo que el layout entienda.
Cada layout entiende su propio segundo parmetro. ElGridBagLayout admite como segundo
parmetro un GridBagConstraints.
GridBagConstraints en una clase en cuyos atributos se guarda informacin de cmo y dnde
aadir el componente. De momento vamos a contemplar slo cuatro de estos atributos:

GridBagConstraints.gridx nos dice la posicin x del


componente, es decir, el nmero de columna en la que
est el componente, siendo la columna 0 la primera
columna de la izquierda. Si el componente ocupa
varias columnas (como nuestra rea de texto),
debemos indicar la columna en la que est la esquina
superior izquierda del componente.

GridBagConstraints.gridy nos dice la posicin y del


componente, es decir, el nmero de fila en la que est
el componente, siendo la fila 0 la primera fila de la
parte de arriba. Si el componente ocupa varias filas
(como nuestra rea de texto), debemos indicar la fila
en la que est la esquina superior izquierda del
componente.

GridBagConstraints.gridwidth nos dice cuntas


celdas en horizontal debe ocupar el componente. El
ancho del componente.

GridBagConstraints.gridheight nos dice cuantas


celdas en vertical debe ocupar el componente. El alto
del componente.

Con esto podemos aadir nuestra rea de texto


JTextAreaareaTexto=newJTextArea("Area
texto");
GridBagConstraintsconstraints=new
GridBagConstraints();
constraints.gridx=0;//Elreadetexto
empiezaenlacolumnacero.
constraints.gridy=0;//Elreadetexto
empiezaenlafilacero
constraints.gridwidth=2;//Elreade
textoocupadoscolumnas.
constraints.gridheight=2;//Elreade
textoocupa2filas.
this.getContentPane().add(areaTexto,
constraints);
En realidad gridwith y gridheight admite tambin determinadas constantes que hacen que el
componente se estire hasta el final del contenedor, ocupando todas las columnas o filas libres
o hasta que encuentre otro componente. No vamos a usar esas constantes (estn definidas
en GridBagConstraints) y simplemente hemos puesto el nmero de filas y columnas (2 en
ambos casos) que queremos que ocupe.
Los siguientes elementos tienen todos un gridwidth y gridheight de 1, puesto que ocupan una
fila y columna. Las posiciones son las siguientes:

JButtonboton1=newJButton("Boton1");
constraints.gridx=2;
constraints.gridy=0;
constraints.gridwidth=1;
constraints.gridheight=1;
this.getContentPane().add(boton1,
constraints);
JButtonboton2=newJButton("Boton2");
constraints.gridx=2;
constraints.gridy=1;
constraints.gridwidth=1;
constraints.gridheight=1;
this.getContentPane().add(boton2,
constraints);
JButtonboton3=newJButton("Boton3");
constraints.gridx=0;
constraints.gridy=2;
constraints.gridwidth=1;
constraints.gridheight=1;
this.getContentPane().add(boton3,
constraints);
JButtonboton4=newJButton("Boton4");
constraints.gridx=2;
constraints.gridy=2;
constraints.gridwidth=1;
constraints.gridheight=1;
this.getContentPane().add(boton4,
constraints);
JTextFieldcampoTexto=newJTextField
("Campotexto");
constraints.gridx=1;
constraints.gridy=2;
constraints.gridwidth=1;
constraints.gridheight=1;
this.getContentPane().add(campoTexto,
constraints);

Hay un detalle importante a tener en cuenta. Slo hemos hecho


un new de GridBagConstraints, por lo que todos ellos comparten la misma instancia de ese
objeto. Hay que tener en cuenta que si cambiamos uno de los atributos para un componente,
debemos restaurarlo luego para el siguiente. Por ejemplo, para el area de texto
pusimos gridwidtha 2. Para el siguiente componente (el botn1), debemo volver a poner esta
valor a 1.
Por ello es acosejable poner siempre todos los atributos. Otra opcin es hacer
un new GridBagConstraints para cada componente (claramente menos eficiente) o finalmente
la que he seguido en el cdigo de ejemplo, ser muy cuidadoso e ir restaurando valores segn
se van cambiando.
Si ejecutamos lo que tenemos hasta ahora y estiramos un poco la ventana resultante nos sale
lo de la siguiente figura:

Pincha la figura para ver el applet que produce esta ventana y sus cdigo fuente.
Bueno, no se parece mucho a lo que queramos. Se ha quedado todo en el centro de la
ventana y el area de texto es bastante canija. Qu ha pasado?

Estirar las filas y las columnas


Lo que ha pasado es que slo le hemos dicho al GridBagLayout dnde colocar los
componentes y eso lo ha hecho bien. Cada componente est donde debe. Lo que pasa es
que no le hemos dicho nada de cmo estirar las filas y columnas, as que ha hecho lo que

hace por defecto: Cada fila y columna es del tamao mnimo necesario para albergar sus
componentes y estn centradas dentro de la ventana. En la siguiente figura vemos como
estn nuestras filas y columnas:

Las filas son de la altura justa para contener a los botones. Las columnas tambin. El rea de
texto que ocupa cuatro celdas se ha situado en el medio de ellas y le sobra un montn de
espacio.
El siguiente paso a dar consiste en decir cmo se deben estirar las filas columnas. Si
comparamos con la figura en las que marcamos inicialmente las filas y columnas, vemos que
las dos primeras filas deben ser ms anchas, la tercera fila ya est bien de ancho. En cuanto a
las columnas, la segunda es la que debe estirarse, la primera y tercera estn bien.
Para estirar filas y columnas, dentro del GridBagConstraints tenemos los
campos weigthx y weigthy. El primero indica cmo estirar las columnas. El segundo las filas.
Aqui vamos a contar una forma sencilla de usar estos campos que nos servir para la mayora
de los casos. En realidad podramos sacarle bastante ms jugo.
A estos campos debemos darles el valor 0.0 (que es el valor por defecto) si no queremos que
la fila o columna se estire. Este es el caso para la primera y tercera columna, as como para la
tercera fila. Debemos dar el valor 1.0 a las filas o columnas que queremos que se estiren
hasta completar toda la ventana. Es el caso de las dos primeras filas y de la columna del
medio.

Hay dos detalles con estos campos. El primero es que widthy afecta a una fila completa, no
solo a un componente. Por ello, cada vez que aadamos un componente a esa fila, debemos
dar a widthy el mismo valor (o 0.0 o 1.0). Lo mismo pasa con widthx y las columnas. El
segundo detalle es el que comentamos antes, slo estamos usando una instancia
de GridBagConstraints, asi que despus de poner uno de estos campos a 1.0 y aadir un
componente, debemos volver a ponerlo a 0.0 para el siguiente (suponiendo que sea eso lo
que necesita).
El cdigo ahora, aadiendo estos dos campos, quedara as:
JTextAreacajaTexto=newJTextArea("Area
texto");
constraints.gridx=0;//Columna0.No
necesitaestirarse,noponemosweightx
constraints.gridy=0;//Fila0.Necesita
estirarse,hayqueponerweighty
constraints.gridwidth=2;
constraints.gridheight=2;
constraints.weighty=1.0;//Lafila0
debeestirarse,leponemosun1.0
this.getContentPane().add(cajaTexto,
constraints);
constraints.weighty=0.0;//Restauramos
alvalorpordefecto,paranoafectara
lossiguientescomponentes.
JButtonboton1=newJButton("Boton1");
constraints.gridx=2;//Columna2.No
necesitaestirarse,noponemosweightx
constraints.gridy=0;//Fila0.Necesita
estirarse,hayqueponerweighty
constraints.gridwidth=1;
constraints.gridheight=1;
constraints.weighty=1.0;/*Lafila0
debeestirarse,leponemosun1.0.Yalo
hicimosenelareadetexto,peroaqu
debemossercoherentesyponerlomismo.*/
this.getContentPane().add(boton1,
constraints);
constraints.weighty=0.0;//Restauramos
alvalorpordefecto,paranoafectara

lossiguientescomponentes.
JButtonboton2=newJButton("Boton2");
constraints.gridx=2;//Columna2,no
necesitaestirarse,noponemosweigthx
constraints.gridy=1;//Fila1,necesita
estirarse,hayqueponerweigthy
constraints.gridwidth=1;
constraints.gridheight=1;
constraints.weighty=1.0;//Lafila1
debeestirarse,leponemos1.0
this.getContentPane().add(boton2,
constraints);
constraints.weighty=0.0;//Restauramos
elvalorpordefecto.
JButtonboton3=newJButton("Boton3");
constraints.gridx=0;//Columna0,no
necesitaestirarse,noponemosweigthx
constraints.gridy=2;//Fila2,no
necesitaestirarse,noponemosweigthy
constraints.gridwidth=1;
constraints.gridheight=1;
this.getContentPane().add(boton3,
constraints);
JButtonboton4=newJButton("Boton4");
constraints.gridx=2;//Columna2,no
necesitaestirarse,noponemosweightx
constraints.gridy=2;//Fila2,no
necesitaestirarse,noponemosweigthy
constraints.gridwidth=1;
constraints.gridheight=1;
this.getContentPane().add(boton4,
constraints);
JTextFieldcampoTexto=newJTextField
("Campotexto");
constraints.gridx=1;//Columna1,debe
estirarse,leponemoselweigthx
constraints.gridy=2;//Fila2,no

necesitaestirarse,noponemosweigthy
constraints.gridwidth=1;
constraints.gridheight=1;
constraints.weightx=1.0;//Lacolumna1
debeestirarse,ponemosel1.0enweigthx
this.getContentPane().add(campoTexto,
constraints);
/*Puestoqueeselltimocomponente,no
restauramoselvalorpordefecto.Sims
adelanteaadimosmscomponentes,seguro
quepagamoscaranuestraosada.*/
Bueno, vamos a ejecutar nuestro programa, estirar la ventana y a ver qu sale. Sale lo de la
siguiente figura, que tampoco es lo que queremos.

Pincha la figura para ver el applet que produce esta ventana y sus cdigo fuente.
Qu es lo que ha pasado ahora?. Como dice un viejo dicho de informtica, el ordenador se
empea en hacer lo que le decimos y no lo que queremos. Le hemos dicho que estire las filas
y columnas y es lo que ha hecho, pero como no le hemos dicho nada sobre los componentes,
no los ha estirado en absoluto.

Estirar los componentes


Si pintamos sobre la ventana las rayas que delimtan filas y columnas, vemos que
efectivamente se han ensanchado las que hemos dicho

pero los componentes siguen con su tamao original y en el centro de las celdas que tienen
asignadas. El area de texto sigue igual, en el centro de sus cuatro celdas, los botones 1 y 2 se
han centrado en sus celdas y lo mismo le pasa al campo de texto.
Lo siguiente que tenemos que hacer es decir qu componentes deben estirarse (el area de
texto y el campo de texto para nuestro ejemplo). Para aquellos componentes que no deben
estirarse, podemos indicar en qu parte de la celda queremos que se situen (caso del boton 1
y boton 2).
Para hacer que un componente se estire, tenemos el atributo fill del GridBagConstraints. Este
puede tomar los siguientes valores:

GridBagConstraints.NONE para que no se estire en


ningn sentido, es la opcin por defecto.

GridBagConstraints.VERTICAL para que se estire


slo en vertical

GridBagConstraints.HORIZONTAL para que se


estire slo en horizontal.

GridBagConstraints.BOTH para que se estire en


ambas dimensiones

Si el componente no se estira en alguna direccin, podemos decirle por medio


de anchor en GridBagConstraints qu posicin queremos que ocupe. Las posibilidades son

GridBagConstraints.CENTER para que el


componente ocupe el centro de la celda. Es la opcin
por defecto

GridBagConstraints.NORTH para que se pegue a la


parte superior, centrado en la misma.

GridBagConstraints.NORTHEAST para que se


pegue a la esquina superior derecha.

... (qu pereza me da escribir todos los puntos


cardinales ...)

GridBagConstraints.WEST para que se pegue al


lado izquierdo, centrado en ese lado.

GridBagConstraints.NORTHWEST para que se


pegue a la esquina superior izquierda.

Igual que antes, estamos usando una nica instancia de GridBagConstraints, por lo que si al
aadir un componente cambiamos una opcin, debemos tenerlo en cuenta para el siguiente.
Bueno, pues bsicamente nos queda decirle al area de texto de se ensanche en todos los
sentidos, al campo de texto que se ensanche en horizontal y a los botones 1 y 2 que ocupen
la posicion NORTH de su celda. El cdigo sera el siguiente:
JTextAreacajaTexto=newJTextArea("Area
texto");
constraints.gridx=0;
constraints.gridy=0;
constraints.gridwidth=2;
constraints.gridheight=2;
//Elareadetextodebeestirarseen
ambossentidos.Ponemoselcampofill.
constraints.fill=
GridBagConstraints.BOTH;
constraints.weighty=1.0;
this.getContentPane().add(cajaTexto,
constraints);
constraints.weighty=0.0;
JButtonboton1=newJButton("Boton1");

constraints.gridx=2;
constraints.gridy=0;
constraints.gridwidth=1;
constraints.gridheight=1;
constraints.weighty=1.0;
//Elbotn1debeocuparlaposicin
NORTHdesucelda
constraints.anchor=
GridBagConstraints.NORTH;
//Elbotn1nodebeestirarse.Habamos
cambiadoestevalorenel
//areadetexto,asiquelorestauramos.
constraints.fill=
GridBagConstraints.NONE;
this.getContentPane().add(boton1,
constraints);
//Restauramosvalorespordefecto
constraints.anchor=
GridBagConstraints.CENTER;
constraints.weighty=0.0;
JButtonboton2=newJButton("Boton2");
constraints.gridx=2;
constraints.gridy=1;
constraints.gridwidth=1;
constraints.gridheight=1;
constraints.weighty=1.0;
//Elboton2debeocuparlaposicin
NORTHdesucelda.
constraints.anchor=
GridBagConstraints.NORTH;
this.getContentPane().add(boton2,
constraints);
//Restauramosvalorespordefecto.
constraints.weighty=0.0;
constraints.anchor=
GridBagConstraints.CENTER;
JButtonboton3=newJButton("Boton3");
constraints.gridx=0;
constraints.gridy=2;

constraints.gridwidth=1;
constraints.gridheight=1;
this.getContentPane().add(boton3,
constraints);
JButtonboton4=newJButton("Boton4");
constraints.gridx=2;
constraints.gridy=2;
constraints.gridwidth=1;
constraints.gridheight=1;
this.getContentPane().add(boton4,
constraints);
JTextFieldcampoTexto=newJTextField
("Campotexto");
constraints.gridx=1;
constraints.gridy=2;
constraints.gridwidth=1;
constraints.gridheight=1;
constraints.weightx=1.0;
//Elcampodetextodebeestirarseslo
enhorizontal.
constraints.fill=
GridBagConstraints.HORIZONTAL;
this.getContentPane().add(campoTexto,
constraints);
Bueno, ejecutamos esto, estiramos la ventana, y Eureka!. Sale lo que queramos al principio.
(No repito la figura, sube un poco y chale un ojo si no la recuerdas).

Algunos comentarios finales


Con esto ya deberamos ser capaces de situar los componentes en nuestra ventana en la
mayora de las ocasiones. El GridBagConstraints nos permite ms cosas, de las que sealo
aqu un par de ellas, por si alguien quiere indagar un poco ms.
Los camos weightx y weighty, como hemos visto, hace que se estiren las filas y columnas.
Hemos puesto 0.0 para las que no se estiran y 1.0 para las que s. En realidad cada fila o
columna se estira en proporcin al valor de este campo respecto a los dems. Por ejemplo, si
a la columna 1 le ponemos weightx=1.0 y a la 2 le ponemos weightx=0.5, ambas se
estiraran , pero la primera el doble que la segunda.

Hay campos insets, ipadx e ipady que permiten fijar mrgenes entre los componentes, de
forma que no queden pegados entre s.
Puedes ver los fuentes y applets funcionando con las tres ventanas que hemos conseguido
pinchando en las imgenes que hemos ido viendo.

Estadsticas y comentarios
Numero de visitas desde el 4 Feb 2007:

Esta pagina este mes: 1330

Total de esta pagina: 139534

Total del sitio: 15765786

Vous aimerez peut-être aussi