Java para programadores (6.1): Componentes y diseño

LA CLASE PRINCIPAL DE AWT se llama Component. Las subclases de Component representan los elementos gráficos de la interface del usuario (excepto los menús que, inexplicablemente, descienden de otra clase MenuComponent). Component es una clase abstracta, esto es, que solo se pueden crear objetos pertenecientes a sus subclases y no al ella misma. Las subclases que representan los elementos comunes GUI son: Button, Checkbox, Choice, Label, List, Scrollbar, TextArea, y TextField.

Los objetos de estas clases tienen comportamientos predefinidos. En la mayor parte de ocasiones, todo lo que tiene que hacer es añadirlos a su programa y ellos se encargan de todo. Cuando el usuario interactua con uno de estos componentes y se requiere alguna acción, los componentes generan eventos que el programa puede detectar y reaccionar convenientemente. Hay también una subclase Canvas que representa un área rectangular que puede ser usada para presentar imágenes.

Estos componentes predefinidos se explican en el siguiente articulo, y los eventos que generan están desarrollados en el posterior. En esta, quiero concentrarme en lo que significa «añadir componentes a su programa». Por esto, necesita entender la clase Container y sus subclases.

Un contenedor (container), en este contexto, es un componente que puede contener otros componentes. Observe que Container es una subclase de Component. La clase Container igual que la Component son clases abstractas. Container directamente tiene dos subclases, Window y Panel. Window representa una ventana independiente del nivel superior, y que no esta contenida en ningún otro componente, lo que no significa que se pueda usar directamente. Tiene dos subclases: Frame que representa la ventana normal que puede tener sus propias barras de menús, y Dialog que representa las cajas de dialogo que se pueden emplear para interactuar limitadamente con el usuario.

El Panel, por otra parte, es un contenedor que no puede existir de forma independiente. La clase Applet es una subclase de Panel, y como ya hemos visto,  un applet no existe por el mismo, sino que ha de ser displayado por un programa navegador. Todo panel, debe estar contenido dentro de algo: un Window , otro Panel,o en el caso de los Applets, aun pagina de un navegador Web.Curso de java. awt

El hecho de que un panel pueda contener otros paneles significa que puede tener muchos niveles de componentes que a su vez contienen otros componentes, como se representa en la ilustración de la derecha. Esto genera dos preguntas: ¿Como puedo añadir componentes a un contenedor?, ¿Como puedo controlar el tamaño y la posición?.

El tamaño y la posición de los componentes en un contenedor, se controla por el manejador de diseño. Diferentes manejadores implementan distintas formas de organizar los componentes. Existen varios manejadores de diseño predefinidos en AWT: FlowLayout, GridLayout, BorderLayout, CardLayout y GridBagLayout.   También se puede definir su propio manejador de fondos, si ninguno de los suministrados le gusta. Por defecto, cada contenedor tiene su propio manejador. Para los Panels, incluyendo Applets, el manejador por defecto pertenece a la clase FlowLayout. Para Window el manejador de diseño por defecto es BorderLayout. Puede cambiar el manejador de diseño de cualquier contenedor utilizando el método setLayout(LayoutManager).( Es posible establecer a nulo el LayoutManager de un contenedor. Esto le permite tener un completo control sobre la situación de los componentes en el contenedor. Sin embargo, aquí no estudiaremos esta posibilidad).

En cuanto al tema de añadir componentes a un contenedor, es algo muy fácil. Puede usar uno  de los métodos add() del contenedor. Hay dos métodos add(), con firmas add(Component) y add(String,Component). (La segunda forma solo se puede usar con BorderLayout y CardLayout, y la comentaremos mas adelante). Por ejemplo, si quiere crear un Panel nuevo y añadirle tres Buttons nuevos, deberá decir:

          Panel panel = new Panel();
          panel.add(new Button("Button 1");
          panel.add(new Button("Button 2");
          panel.add(new Button("Button 3");

Empleando el manejador por defecto FlowLayout que alineara los botones en la parte de arriba de derecha a izquierda.

A menudo tengo muchas dificultades para conseguir en mis applets y ventanas el diseño que quiero.A continuación le comento brevemente como funciona cada manejador, pero usarlos correctamente requiere practica y experimentación.


BorderLayoutCurso de Java. BorderLayout

Este manejador coloca un componente en el centro del contenedor. El componente central es rodeado por hasta cuatro componentes situados en los bordes «Norte», «Sur», «Este», y «Oeste» como se indica en el diagrama de la derecha. Cada uno de los cuatro componentes del borde es opcional. El LayoutManager reserva primero espacio para los componentes del borde. Todo el espacio restante es para el componente central.

Si un contenedor emplea BorderLayout, los componentes deben ser añadidos al contenedor empleando el método add(string,Component). El primer parámetro especifica donde se va a colocar el componente. Deberá ser una de las siguientes cadenas:»Center», «North», «South», «East», o «West». (Estos nombres son sensibles a las mayúsculas/minúsculas por lo que si emplea por ejemplo «east» en lugar de «East», puede encontrarse con la misteriosa desaparición de un componente. Por ejemplo, el siguiente código crea un panel en el que el componente central es drawArea y con barras de desplazamiento a la derecha y abajo::

       Panel panel = new Panel();
       panel.setLayout(new BorderLayout());
               // para usar BorderLayoutcon Panel, deberá
               //   cambiar el manejador por defecto
       panel.add("Center", drawArea);
               // suponemos que drawArea ya existe
       panel.add("South", hScroll);
               // suponemos que hScroll es un componente que
               //     ya existe y que es la barra horizontal
       panel.add("East", vScroll);
               // suponemos que vScroll es el componente de 
               //    la barra vertical y que ya existe

Algunas veces quiere dejar espacio entre los componentes del contenedor. Puede especificar huecos horizontales y verticales en el constructor del objeto BorderLayout. Por ejemplo si dice:

panel.setLayout(new BorderLayout(5,7));

hace que el manejador inserte un espacio horizontal de 5 pixeles y uno vertical de 7 pixeles entre cada componente. (Los huecos horizontal se insertan entre el centro y los componentes «East» y «West», mientras que los verticales se sitúan entre el centro y los componentes «North» y «South»)


GridLayoutCurso de Java GridLayout

El GridLayout sitúa los componentes en una rejilla de rectángulos del mismo tamaño. La imagen presenta como se organizan los componentes en una rejilla de tres filas por 2 columnas. Los componentes se añaden a la rejilla según el orden indicado, esto es primero se llenan las filas de izquierda a derecha y luego se pasa a la nueva fila. Cuando emplea GridLayout, debe asegurarse de ir añadiendo los componentes exactos para llenar la rejilla. Son muy comunes las rejillas con una sola fila horizontal o vertical.

El constructor para GridLayoutcon R filas y C columnas tiene la forma de GridLayout(R,C), Si quiere dejar huecos horizontales de H pixeles entre las columnas y verticales de V pixeles entre las filas, puede emplear GridLayout(R,C,H,V)


FlowLayout

El FlowLayout va situando los componentes en una línea sin preocuparse demasiado. Cuando la línea tiene algunos ítems,  encaja el conjunto en una fila del contenedor, y empieza otra. Al menos esto es lo que dice la documentación. Sin embargo a menudo se empiezan a añadir los componentes al container antes de conocer el tamaño que tendrá, y en este caso, puede que coloque todos los componentes en una línea, incluso cuando alguno de ellos quede fuera del contenedor y por lo tanto invisible. Es por esto que normalmente considero inaceptable este manejador, aunque sea el por defecto para Panel.

Sin embargo, FlowLayout es útil al menos en una circunstancia. El botón que se debe expandir para llenar todo el espacio disponible. Si su «paquete» esta dentro de un Panel que emplea FlowLayout, no obstante querrá mantener , como es natural, un tamaño por defecto. Por ejemplo considere:

         Panel mainPanel = new Panel();
         mainPanel.setLayout(new BorderLayout());
         mainPanel.add("Center", myCanvas);
                // asumimos que myCanvas ya existe
         Panel bttnPanel = new Panel();
               // usa FlowLayout para bttnPanel
         bttnPanel.add(new Button("Clear");
         mainPanel.add("South", bttnPanel);

Esto hara que aparezca el botón Clear centrado debajo del área Canvas. Por otra parte,  si hubiéramos añadido el botón directamente al mainPanel, se hubiera expandido para llenar completamente ese panel. Esto también funciona bien con varios botones. Puede añadir todos los botones al panel, y emplear el panel como un componente «North» o «South» de BorderLayout. Los botones se van alineando en la parte superior de la pantalla expandiéndose desde el centro del componente para ocupar todo el espacio disponible. (Si quiere que los botones se sitúen en el «East» o en el «West», le sugiero que utilice GridLayoutcon una columna llena de botones.


GridBagLayout

GridBagLayout es semejante a GridLayout en que el contenedor esta dividido en filas y columnas de rectángulos. Sin embargo GridBagLayout es mucho mas sofisticado porque no todas las filas han de tener la misma altura, así como las columnas tampoco han de tener todas la misma anchura, y los componentes pueden ocupar varias filas y varias columnas. Hay una clase independiente, GridBagConstraints, que se emplea para indicar la posición del componente y el numero de filas y columnas que ocupa.

El empleo de GridBagLayout es bastante complejo y no lo vamos a estudiar aquí; si esta interesado, deberá consultar el manual de referencia Java


CardLayout

La diferencia principal de este manejador, es que el contenedor que lo usa, solo mantiene visible un componente en un momento determinado. Piense en los componentes como en un conjunto de cartas.En cada momento, solo se ve una carta, pero puede saltar de una carta a otra. CardLayoutproporciona métodos para saltar desde la primera carta a la ultima, y a la siguiente carta del paquete. Se puede especificar un nombre para cada carta que se añada al contenedor y hay métodos para saltar directamente a la carta con un nombre determinado.(Por alguna razón, a cada uno de esos métodos se les ha de pasar el objeto contenedor como parámetro).

Supongamos, por ejemplo, que quiere crear un Panel que muestre uno de los tres paneles: Panel1, Panel2, y Panel3. Supongamos que los tres ya están creados:

         cardPanel = new Panel();
              // suponemos que cardPanel se declara como instancia
              // variable dado que se va a utilizar en otros métodos
         cards = new CardLayout();
              // suponemos que cards se declara como instancia variable
              // dado que se va a usar en otros métodos
         cardPanel.setLayout(cards);
         cardPanel.add("First", panel1);
              // añade panel1 con el nombre "First"
         cardPanel.add("Second", panel2);
              // añade panel2 con el nombre "Second"
         cardPanel.add("Third", panel3);
              // añade panel3 con el nombre "Third"

Entonces puede mostrar el Panel1diciendo

         cards.show(cardPanel, "First");

o

         cards.first(cardPanel);

Otros métodos que están disponibles son cards.last(cardPanel) y cards.next(cardPanel). Observe que para poder emplear CardLayout de forma efectiva,  debe guardar el manejador y el contenedor como instancias de variables, ya que se va a referir a ellas en mas de un método de su clase.


Components en Applets y Frames

Cuando esta escribiendo un Applet o un programa que utilice Frame debe recordar que los Applets y las Frames son en si contenedores. Esto significa que tienen el método add()y que puede usarse para añadir componentes, y el método setLayout() que puede usarse para modificar el manejador por defecto.

En general, el diseño completo del applet debe establecerse en el método init(). Esto a menudo significa construir subpaneles y añadirlos al applet. Si escribe una subclase de Frame, deberá establecer el manejador de diseño en el constructor de la clase. Si hace directamente un objeto del tipo Frame, en vez de hacer una subclase, antes de hacerla visible, deberá montarla. (Un Frame es invisible por defecto, deberá hacerla visible llamando al método show())

Como punto final, debe tener en cuenta que con muchos manejadores de diseño puede especificar huecos entre componentes. Pero que pasa si quiere huecos entre los bordes de un applet o de un marco (frame) y los componentes?. Para ello, deberá sobregrabar el método insets() del applet o del marco. Normalmente este método es:

        public Insets insets() {
           return new Insets(top,left,bottom,right);
        }

donde top, left, bottom, y right indican el numero de pixeles tienen que insertarse como hueco antes de cada borde. Cada contenedor tiene un método insets(), y  se puede sobregrabar desde cualquier subclase que defina de contenedores como Applet o Frame.

Acerca de Miguel Garcia

Programador, Desarrollador web, Formador en distintas areas de informatica y director de equipos multidisciplinares.
Esta entrada fue publicada en Formacion, Java y etiquetada , , , . Guarda el enlace permanente.

3 respuestas a Java para programadores (6.1): Componentes y diseño

  1. melania6149 dijo:

    Hey there! Brief issue that’s entirely from subject.
    Are you aware learning to make a site cellular friendly? My internet site seems to be odd when exploring from my telephone.
    I’m looking for a style or wordpress plugin that could possibly clear up this concern. Please share if you have any suggestions.
    Many thanks.

    • Miguel dijo:

      No creo que tenga mucho que ver con este articulo, sin embargo le invito a que pruebe por ejemplo, este mismo tema que utilizo que funciona bastante bien en moviles

  2. Pingback: Java - Un resumen organizado....o no.Recursos para formacion

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.