El Kit Gráfico: AWT

AWT permite hacer interfaces gráficas mediante artefactos de interacción con el usuario, como botones, menús, texto, botones para selección, barras de deslizamiento, ventanas de diálogo, selectores de archivos, etc. Y por supuesto despliegue gráfico general. La siguiente figura muestra algunos de estos artefactos de interacción:

Estos artefactos de interacción se denominan widgets. En la ventana los artefactos se organizan en una jerarquía de componentes gráficas:

Es el programador de la interfaz gráfica el que diseña esta jerarquía de componentes.


Jerarquía de clases de AWT

Cada una de las componentes de una ventana en AWT se representa mediante uno o más objetos de la aplicación. Estos objetos pertenecen a las clases que se observan en la siguiente jerarquía de clases para AWT:

La clase de los contenedores sirve para crear áreas en la ventana cuyo único fin es colocar otras componentes en su interior. Hay dos tipos de contenedores:


Construcción de una jerarquía de artefactos de interacción

Un artefacto de interacción se construye creando el objeto correspondiente de la jerarquía de clases. Por ejemplo el botón de la ventana de la figura se creó con:
Button boton= new Button("Button")
El argumento que recibe el constructor es la etiqueta que se colocará sobre el botón. El aspecto y comportamiento de este botón es dependiente de la plataforma. La aplicación se basa sólo en que será informada cuando el botón sea presionado por el usuario para ejecutar alguna acción.

Los otros artefactos se crearon con:


Artefactos complejos

Los artefactos que hemos visto hasta el momento son simples porque la plataforma sabe como dibujarlos y qué tamaño deben ocupar. Es decir la aplicación no necesita especificar tamaño ni forma.

El canvas es un artefacto complicado porque AWT no conoce en absoluto el aspecto que debe tener en la ventana. Por lo tanto es la aplicación la que se debe preocupar de especificar qué tamaño debe tener y cómo se dibuja. Lo anterior se logra creando una nueva clase derivada a partir de Canvas. En ella se redefinen algunos métodos que realizan las funciones que un canvas normal no sabe hacer:

class MyCanvas extends Canvas
{
    public void paint(Graphics g) {
        int w = size().width;
        int h = size().height;
        g.drawLine(10,10, 100,100);
    }

    public Dimension minimumSize() {
        return new Dimension(150,130);
    }

    public Dimension preferredSize() {
        return minimumSize();
    }
}
El principio es que todas las componentes tienen un método paint que AWT invoca cada vez que la componente se descubre y por lo tanto hay que redibujarla. La mayoría de las componentes (como botones, listas, etc.) saben dibujarse porque en la clase respectiva se redefinió el método paint con el código apropiado para mostrar su aspecto.

Sin embargo el aspecto de un canvas es absolutamente dependiente de la aplicación. Por lo tanto es la aplicación la que redefine paint con sus propias instrucciones para dibujar el artefacto. Si este método no se redefine, el canvas no será dibujado cuando la ventana sea descubierta. El método paint recibe un argumento g que acepta primitivas gráficas como drawLine.

Del mismo modo, AWT invoca los métodos minimunSize y preferredSize para conocer el tamaño mínimo y preferido de una componente. Botones, listas, barras de deslizamiento, etc. han redefinido estos métodos.

Entonces en el nuevo canvas también se redefinen estos métodos para indicar el tamaño apropiado. Si estos no se redefinen el canvas podría quedar reducido a un tamaño 0. El nuevos canvas puede determinar su tamaño real en la ventana consultando su propio método size.


Organizando los artefactos en un contenedor

Los contenedores usan organizadores (layout manager) para distribuir los artefactos en la superficie de despliegue de la mejor forma. Cada tipo de contenedor tiene su propio organizador. Por ejemplo los paneles usan FlowLayout que coloca los artefactos de izquierda a derecha.

Para el contenedor de la raiz (Gui) definimos explícitamente un organizador por medio de:

public class Gui extends Frame {
  Gui() {
    setLayout(new BorderLayout());
    ...
  }
Observe que como no se especifica objeto en la invocación, el método se aplica al objeto principal, que en este caso es la raíz (un frame).

Para crear el panel y colocar en su interior los artefactos se usa:

// Crear panel
Panel bottomPanel = new Panel();

// Crear artefactos
texto= new TextField("TextField");
boton= new Button("Button");
check= new Checkbox("Checkbox");

// Agregarlos al panel
bottomPanel.add(texto);
bottomPanel.add(boton);
bottomPanel.add(check);
Para colocar los artefactos en el frame (es decir en un objeto de la clase Gui) se usa el método add, pero con un argumento adicional que dice si cada artefacto se agrega a la izquierda, arriba, etc. Esto es específico del organizador BorderLayout.
// Define el organizador
setLayout(new BorderLayout());

// Crear artefactos
...

// Agregar artefactos
add("Center", canvas);
add("North", etiqueta);
add("West", areaTexto);
add("East", lista);

// Agregar el panel
add("South", bottomPanel);
Cuando se invoca pack en el frame se invoca el organizador que asigna un rectángulo a cada artefacto. A estas alturas todavía no se muestra en la pantalla la ventana. Para realizar esto se invoca el método show del frame.