Está en la página 1de 32

6-. Interfaces de Usuario.

Captulo 6: Interfaces
Interfaces de
Usuario.

- 77 -
6-. Interfaces de Usuario.

6. Interfaces de Usuario.
En el proceso de interaccin persona-ordenador, la Interfaz Grfica de Usuario
(GUI), es el artefacto que permite la interaccin amigable con el sistema informtico.
La interfaz grfica de usuario (en ingls Graphical User Interface, GUI) es un tipo de
interfaz de usuario que utiliza un conjunto de imgenes y objetos grficos (iconos,
ventanas, tipografa) para representar la informacin y acciones disponibles en la
interfaz. En este captulo comentaremos las diferentes herramientas que se pueden
utilizar para realizar interfaces de usuario; comenzaremos por describir el paquete
AWT (Abstract Window Toolkit) de java; a continuacin describiremos con mucho
detalle el paquete Java Swing, que es el que ha sido utilizado finalmente para
implementar la interfaz. Por ltimo hablaremos de SWT, otra tecnologa alternativa
para la realizacin de interfaces grficas que est adquiriendo cada vez ms
importancia.

6.1-. Paquete Java.awt.

El AWT o Abstract Window Toolkit es un conjunto de herramientas que permite


el desarrollo de aplicaciones grficas basadas en ventanas. El AWT contiene numerosas
clases y mtodos que permiten crear y gestionar dichas ventanas. Aunque el propsito
principal del AWT es suministrar a las applets el soporte necesario para que trabajen
con ventanas, tambin se puede utilizar para crear ventanas independientes que se
ejecuten en un entorno grfico independiente, como puede ser Windows 95/98/NT. Una
descripcin completa del AWT podra fcilmente ocupar un libro entero, es por eso que
aqu slo se darn unas nociones bsicas que permitan entender su funcionamiento,
limitaciones, y el por qu de la eleccin de Swing para el desarrollo de este proyecto.
Esta descripicin pretende tambin realizar una pequea introduccin a las libreras de
creacin de interfaces grficas.
Java.awt es el paquete que maneja ventanas e interfaces grficas, independientes
(abstractas) del entorno operativo. Es un paquete muy importante, y est disponible en
todas las plataformas Java.
Antes de seguir, es necesario aclarar a qu nos referimos con GUI. Si estamos
utilizando un programa, es muy probable que en la parte superior exista un men.
Tpicamente tendremos los elementos Archivo, Ver, Ayuda, etc. Aparte de esto,
es muy probable que el programa disponga tambin de una serie de iconos. Por ejemplo,
una carpeta para abrir un documento, un disquette para guardar un documento, una
impresora que pulsaremos si queremos imprimir, etc. Todo esto constituye la interfaz
grfica de usuario o GUI. Este es el fin del paquete java.awt: dar el soporte necesario
para crear un GUI. Es un paquete que permite por ejemplo definir botones y cajas de
texto. Es ms, dado que es un paquete Java, mantiene como es lgico la caracterstica
principal de este lenguaje de programacin: la portabilidad. Definiremos pues botones o
etiquetas portables a Windows, OS/2, Xwindows, o cualquier otro entorno grfico,
siempre usando el mismo cdigo fuente, evidentemente.
Java AWT (Abstract Windows Toolkit) es la librera visual ms antigua de java,
pero hoy en da es mucho ms utilizada la librera Swing. El AWT define ventanas en

- 79 -
6-. Interfaces de Usuario.

funcin de una jerarqua de clases que aade funcionalidad y carcter especfico con
cada nivel. Las dos ventanas ms comunes son las que derivan de panel (utilizadas por
las applets) y las que derivan de Frame (marco), que permiten crear ventanas estndar.
La mayor parte de la funcionalidad de estas ventanas la heredan de sus superclases. Para
poder entender esto es fundamental describir una jerarqua de clases que relacione
ambas clases. De forma grfica, esta jerarqua podra representarse como sigue:

Component

Container

Menu Container
Interface Window Panel

Frame

Ilustracin 3: Jerarqua de clases para Panel y Frame.

En la parte superior de la jerarqua de clases del AWT se encuentra la clase


Component. Es una clase abstracta que encapsula todos los atributos de un componente
visual. Todos los elementos del GUI que se visualizan en pantalla e interactan con el
usuario son subclases de Component. A continuacin viene la clase Container, que es
una subclase abstracta de Component y que contiene una serie de mtodos adicionales
que permiten que otros objetos Component aniden dentro de l. Tambin se pueden
anidar objetos Container dentro de otros objetos Container, puesto que tambin son
instancias de Component. Esto hace que sea un sistema de contenidos completamente
jerrquico.
La clase Panel es una subclase concreta de Container que no aade ningn
mtodo. Es la superclase de Applet. Bsicamente, un objeto Panel es una ventana que
no contiene barra de ttulo, ni barra de men, ni bordes. Esta es la razn por la que no se
pueden ver estos elementos cuando una applet se ejecuta en un navegador. Cuando se
visualiza con el visualizador de applets, es el visualizador el que proporciona el ttulo y
el borde.
La clase Window crea una ventana de nivel superior que no est contenida en
ningn otro objeto y se encuentra directamente sobre el escritorio. En general, no se
pueden crear objetos de la clase Window directamente. En su lugar se crean objetos
Frame. La clase Frame (marco) es una subclase de Window y tiene una barra de ttulo,
una barra de men, bordes y esquinas para cambiar el tamao.
Por ltimo, y aunque no aparezca en la jerarqua de clases mostrada anteriormente,
hay que hablar de la clase Canvas. Esta clase encapsula una ventana vaca sobre la que
se puede dibujar. Es, digamos, una superficie de dibujo.

- 80 -
6-. Interfaces de Usuario.

Aparte de estas clases de alto nivel, existen otras clases que permiten al usuario
interactuar con la aplicacin de muy diversas formas. Se denominan controles y el
AWT permite los siguientes tipos de controles:
- Etiquetas.
- Botones.
- Cuadros de comprobacin.
- Mens de opciones.
- Listas.
- Barras de desplazamiento.
- Edicin de texto.

Estos controles son de tambin subclases de Component. Excepto las etiquetas,


que son controles pasivos, el resto de controles generan eventos cuando el usuario acta
sobre ellos. Por ejemplo, si el usuario pulsa un botn, se genera un evento que identifica
el botn pulsado. Estos eventos hay que gestionarlos. El modelo de gestin de eventos
del AWT es el mismo que utiliza Swing y ser explicado un poco ms tarde.
No vamos a explicar mucho ms sobre el AWT ya que el proyecto ha sido
desarrollado utilizando el paquete Swing. Sin embargo, es bueno realizar esta pequea
introduccin al AWT para ir entrando en materia e ir comprendiendo un poco qu nos
vamos a encontrar en el paquete Swing.

6.2-. Paquete Javax.swing.


6.2.1-. Origen.

Para comenzar a hablar de Swing, vamos a ver su origen, y para ello nombraremos
el JFC. JFC es la abreviatura de Java Foundation Classes, que comprende un grupo de
caractersticas para ayudar a construir interfaces grficas de usuario (GUIs). El JFC
incluye una serie de caractersticas, como pueden ser:
- Los componentes Swing: hablaremos a continuacin de ellos. Para comenzar,
diremos que incluye prcticamente todo lo que haba en el AWT y ms. Por
ejemplo, tenemos desde botones hasta SplitPanes (que dividen la pantalla en
zonas) o tablas.
- Soporte de Aspecto y Comportamiento Conectable: Le ofrece a cualquier
componente Swing una amplia seleccin de aspectos y comportamientos (look and
feel). Por ejemplo, el mismo programa puede usar el Aspecto y Comportamiento
Java o el Aspecto y Comportamiento Windows.
- API de Accesibilidad: Permite tecnologas asistivas como lectores de pantalla o
displays Braille para obtener informacin desde el interfaz de usuario.

Estas tres primeras caractersticas del JFC fueron implementadas sin ningn
cdigo nativo, es decir, utilizando nicamente la API definido en el JDK 1.1. Cmo
resultado, se convirtieron en una extensin del JDK 1.1. Esta versin fue liberada como
JFC 1.1, que algunas veces es llamada 'Versin Swing'. La API del JFC 1.1 es conocido
como la API Swing. Una curiosidad sobre el nombre: "Swing" era el nombre clave del
proyecto que desarroll los nuevos componentes. Aunque no es un nombre oficial,
frecuentemente se usa para referirse a los nuevos componentes y al API relacionado.

- 81 -
6-. Interfaces de Usuario.

Est inmortalizado en los nombres de paquete de la API Swing, que empiezan con
"javax.swing". En el JDK 1.2 se incluyeron otras caractersticas, como el Java 2D API
que permite a los desarrolladores incorporar fcilmente grficos 2D de alta calidad,
texto e imgenes, o por ejemplo el soporte de Drag and Drop para arrastrar y soltar
entre aplicaciones Java y aplicaciones nativas.
Dada la importancia de Swing, hoy en da no se plantea el tener un JDK sin las
capacidades que proporciona este paquete.

6.2.2-. API Swing.

Swing consta de 16 paquetes, cada uno de los cuales tiene un propsito concreto
que detallamos brevemente a continuacin:

- javax.swing: Es el paquete de ms alto nivel, que contiene los componentes,


adaptadores, los modelos por defecto de los componentes, y las interfaces para
todos los modelos.

- javax.swing.border: Clases e interfaces que se usan para definir estilos de bordes


especficos. Observe que los bordes pueden ser compartidos por cualquier nmero
de componentes Swing, ya que no son componentes por s mismos.

- javax.swing.colorchooser: Contiene clases de soporte para el componente


seleccionador de color.

- javax.swing.event: Contiene los tipos de eventos y listeners (oyentes) especficos


de Swing. Adems, los componentes Swing pueden generar sus propios eventos.

- javax.swing.filechooser: Contiene clase de soportes para el componente


seleccionador de ficheros.

- javax.swing.plaf: (PLAF = pluggable look-and-feel) contiene las clases de


Interfaz de Usuario que implementan los diferentes look-and-feel para los
componentes. stas estn orientadas a desarrolladores que, por una razn u otra,
no pueden usar uno de los look-and-feel existentes.

- javax.swing.plaf.basic: Consiste en la implementacin del Basic look-and-feel,


encima del cual se construyen los look-and- feels que provee Swing. Normalmente
deberemos usar las clases de este paquete si queremos crear nuestro look-and-feel
personal.

- javax.swing.plaf.metal: Metal es el look-and-feel por defecto de los componentes


Swing. Es el nico look-and-feel que viene con Swing y que no est diseado para
ser consistente con una plataforma especfica.

- javax.swing.plaf.multi: Es el Multiplexing look-and-feel. No se trata de una


implementacin normal de look-and-feel ya que no define ni el aspecto ni el

- 82 -
6-. Interfaces de Usuario.

comportamiento de ningn componente. Ms bien ofrece la capacidad de


combinar varios look-and-feels para usarlos simultneamente.

- javax.swing.table: Contiene las clases e interfaces para soportar el componente


tabla.

- javax.swing.text: Contiene las clases de soporte para la edicin de texto.

- javax.swing.text.html: Contiene las clases de soporte para crear editores de texto


HTML.

- javax.swing.text.html.parser: Soporte para analizar gramaticalmente HTML.

- javax.swing.text.rtf: Contiene soporte para documentos RTF.

- javax.swing.tree: Clases e interfaces que dan soporte al componente tree. Este


componente se usa para mostrar y manejar datos que guardan alguna jerarqua.

- javax.swing.undo: El paquete undo contiene soporte para implementar y manejar


la funcionalidad deshacer/rehacer.

6.2.3-. Diferencias entre Swing y AWT.

Para empezar con diferencias sencillas, nos fijaremos en una diferencia sintctica
que salta a la vista: se pueden identificar los componentes Swing porque sus nombres
empiezan por J. Por ejemplo, la clase del AWT que crea un botn se denomina
Button, y la clase Swing se llama JButton. Los componentes AWT estn en el paquete
java.awt, mientras que los componentes Swing estn en el paquete javax.swing.
Si profundizamos un poco ms, podemos ver otras diferencias importantes. La
mayor diferencia entre los componentes AWT y los componentes Swing es que stos
ltimos estn implementados sin nada de cdigo nativo. Esto significa que los
componentes Swing pueden tener ms funcionalidad que los componentes AWT,
porque no estn restringidos a las caractersticas presentes en cada plataforma. Esto
tambin significa que un botn Swing y un rea de texto se vern y funcionarn
idnticamente en cualquier plataforma (Macintosh, Solaris, Linux, Windows, etc.).
Las capacidades que tienen los componentes Swing son bastante ms importantes
que las que ofrecen los componentes del AWT. Por citar algunos ejemplos:

- Los botones y las etiquetas Swing pueden mostrar imgenes en lugar de o adems
del texto.
- Se pueden aadir o modificar fcilmente los bordes dibujados alrededor de casi
cualquier componente Swing.
- Se puede modificar fcilmente el comportamiento o la apariencia de un
componente Swing llamando a mtodos o creando una subclase que herede del
componente en cuestin.
- Los componentes Swing no tienen por qu ser rectangulares. Por ejemplo, los
botones pueden ser redondos.

- 83 -
6-. Interfaces de Usuario.

Otra caracterstica importante de Swing es que se puede especificar el Aspecto y


Comportamiento (Look & Feel) que utilice el GUI de nuestro programa (Java o Metal /
Motif / Windows) en funcin de nuestras preferencias. Por el contrario, los
componentes AWT siempre tienen el aspecto y comportamiento de la plataforma nativa.
Otro detalle interesante es que los componentes Swing con estado usan modelos
para mantener el estado. Por ejemplo, un JSlider (barra de desplazamiento) usa un
objeto BoundedRangeModel para contener su valor actual y un rango de valores legales.
La gran ventaja que esto ofrece es que los modelos se configuran automticamente, por
eso no tenemos que tratar con ellos, a menos que queramos tomar ventaja de la potencia
que pueden ofrecernos.
Existen una serie de reglas a la hora de utilizar componentes AWT y/o
componentes Swing. Estas reglas son especialmente importantes si se van a utilizar
ambos tipos de componentes simultneamente.

- Como regla general, los programas no deberan usar componentne de peso


pesado junto con componentes Swing. Los componentes de peso pesado incluyen
todos los componentes AWT listos para usar (como Menu y ScrollPane) y todos
los componentes que desciendan de las clases Canvas y Panel del AWT. Esta
restriccin existe porque cuando un componente Swing (u otro componente de
peso ligero) se solapa con componentes de peso pesado, ste ltimo siempre se
dibuja encima.
- Los componentes Swing no son de thread seguro. Si se modifica un componente
Swing visible desde cualquier lugar que no sea el manejador de eventos, hay que
seguir unos pasos especiales para hacer que la modificacin se ejecute en el thread
de despacho de eventos. Esto no es ningn problema para la mayora de los
programas Swing, ya que el cdigo que modifica los componentes normalmente se
encuentra en los manejadores de eventos y estos se ejecutan en el thread de
despacho de eventos. (Veremos estos conceptos de eventos y manejador de
eventos con ms detalle en apartados posteriores.).
- La herencia de contenidos de cualquier ventana o applet que contenga
componentes Swing debe tener un contenedor de alto nivel Swing como raz del
rbol. Por ejemplo, una ventana principal debera ser implementada como un
ejemplar de JFrame en vez de como un ejemplar de Frame.
- No se aaden directamente los componentes a un contenedor de alto nivel como
un JFrame. En su lugar, se aaden los componentes a un contenedor (llamado
panel de contenido) que a su vez est contenido por el JFrame.

6.2.4-. Vista rpida por el cdigo de un programa Swing.

Antes de entrar en ms detalle sobre los elementos del paquete Swing, vamos a
echar un vistazo al cdigo de una aplicacin Swing. En los siguientes apartados se darn
explicaciones completas sobre los tpicos que aqu se introduzcan, sin embargo es
interesante empezar por tener una visn global.
Veamos la ventana de la aplicacin con la que vamos a tratar:

- 84 -
6-. Interfaces de Usuario.

Ilustracin 4: Ejemplo de Aplicacin Swing.

El funcionamiento es bien sencillo: cada vez que el usuario pulsa el botn, la


etiqueta de la ventana se actualiza. Para llegar a este resultado hay que realizar una serie
de acciones. Comentamos a continuacin los detalles ms notorios del cdigo
correspondiente a este ejemplo.

- IMPORTAR PAQUETES SWING:


Los programas Swing necesitan los elementos del paquete principal de Swing que
se importa mediante la lnea:

import javax.swing.*;

Sin embargo, no es este el nico paquete que necesitaremos por norma general. Es
muy comn que los programas Swing tambin necesiten clases de los paquetes
principales del AWT, ya que Swing utiliza el modelo de eventos de este ltimo. Para
poder utilizarlos se aaden las lneas siguientes:

import java.awt.*;
import java.awt.event.*;

- ELEGIR EL ASPECTO Y COMPORTAMIENTO:


Como ya dijimos, el aspecto y comportamiento de nuestro programa es
configurable. Para poder elegir el Look and Feel que deseemos tendremos que tratar con
el conocido como UIManager o delegado UI (UI significa User Interface). Swing
incluye varios conjuntos de delegados UI. Cada conjunto contiene implementaciones de
UI para casi todos los componentes Swing y podemos llamar a estos conjuntos una
implementacin de look-and-feel o pluggable look-andfeel (PLAF).
Hay tres implementaciones de pluggable look-and-feel que descienden de Basic
look-and- feel y son:
- Windows: com.sun.java.swing.plaf.windows.WindowsLookAndFeel.
- CDE\Motif: com.sun.java.swing.plaf.motif.MotifLookAndFeel.
- Metal\Multiplataforma (look and feel por defecto): javax.swing.plaf.metal.
MetalLookAndFeel.

- MacLookAndFeel: Existe tambin este look-and-feel que simula las interfaces de


usuario de Macintosh, pero no viene con Java 2 y hay que descargarlo por
separado.

Otro detalle a tener en cuenta es que las libreras de los Windows y Macintosh
pluggable look-and-feel slo se soportan en la plataforma correspondiente.
Realizar el cambio del look-and-feel de una aplicacin es bien sencillo.
nicamente hay que llamar al mtodo setLookAndFeel() de UIManager, pasndole el

- 85 -
6-. Interfaces de Usuario.

nombre completo del LookAndFeel que vamos a usar. El cdigo que se muestra a
continuacin se puede usar para llevar esto a cabo en tiempo de ejecucin:

try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.motif.MotifLookAndFeel");
SwingUtilities.updateComponentTreeUI(myJFrame);
}catch (Exception e) {
System.err.println("Could not load LookAndFeel");
}

SwingUtilities.updateComponentTreeUI() informa a todos los hijos del


componente especificado que el look-and-feel ha cambiado y que necesitan reemplazar
sus delegados UI por los del tipo especificado.

- CONFIGURAR EL CONTENEDOR DE ALTO NIVEL:


Es fundamental saber que todo programa que presente un GUI Swing contiene al
menos un contenedor de alto nivel. Para la mayora de los programas, los contenedores
de alto nivel Swing son ejemplares de JFrame, JDialog o JApplet en el caso de las
applets. Un contenedor de alto nivel existe principalmente para proporcionar el soporte
que necesitan los componentes Swing para realizar su dibujado y manejo de eventos.
Para ir conociendo un poco los elementos Swing podemos decir que un objeto JFrame
(frame significa marco en Ingls), implementa una ventana principal, mientras que un
objeto JApplet implementa un rea de pantalla de un applet dentro de una ventana del
navegador.
A continuacin podemos ver un ejemplo de cdigo en el que tenemos como
contenedor de alto nivel un JFrame, y en el que se especifica que cuando el usuario
cierre el frame, la aplicacin finalice.

public class SwingApplication {


...
public static void main(String[] args) {
...
JFrame frame = new JFrame("SwingApplication");
//...crear los componentes que irn en el marco...
//...incluirlos en un contenedor llamado contents...
frame.getContentPane().add(contents,BorderLayout.CENTER);

//Poltica de cierre de ventana


frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//Termina de configurar el frame y lo muestra.
frame.pack();
frame.setVisible(true);
}

- 86 -
6-. Interfaces de Usuario.

Como dijimos anteriormente, esto es una ligera introduccin para que nos vayan
sonando los conceptos. Muchos de ellos sern ampliamente desarrollados ms adelante.

- CONFIGURAR LOS BOTONES Y LAS ETIQUETAS:


Dado que esto es un ejemplo sencillo, la aplicacin slo contiene un botn y una
etiqueta. El resto de aplicaciones Swing tienen por norma general bastante ms
elementos, desde SplitPanes hasta CheckBoxes, pasando por TabbedPanes (paneles de
pestaas) y otros componentes. Veremos diversos componentes ms adelante, pero de
momento nos centramos en los del ejemplo. El cdigo que inicializa el botn es el
siguiente:

JButton button = new JButton("I'm a Swing button!");


button.setMnemonic('i');
button.addActionListener(this);

En la primera lnea se crea el botn con el texto Im a Swing button!. A


continuacin se aade un mnemnico al botn. Este mnemnico se utiliza para poder
simular el click del ratn. En el caso del Look & Feel Metal, o en el Windows,
simularamos el click del ratn mediante el tecleo de Alt+i (i para este ejemplo ya que
es la letra elegida como mnemnico en el cdigo). La tercera lnea aade el manejador
de eventos, veremos ms adelante qu son y para qu sirven los eventos.
El cdigo para la etiqueta lo podemos ver a continuacin:

// en el lugar de declaracin de las variables de instancia::


private static String labelPrefix = "Number of button clicks: ";
private int numClicks = 0;

//en el cdigo de inicializacin del GUI:


final JLabel label = new JLabel(labelPrefix + "0 ");

//en el manejador de eventos de las pulsaciones de botn:


label.setText(labelPrefix + numClicks);

Las primeras lneas son fciles de interpretar, y la creacin de la etiqueta es


bastante similar a la del botn. Slo nos quedara aadir al manejador de eventos la
ltima lnea en la que numClicks es una variable contador que ir acumulando el
nmero de clicks que realicemos.

- AADIR COMPONENTES A LOS CONTENEDORES:


Si volvemos a mirar la imagen de la aplicacin de ejemplo, vemos que la etiqueta
y el botn estn dentro de un marco o Frame. Sin embargo, los componentes no se
pueden aadir directamente al frame, sino que hay que aadirlos antes a un contenedor.
En este caso se ha utilizado un JPanel.

JPanel pane = new JPanel();

- 87 -
6-. Interfaces de Usuario.

pane.setBorder(BorderFactory.createEmptyBorder(30, 30, 10, 30));


pane.setLayout(new GridLayout(0, 1));
pane.add(button);
pane.add(label);

Primero creamos el JPane, para a continuacin decir qu tipo de borde y que


controlador de distribucin queremos. El borde simplemente proporciona un espacio en
blanco alrededor del panel. Los nmeros son medidas en pixels.
En la tercera lnea entra en juego el controlador de distribucin. ste fuerza al
contenido del panel a dibujarse en una sola columna en este caso, por haber elegido
GridLayout. Las dos ltimas lneas aaden el botn button y la etiqueta label al panel.
Esto significa que tanto el botn como la etiqueta sern controlados por el controlador
de distribucin que hemos asignado al panel, y ser ste quien determine el tamao y
posicin de cada componente.

- MANEJAR EVENTOS:
En el cdigo que hemos visto hasta ahora hemos encontrado dos manejadores de
eventos. Uno maneja las pulsaciones de botn y otro maneja los eventos de cierre de la
ventana o frame. Desarrollaremos este punto con detalle en captulos posteriores, pero
veamos el cdigo del ejemplo que corresponde al manejo de eventos (en este caso se
definen en clases internas annimas):

//Manejador de eventos para el botn .


button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
numClicks++;
label.setText(labelPrefix + numClicks);
}
});

//Manejador de eventos para el cierre de ventana.


frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});

- TRATAR CON LOS THREADS:


El programa de ejemplo es de thread seguro. Una vez q que su GUI es visible, en
el manejador de eventos slo ocurre manipulacin del GUI (actualizar la etiqueta).
Como el manejador de eventos se ejecuta en el mismo thread que realiza todo el manejo
de eventos y pintado de la aplicacin, no existe la posibilidad de que dos threads
intenten manipular el GUI a la vez. Sin embargo, es fcil introducir problemas de
threads en un programa Swing. Ms adelante veremos algunos apartados sobre los hilos
en Swing.

- 88 -
6-. Interfaces de Usuario.

6.2.5-. Estructura bsica de una aplicacin Swing.

En la aplicacin de ejemplo hemos presentado algn componente Swing. En esta


seccin presentaremos con ms detalles esos componentes as como otros componentes
muy utilizados en Swing.
Los elementos que utilizamos en el ejemplo eran: un frame, o ventana principal
(ejemplar de la clase JFrame), un panel, algunas veces llamado pane (clase JPanel),
un botn (clase JButton) y una etiqueta (clase JLabel). Con este ejemplo vamos a poder
estudiar bien la anatoma general de un programa Swing.
El frame es un contenedor de alto nivel. Como ya explicamos anteriormente,
existe principalmente para proporcionar espacio para que se dibujen otros componentes
Swing. En un programa Swing debe haber siempre un Contenedor de Alto Nivel para
dar soporte al resto de componentes. Los contenedores de alto nivel ms utilizados son:
- javax.swing.JFrame: una ventana independiente.
- javax.swing.JApplet: un applet
- Dilogos: ventanas de interaccin sencilla con el usuario, como por ejemplo:
o javax.swing.JOptionPane: ventana de dilogo tipo SI/NO,
SI/NO/ACEPTAR/CANCELAR, etc.
o javax.swing.JFileChooser: ventana para elegir un archivo.
o javax.swing.JColorChooser: ventana para elegir colores.
El panel es un contenedor intermedio. Los Contenedores Intermedios tienen el
nico cometido de simplificar el posicionamiento de los otros componentes, en nuestro
ejemplo del botn y la etiqueta. JPanel es un contenedor intermedio que no proporciona
ninguna caracterstica especial. Otros contenedores intermedios, como los paneles
desplazables (JScrollPane) y los paneles con pestaas (JTabbedPane), juegan un papel
ms visible e interactivo en el GUI de un programa.
Por ltimo llegamos a los Componentes Atmicos, que seran el botn y la
etiqueta de nuestro ejemplo. Son componentes que existen no para contener otros
componentes Swing como era el caso de los Contenedores Intermedios y de Alto Nivel,
sino como entidades auto-suficientes que representan bits de informacin para el
usuario. Frecuentemente, los componentes atmicos tambin obtienen entrada del
usuario. El API Swing proporciona muchos componentes atmicos, incluyendo combo
boxes (JComboBox), checkBoxes para elegir opciones (JCheckBox), campos de texto
(JTextField), y tablas (JTable).
Veamos un diagrama de rbol que nos muestra la anatoma del programa. Es
importante comentar que si aadimos una ventana -- por ejemplo, un dilogo -- la nueva
ventana tendra su propio rbol de contenidos, independiente del mostrado en esta
figura.

JFrame (contenedor de alto nivel)


|
(Panel de contenido)
|
JPanel (contenedor intermedio)
|
+----------------+
| |
JButton JLabel

- 89 -
6-. Interfaces de Usuario.

Incluso el programa Swing ms sencillo tiene mltiples niveles en su rbol de


contenidos. La raz del rbol de contenidos es siempre un contenedor de alto nivel que
proporciona espacio para que los componentes Swing descendentes se dibujen. Todo
contenedor de alto nivel contiene un contenedor intermedio conocido como panel de
contenido. Cmo regla general, el panel de contenido contiene todos los componentes
visibles en el GUI de la ventana. Sin embargo, existe una gran excepcin a esta regla y
es la siguiente: si el contenedor de alto nivel tiene una barra de men (JMenuBar),
entonces sta se sita en un lugar especial fuera del panel de contenido.
Como curiosidad comentar que se puede ver el rbol de contenidos de cualquier
frame o dilogo, pulsando el borde para seleccionarlo y pulsando a continuacin
Control-Shift-F1. Se escribir una lista con el rbol de contenidos en el flujo de salida
estndar.
Hemos dicho que unos componentes contienen a otros pero, cmo se aaden los
componentes a un contenedor? Pues es algo tan sencillo como utilizar el mtodo add
(aadir en ingls) en sus distintas formas. Este mtodo tendr siempre como argumento
al menos el componente aadir, aunque dependiendo del mtodo add que utilicemos
podemos encontrar otros argumentos adicionales que especifiquen por ejemplo, el lugar
de colocacin del elemento a aadir. Concluyamos esta explicacin con cdigo:

frame = new JFrame(...);


pane = new JPanel();
button = new JButton(...);
label = new JLabel(...);
pane.add(button);
pane.add(label);
frame.getContentPane().add(pane, BorderLayout.CENTER);

Con el cdigo anterior creamos el contenedor de alto nivel (frame), el intermedio


(pane) y los elementos (button y label). Aadimos al panel el botn y la etiqueta
mediante pane.add(), y a continuacin lo aadimos al contendor de alto nivel el panel.
Ms concretamente, la ltima lnea especifica que el panel debera estar en el centro
(CENTER) de su contenedor (el panel de contenido).

6.2.6-. Control de Distribucin.

Las ilustracin 5 muestra los GUIs de cinco programas, cada uno de ellos con
cinco botones. Los botones son idnticos, y el cdigo de los programas es tambin
prcticamente idntico. Entonces, por qu parecen tan diferentes? Simplemente porque
usan diferentes controladores de distribucin para controlar el tamao y posicin de los
botones.

- 90 -
6-. Interfaces de Usuario.

Ilustracin 5: Controladores de Distribucin.

Control de Distribucin es el proceso de determinar el tamao y posicin de los


componentes. Por defecto, cada contenedor tiene un controlador de distribucin, es
decir, un objeto que realiza el control de la distribucin de los componentes que se
alojen dentro del contenedor. Los componentes pueden indicarle al controlador sus
preferencias de tamao y alineamiento, pero es finalmente el controlador el que decidir
la posicin final del componente, es l quien tiene la ltima palabra.
Existen cinco tipos de layout estndares en Java Swing:

- BorderLayout
- BoxLayout
- FlowLayout
- GridLayout
- GridBagLayout

En la figura anterior se muestra cmo cada uno de ellos mostrara diferentes


componentes. Existe una sexta clase, CardLayout, que es un controlador de distribucin
de carcter general que se utiliza en combinacin con otros controladores de
distribucin.
Anteriormente hablamos del mtodo add. Siempre que se use el mtodo add para
poner un componente en un contenedor, debemos tener en cuenta el controlador de
distribucin del contenedor con el que estamos tratando. En general los controladores de
distribucin colocarn los componentes en el orden que se han ido aadiendo. Sin
embargo, algunos controladores como BorderLayout requieren que especifiquemos la
posicin relativa del componente en el contenedor, usando un argumento extra para el
mtodo add. Tambin hay otros como GridBagLayout que requieren elaborados

- 91 -
6-. Interfaces de Usuario.

procesos de configuracin. Generalmente, slo se tendr que seleccionar el controlador


de distribucin de dos tipos de contenedores: paneles de contenido (que usan
BorderLayout por defecto) y JPanel (que usa FlowLayout por defecto).
Tras esta introduccin a los Controladores de Distribucin vamos a ver algunas de
las tareas ms comunes para ellos:

- SELECCIONAR EL CONTROLADOR DE DISTRIBUCIN:


Se puede cambiar el controlador que utiliza un contenedor por defecto. Slo hay
que llamar al mtodo setLayout del contenedor. Por ejemplo, para hacer que un JPanel,
que por defecto usa FlowLayout, utilice BorderLayout habra que escribir lo siguiente:

JPanel pane = new JPanel();


pane.setLayout(new BorderLayout());

Aunque es recomendable utilizar controladores de distribucin, se puede realizar


la distribucin sin ellos. Seleccionando una propiedad de distribucin del contenedor
inicializada a nulo, podemos hacer que el contenedor no use ningn controlador de
distribucin. Esta tcnica se denomina posicionamiento absoluto y con ella se puede
especificar el tamao y posicin de cada componente dentro del contenedor. Una
desventaja del posicionamiento absoluto es que no se ajusta bien cuando se
redimensiona el contenedor de alto nivel. Tampoco se ajusta bien a las diferencias
entres usuarios y sistemas, ni a los diferentes tamaos de fuente.

- PROPORCIONAR CONSEJOS SOBRE UN COMPONENTE:


Como ya hemos comentado, un componente puede decirle al controlador de
distribucin sus preferencias de tamao y alineamiento, pero es el controlador de
distribucin el que decide en ltima instancia qu hacer. Para personalizar estas
preferencias del componente podemos configurar sus tamaos mximo, mnimo y
preferido mediante los mtodos de seleccin de tamao del componente que son
setMinimumSize, setPreferredSize y setMaximumSize. Sin embargo esto no tiene por
qu dar el resultado que desearamos: actualmente, el nico controlador de distribucin
en la plataforma Java que presta atencin a la peticin de tamao mximo del
componente es BoxLayout.
Tambin existen mtodos para especificar preferencias de alineamiento
(setAlignmentX y setAlignmentY). Al igual que para el tamao, BoxLayout es el nico
controlador de distribucin que presta atencin a los consejos de alineamiento.

- PONER ESPACIO ENTRE COMPONENTES:


Hay tres factores que influyen en la cantidad de espacio entre componentes
visibles en un GUI:
o El controlador de distribucin: Algunos ponen espacio entre componentes
automticamente, otros no. Algunos permiten especificar la cantidad de
espacio que queremos dejar entre los componentes.
o Los Componentes Invisibles: Son componentes de peso ligero que ocupan
espacio en el GUI, pero no realizan ningn dibujo. Podemos por tanto crear un
componente invisible si queremos dejar un espacio en nuestro GUI.
o Bordes Vacos: Es otra de las opciones para aadir espacio entre componentes.
Consiste en algo tan sencillo como aadir bordes vacos. Los mejores
candidatos para los bordes vacos son los que tpicamente no tienen bordes,

- 92 -
6-. Interfaces de Usuario.

como los paneles y las etiquetas. Sin embargo, hay algunos otros
componentes, como los paneles desplazables, que no funcionan bien con
bordes en algunas implementaciones del Aspecto y Comportamiento, debido a
la forma en que implementan su cdigo de dibujo.

- CMO OCURRE EL CONTROL DE DISTRIBUCIN:


Mostramos un ejemplo de secuencia de control de distribucin para un frame
(JFrame). Es interesante leerlo por tener una idea de cmo funciona por dentro nuestro
GUI, pero realmente son detalles de bajo nivel de los que, por lo general, no tendremos
que ocuparnos nosotros.
1. Despus de que el GUI est construido, se llama al mtodo pack sobre el
JFrame. Esto especifica que el frame debera ser de su tamao preferido.
2. Para encontrar el tamao preferido del frame, el controlador de distribucin
aade el tamao de los lados del frame al tamao preferido del componente
directamente contenido por el frame (en nuestro ejemplo inicial este elemento
sera el JPanel). Esto es: la suma del tamao preferido del panel de contenido
ms el tamao de la barra de men del frame, si existe.
3. El controlador de disposicin del panel de contenido es responsable de
imaginarse el tamao preferido del panel de contenido. Por defecto, este
controlador de disposicin es un objeto BorderLayout. Sin embargo, asumamos
que lo hemos reemplazado con un objeto GridLayout que se ha configurado para
crear dos columnas. Lo interesante de Gridlayout es que fuerza a que todos los
componentes sean del mismo tamao, e intenta hacerlos tan anchos como la
anchura preferida del componente ms ancho, y tan altos como la altura
preferida del componente ms alto. Primero, el controlador Gridlayout pregunta
al panel de contenido por su insets (el tamao del borde del panel de contenido),
si existe. Luego, el controlador de Gridlayout le pregunta a cada componente del
panel de contenido sus tamaos preferidos, anotando la mayor anchura preferida
y la mayor altura preferida. Por ltimo calcula el tamao preferido del panel de
contenido.
4. Cuando a cada botn se le pide su tamao preferido, el botn primero
comprueba si el usuario ha especificado un tamao preferido. Si es as, reporta
este tamao. Si no es as, le pregunta a su Aspecto y Comportamiento el tamao
preferido por defecto.

El resultado final es que para determinar el mejor tamao de un frame, el sitema


determina los tamaos de los contenedores en la parte inferior del rbol de contenidos.
De forma similar ocurren los clculos cuando se redimensiona el frame.

6.2.7-. Manejo de Eventos.

Cada vez que el usuario teclea un carcter o pulsa un botn del ratn, ocurre un
evento. Cualquier componente puede ser notificado del evento. Todo lo que tiene que
hacer es implementar el interfaz apropiado y ser registrado como oyente de evento del
evento fuente apropiado.
Existen muchos tipos de eventos diferentes en Swing. En la siguiente tabla se
muestran algunos ejemplos:

- 93 -
6-. Interfaces de Usuario.

Accin que resulta en el evento Tipo de oyente


El usuario pulsa un botn, presiona Return mientras teclea en un
ActionListener
campo de texto, o elige un tem de un men.
El usuario selecciona una ventana principal. WindowListener
El usuario pulsa un botn del ratn mientras el cursor est sobre
MouseListener
un componente.
El usuario mueve el cursor sobre un componente. MouseMotionListener
El componente se hace visible. ComponentListener
El componente obtiene el foco del teclado. FocusListener
Cambia la tabla o la seleccin de una lista. ListSelectionListener
Tabla 6: Eventos y Oyentes Asociados en Swing.

Cada evento est representado por un objeto que ofrece informacin sobre el
evento e identifica la fuente (es decir, quin produjo dicho evento). Las fuentes de los
eventos normalmente son componentes, pero otros tipos de objetos tambin pueden ser
fuente de eventos.
Cada fuente de eventos puede tener varios oyentes registrados, es decir, varios
objetos a la vez pueden estar escuchando una fuente de eventos, y sern notificados
cuando un se produzca un evento en esta fuente. Inversamente, un oyente puede
registrarse con varias fuentes de eventos. Mostramos grficamente lo explicado:

Objeto evento /----> oyente de evento


Fuente de evento -----------------------------------> oyente de evento
\----> oyente de evento

Objeto evento /----> fuente de evento


Oyente de evento -----------------------------------> fuente de evento
\----> fuente de evento

- COMO IMPLEMENTAR UN MANEJADOR DE EVENTOS:

Todo manejador de eventos requiere tres partes de cdigo.

1. La clase del manejador: debe o bien implementar una interfaz de oyente, o


bien descender de una clase que implementa una interfaz del oyente en
cuestin. Por ejemplo:

public class MyClass implements ActionListener {

- 94 -
6-. Interfaces de Usuario.

2. El cdigo que registra sobre uno o ms componentes un ejemplar de la clase


de manejo de eventos de un oyente. Por ejemplo:

someComponent.addActionListener(instanceOfMyClass);

En este cdigo se est registrando una instancia de la clase de manejo de


eventos (MyClass, definida en el punto 1) sobre el componente de nombre
someComponent.

3. En el caso en que en el primer punto hayamos decidido implementar el


interfaz, ahora es necesaria la implementacin de los mtodos del interfaz
oyente. Por ejemplo:

public void actionPerformed(ActionEvent e) {


...//cdigo que reaccione a la accin...
}

Veamos un ejemplo en el que iremos indicando los pasos descritos anteriormente.


Imaginemos un programa que tiene botones (JButton). El usuario pulsar el botn de la
pantalla (o bien las teclas equivalentes al botn). Para poder detectar esta pulsacin, el
programa debe tener algn objeto que implemente el interfaz ActionListener (que es el
correspondiente al evento pulsacin de botn). Este ser nuestro manejador u
oyente de action (PASO 1).
El programa debe registrar este manejador como un oyente de Action del botn
(PASO 2). Cuando el usuario pulse el botn, se producir el evento Action, y ser
notificado a todos los elementos que estn registrados a este tipo de evento de esta
fuente, en este caso nuestro manejador. Esto resulta en una llamada al mtodo
ActionPerformed del oyente de action, que en este caso particular es el nico mtodo
del interfaz ActionListener. El nico argumento del mtodo es un objeto ActionEvent,
que representa al evento ocurrido y nos proporciona informacin tanto del evento como
de su fuente.
Es decir, cuando el usuario pulsa un botn, se produce un evento ActionEvent y
los oyentes de action del botn son notificados. Grficamente:

ActionEvent
button ---------------------------------> action listener

Los manejadores de eventos pueden ser ejemplares de cualquier clase.


Frecuentemente, se implementan usando clases internas annimas. Son clases sin
nombre definidas dentro de otras clases. Aunque las clases internas puedan hacer el
cdigo algo ms confuso y parezcan difciles de leer, realmente hacen el cdigo mucho
ms fcil de entender, una vez que se han utilizado. Manteniendo una implementacin
de un manejador de eventos cerca de donde se registra el manejador de eventos, las
clases internas ayudan tanto al programador como a los que siguen su cdigo a
encontrar fcilmente la implementacin completa del manejador de eventos.

- LOS THREADS Y EL MANEJO DE EVENTOS:


El cdigo de manejo de eventos se ejecuta en un slo thread: el thread de despacho
de eventos. Esto asegura que todo manejador de eventos se terminar de ejecutar antes

- 95 -
6-. Interfaces de Usuario.

de ejecutar otro. Es ms, el cdigo de dibujo tambin se realiza el thread de despacho de


eventos y sigue la misma norma. Esto significa que, mientras se est ejecutando por
ejemplo el mtodo actionPerformed de la interfaz ActionListener citada anteriormente,
el GUI del programa permanecer congelado: no se dibujar nada ni tampoco se
responder a otros eventos como pulsaciones de ratn.
Hay que tener cuidado con el manejo de eventos. El cdigo de manejo de eventos
debera poder ejecutar cada pulsacin, cada click de ratn, cada evento en resumen. De
otro modo el rendimiento del programa se ver empobrecido. Si fuese necesario realizar
una larga operacin como consecuencia de un evento, la opcin ms acertada es
arrancar un nuevo thread que realice dicha operacin.

- LOS ADAPTADORES:

La mayora de los interfaces de oyentes, al contrario que ActionListener,


contienen ms de un mtodo. Por ejemplo, el interface MouseListener contiene cinco
mtodos: mousePressed, mouseReleased, mouseEntered, mouseExited, y
mouseClicked. Incluso si slo te importan las pulsaciones, si tu clase implementa
directamente la interfaz MouseListener, entonces debes implementar los cinco mtodos
de MouseListener. Aquellos mtodos de eventos que no te interesan pueden tener los
cuerpos vacos. Aqu hay un ejemplo:

public class MyClass implements MouseListener {


...
someObject.addMouseListener(this);
...
// Definiciones vacas de mtodos:
public void mousePressed(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mouseClicked(MouseEvent e) {
//Supongamos que solo nos interesa este evento.
//La implementacin ira aqu.
}
}

Desafortunadamente, la coleccin de cuerpos de mtodos vacos resultante puede


resultar dura de leer y de mantener. Para ayudarnos a evitar este emborronamiento del
cdigo con cuerpos de mtodos vacos, el AWT y Swing proporcionan una clase adapter
por cada interfaz de oyente con ms de un mtodo. Por ejemplo, la clase MouseAdapter
implementa el interfaz MouseListener. Una clase adaptador implementa versiones
vacas de todos los mtodos del interfaz.
Para usar un adaptador se crea una subclase, en vez de implementar directamente
una interfaz de oyente. Por ejemplo, extendiendo la clase MouseAdapter, nuestra clase
hereda definiciones vacas para los mtodos que contiene MouseListener. Por ejemplo:

public class MyClass extends MouseAdapter {


...
someObject.addMouseListener(this);

- 96 -
6-. Interfaces de Usuario.

...
public void mouseClicked(MouseEvent e) {
//Implementacin del manejador para este evento.
}
}

Qu pasa si no queremos que nuestras clases de manejo de eventos desciendan de


una clase adaptador? Por ejemplo, supongamos que escribimos un applet, y queremos
que nuestra subclase Applet contenga algn mtodo para manejar eventos de ratn.
Como el lenguaje Java no permite la herencia mltiple, nuestra clase no puede
descender de las clases Applet y MouseAdapter a la vez. La solucin es definir una
clase interna (una clase dentro de nuestra subclase Applet) que descienda de la clase
MouseAdapter, como se muestra a continuacin.

//Ejemplo de utilizacin de clase interna.


public class MyClass extends Applet {
...
someObject.addMouseListener(new MyAdapter());
...
class MyAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
//Implementacin del manejador para este evento.
}
}

Otro ejemplo de uso de clases internas, en este caso con una clase interna
annima:

public class MyClass extends Applet {


...
someObject.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
//Implementacin del manejador para este evento.
}
});
...
}
}

Las clases internas funcionan bien incluso si nuestro manejador de eventos


necesita acceder a ejemplares de variables privadas de la clase que la encierra, aunque
algunos compiladores no permiten el acceso a dichas variables privadas. Un atajo es
eliminar el especificador private de la declaracin del ejemplar de la variable. Siempre
que no declaremos una clase interna como static, se podr referir a ejemplares de
variables y mtodos como lo hace el resto de cdigo que contiene la clase.

- 97 -
6-. Interfaces de Usuario.

6.2.8-. Dibujo.

En principio no es necesario conocer todos los detalles de dibujo del GUI pues el
programador no tiene que encargarse prcticamente de nada con respecto a este aspecto.
Sin embargo, puede ser interesante tener ciertas nociones para, en caso de que nuestros
componentes no se dibujen correctamente, ser capaces de entender qu hay de errneo
en nuestra implementacin. Tambin es til lo que se explica a continuacin si
queremos crear cdigo de dibujo personalizado para un componente.

- CMO FUNCIONA EL DIBUJO:


Cuando un GUI necesita dibujarse a si mismo (al iniciarlo, en respuesta a la vuelta
de un ocultamiento, o porque necesite reflejar un cambio en su estado), empieza con el
componente ms alto del rbol de contenidos que necesite ser redibujado, y va
descendiendo. Todo esto lo controla el sistema de dibujo del AWT, y se ha hecho ms
eficiente mediante el manejador de dibujo de Swing que utiliza un doble buffer.
Al igual que el cdigo de manejo de eventos, el cdigo de dibujo se ejecuta en el
thread del despacho de eventos. Mientras se est manejando un evento no ocurrir
ningn dibujo. De forma similar, si la operacin de dibujado tarda mucho tiempo, no se
manejar ningn evento durante ese tiempo
Los componentes Swing generalmente se redibujan a s mismos siempre que es
necesario. Por ejemplo, cuando llamamos al mtodo setText de un componente, el
componente debera redibujarse automticamente a s mismo, y si es necesario,
redimensionarse. Si no lo hace as es un bug. El atajo es llamar al mtodo repaint sobre
el componente para pedir que el componente se ponga en la cola para redibujado.
Los programas slo deberan dibujarse cuando el sistema de dibujo se lo diga.
Esto es as porque cada ocurrencia de dibujo de un componente debe ejecutarse sin
ningn tipo de interrupcin. Si no se hace as, podramos tener resultados impredecibles
e indeseados, como por ejemplo un botn que se dibuje medio pulsado y medio
liberado.
Para acelerar y mejorar el rendimiento, el dibujo Swing usa doble-buffer por
defecto. En qu consiste este doble buffer? Se realiza el dibujo en un buffer fuera de
pantalla y luego se lanza a la pantalla una vez finalizado. Otra opcin para ayudar al
rendimiento es hacer un componente Swing opaco. As, el sistema de dibujo de Swing
conocer lo que no tiene que pintar detrs del componente. Para hacer opaco un
componente Swing, se llama al mtodo setOpaque(true) sobre el componente.
Los componentes no-opacos de Swing puede parecer que tienen cualquier forma,
aunque su rea de dibujo disponible es siempre rectangular. Por ejemplo, un botn
podra dibujarse a s mismo dibujando un octgono relleno. El componente detrs del
botn, (su contenedor, comnmente) sera visible, a travs de las esquinas de los lados
del botn. El botn podra necesitar incluir cdigo especial de deteccin para evitar que
ocurra un evento Action cuando el usuario pulsa en las esquinas del botn.

- UN EJEMPLO DE DIBUJO:

Si volvemos a nuestra aplicacin de ejemplo, que no contena nada ms que un


botn y una etiqueta, podemos describir cmo ocurre su dibujo.

- 98 -
6-. Interfaces de Usuario.

1. El contenedor de alto nivel, JFrame, se dibuja as s mismo.


2. El panel de contenido primero dibuja su fondo, que es un rectngulo slido de
color gris. Luego le dice al JPanel que se dibuje el mismo. El rectngulo del
panel de contenido realmente no aparece en el GUI finalizado porque est
oscurecido por el JPanel. Es importante que el panel de contenido sea opaco.
De otro modo, resultar en dibujados confusos. Como un JPanel es opaco,
podemos hacer que sea el panel de contenido (utilizando getContentPane().
add). Esto simplifica considerablemente el rbol de contenidos y el dibujado,
eliminado un contenedor innecesario.
3. El JPanel primero dibuja su fondo, un rectngulo slido de color gris. Luego
dibuja su borde. El borde es un EmptyBorder, que no tendr efecto excepto
para incrementar el tamao del JPanel reservando algn espacio extra en los
laterales del panel como ya explicamos cuando hablamos del espacio entre
componentes. Finalmente, el panel le pide a sus hijos, es decir, a los
componentes que descienden de l en el rbol que se dibujen a s mismos.
4. Para dibujarse a s mismo, el JButton dibuja su rectngulo de fondo si es
necesario y luego dibuja el texto que contiene. Si el botn tiene el foco del
teclado, significa que cualquier cosa que se teclee va directamente al botn
para su procesamiento (el botn realiza algn dibujado caracterstico para
aclarar que tiene el foco, especfico del Aspecto y Comportamiento que se est
utilizando).
5. Para dibujarse a s misma, la etiqueta JLabel dibuja su texto.

Resumiendo, un componente se dibuja a si mismo antes de dibujar a los


componentes que contenga. De este modo nos aseguramos que una zona del fondo de
un JPanel slo queda dibujada si no tiene ningn componente hijo que la cubra. La
siguiente figura ilustra el orden en que cada componente que desciende de JComponent
se dibuja a s mismo.

2. dibujo
1. fondo 3. borde 4. hijos
personalizado
(si es opaco) (si existe) (si existen)
(si existe)
............. ............. ============= =============
............. ....()....... =...()......= =...()......=
............. ............. =...........= =.---------.=
............. ............. =...........= =.|JButton|.=
............. ............. =...........= =.---------.=
............. ............. ============= =============
Ilustracin 6: Orden en el dibujo de una aplicacin Swing.

6.2.9-. Los threads y Swing.

Hasta ahora hemos nombrado el thread de despacho de eventos. Tambin hemos


hablado de programas de thread seguro. Vamos a intentar aclarar un poco todo esto.
Si nuestro programa es un applet, lo ms seguro es construir el GUI en el mtodo init.
Por el contrario, si nuestro programa es una aplicacin, podemos usar el siguiente
patrn comn para estar seguros con respecto a los hilos:

- 99 -
6-. Interfaces de Usuario.

//Ejemplo de hilo seguro


public class MyApplication {
public static void main(String[] args) {
JFrame f = new JFrame(...);
...//Aadir componentes al frame aqu.
f.pack();
f.setVisible(true);
//No realizar ms trabajo para la GUI aqu.
}

...
//Toda la manipulacin de la GUI (setText, getText, etc.)se realiza
//en manejadores de eventos como por ejemplo actionPerformed().
...
}

Existe una regla para tratar con los hilos en Swing:


Una vez que se haya realizado un componente Swing, todo el cdigo que pudiera
afectar o depender del estado de ese componente debera ejecutarse en el thread de
despacho de eventos.
Esta regla puede parecer complicada a primera vista, pero para la mayora de
programas sencillos no tenemos que preocuparnos de los threads. Es importante definir
un par de trminos antes de continuar la exposicin: realizado y thread de despacho
de eventos.
Realizado significa que el mtodo paint del componente haya sido o podra ser
llamado. Un componente Swing que sea una ventana de alto nivel se realiza habiendo
llamado a uno de estos mtodos sobre ella: setVisible(true), show, o pack. Una vez que
una ventana se ha realizado, todos los componentes que contiene estn realizados. Otra
forma de realizar un componente es aadirlo a un componente que ya est realizado.
El thread de despacho de eventos es el thead que ejecuta el cdigo de dibujo y
de manejo de eventos. Por ejemplo, los mtodos paint y actionPerformed se ejecutan
automticamente en el thread de despacho de eventos. Otra forma de ejecutar cdigo en
el thread de despacho de eventos es usar el mtodo invokeLater de SwingUtilities
Como para casi toda regla, existen algunas excepciones. Existen algunos mtodos
que se denominan de thread seguro. Podemos ver qu mtodos son stos en la
documentacin de la API Swing, ya que los mtodos de thread seguro estn marcados
con dicho texto.
Podemos aadir otra excepcin que dice: La GUI de una aplicacin
frecuentemente puede ser construida y mostrada en el thread principal.. Mientras no se
haya realizado ningn componente, no hay problema en construir y mostrar un GUI en
el hilo main. De hecho, en general se puede construir (pero no mostrar) un GUI en
cualquier thread, mientras no se hagan llamadas que se refieran o afecten a los
componentes ya realizados. Vemoslo en el ejemplo de hilo seguro anterior.
1. El ejemplo construye el GUI en el thread principal.
2. Los componentes del GUI son realizados por la llamada a pack.
3. Segn la regla, una vez realizado un componente Swing, todo el cdigo que
pudiera afectar o depender del estado de ese componente debera ejecutarse en
el thread de despacho de eventos. Es decir, la llamada a setVisible, con la que

- 100 -
6-. Interfaces de Usuario.

son mostrados los componentes del GUI, es tcnicamente insegura ya que los
componentes han sido realizados con la llamada a pack y se est ejecutando
este setVisible fuera del thread de despacho de eventos. Sin embargo, como el
programa no ha hecho visible el GUI todava, es sumamente contrario a que
una llamada a paint ocurra antes de que retorne setVisible.
4. El thread principal no ejecuta cdigo GUI despus de llamar a setVisible. Esto
significa que el cdigo del GUI se mueve del thread principal al thread de
despacho de eventos, y el ejemplo es, en la prctica, de thread seguro.

Si queremos ejecutar cdigo en el thread de despacho de eventos, pero no desde


algn mtodo de un Oyente, sino desde otros lugares de nuestro programa, podemos
utilizar unos mtodos de la clase SwingUtilities:
- invokeLater: Pide que algn cdigo se ejecute en el thread de despacho de
eventos. Este mtodo retorna inmediatamente, sin esperar a que el cdigo sea
ejecutado.
- invokeAndWait: Acta igual que invokeLater, excepto en que este mtodo espera
a que el cdigo se ejecute. Como regla, deberamos usar invokeLater en vez de
este mtodo.

Si no hablamos de aplicaciones sino de Applets, la tcnica para construir un GUI


de hilo seguro consiste en construir y mostrar el GUI en el mtodo init. Los navegadores
existentes no dibujan el applet hasta despus de que hayan sido llamados los mtodos
init y start. As, construir el GUI en el mtodo init del applet es seguro, siempre que no
se llame a show() o setVisible(true) sobre el objeto applet actual. Por supuesto, los
applets que usan componentes Swing deben ser implementados como subclases de
JApplet, y los componentes deben ser aadidos al panel de contenido del JApplet, en
vez de directamente al JApplet, es decir, el procedimiento es similar al explicado para
las aplicaciones. Al igual que para cualquier applet, nunca deberamos realizar
inicializacin que consuma mucho tiempo en los mtodos init o start; en su lugar
deberamos arrancar un thread que realice las tareas que consuman tiempo.

6.2.10-. Ms caractersticas Swing.

- Caractersticas adquiridas de JComponent: Todos los componentes Swing cuyo


nombre empieza por J, salvo los contenedores de alto nivel, descienden de la clase
JComponent y por tanto obtienen muchas caractersticas de esta clase. Por
ejemplo, la posibilidad de tener bordes, tooltips (texto de ayuda que aparece al
dejar el ratn quieto sobre un componente durante algunos segundos) y Look &
Feel configurable.

- Iconos: Muchos componentes Swing, principalmente los botones y las etiquetas,


pueden mostrar algn tipo de dibujo o imagen. Para ello se utilizan objetos de la
clase Icon.

- Actions: Estos objetos permiten compartir datos y estados entre dos o ms


componentes que puedan generar eventos de tipo Action. Un ejemplo: un botn e

- 101 -
6-. Interfaces de Usuario.

un item de men que realicen la misma funcin pueden ser implementados con
este tipo de objeto.

- Aspecto y Comportamiento Conectable: Un programa, aunque sea muy sencillo,


puede tener uno o varios Aspectos y Comportamientos diferentes. Es ms,
podemos permitir que el usuario los determine, o determinarlos nosotros
directamente mediante la programacin.

- Soporte para tecnologas asistivas: Ya hemos nombrado esta caracterstica Swing.


No entraremos mucho ms en detalle de lo visto hasta ahora, pero merece la pena
recordar que las tecnologas asistivas, como por ejemplo un lector de pantalla,
tambin pueden usar la API Swing. La utilizacin de tecnologas asistivas puede
expandir sin duda el mercado de nuestro programa.

- Modelos de Datos y Estados separados: La mayora de los objetos Swing que no


son contenedores tienen un modelo. Por ejemplo, un botn (JButton) tiene un
modelo (ButtonModel) que almacena el estado del botn: su mnemnico de
teclado, si est activado/seleccionado/pulsado, etc. Otros componentes como JList
tienen mltiples modelos: un ListModel para almacenar los contenidos de la lista y
un ListSelectionModel que sigue la pista de la seleccin actual de la lista. En
general no es necesario conocer los modelos, de hecho hay muchas veces en las
que ni se utilizan. Sin embargo, existen porque ofrecen la posibilidad de trabajar
con componentes ms eficientemente y de compartir fcilmente datos y estados
entre componentes.

6.2.11-. Sobre los componentes de texto en Swing.

Dado que la aplicacin que se desarrolla en este proyecto fin de carrera es una
herramienta para la edicin de un tipo concreto de documento, debemos prestar especial
atencin a los Componentes de Texto de Swing en esta memoria.
Los componentes de texto muestran algn texto y opcionalmente permiten que el
usuario lo edite. Los programas necesitan componentes de texto para tareas dentro del
rango del sencillo (introducir una palabra y pulsar Enter) al complejo (mostrar y editar
texto con estilos y con imagenes embebidas en un lenguaje asitico). Los paquetes
Swing proporcionan cinco componentes de texto y proporcionan clases e interfaces para
conseguir los requerimientos ms complejos. Sin importar sus diferentes usos o
capacidades, todos los componentes de texto Swing descienden de la misma superclase,
JTextComponent, que proporciona una base poderosa y ampliamente configurable
para la manipulacin de texto. La ilustracin 7 muestra una clasificacin de los distintos
componentes de texto Swing. As mismo, mostramos una figura (ilustracin 8) de una
sencilla aplicacin en la que se pueden observar estos componentes.

- 102 -
6-. Interfaces de Usuario.

Ilustracin 7: Clasificacin de los Componentes de Texto Swing.

Ilustracin 8: Aplicacin con Componentes de Texto Swing.

El siguiente cuadro define los tres grupos existentes de componentes de texto.

Grupo Descripcin Clases Swing


Conocidos simplemente como campos de texto, los
controles de texto pueden mostrar y editar slo una
Controles de lnea de texto y estn basados en action como los JTextField
Texto botones. Se utilizan para obtener una pequea y su subclase
cantidad de informacin textual del usuario y toman JPasswordField
algunas acciones despus de que la entrada se haya
completado.
JTextArea, el nico componentes de texto plano de
Swing, puede mostrar y editar mltiples lneas de
texto. Aunque un rea de texto puede mostrar texto
en cualquier fuente, todo el texto est en la misma
fuente. Toda la edicin de los componentes de texto
plano se consigue a travs de la manipulacin directa
Plano del texto con el teclado y el ratn, por esto los JTextArea
componentes de texto plano son ms fciles de

- 103 -
6-. Interfaces de Usuario.

configurar y utilizar que los componentes de texto


formateado. Tambin, si la longitud del texto es
menor de unas pocas pginas, podemos fcilmente
utilizar setText y getText para recuperar o modificar
el contenido del componente con una simple llamada
a un mtodo.
Un componente de texto formateado puede mostrar y
editar texto usando ms de una fuente. Algunos
componentes de texto formateado permiten incluir
imgenes e incluso componentes. Tpicamente se
tendrn que hacer ms programacin para usar y JEditorPane
Formateado configurar componentes de texto formateado, porque y su subclase
muchas de sus funcionalidades no estn disponibles a JTextPane
travs de la manipulacin directa con el ratn y el
teclado. Una caracterstica manejable y fcil de usar
proporcionada por JEditorPane es que puede ser
cargado con texto formateado desde una URL
Tabla 7: Grupos de Componentes de Texto.

Veamos ahora algunas reglas de uso de los Componentes de Texto.


JTextComponent es la base para los componentes de texto Swing y proporciona estas
caractersticas, personalizables para todos sus descendientes:

- Un modelo separado, conocido como Document, para manejar el contenido del


componente.
- Una vista separada, que se encarga de mostrar el componente en la pantalla.
- Un controlador separado, conocido como un editor kit, que puede leer y escribir
texto e implementa capacidades de edicin con comandos action.
- Mapas de teclas personalizados.
- Soporte para repetir/deshacer infinito.
- Cursores conectables y oyentes de cambios de cursor.

Como hemos dicho, y al igual que muchos otros componentes Swing, un


componente de texto separa su contenido de su vista. El contenido de un componente es
manejado por su documento, el cual contiene el texto, soporte para edicin, y notifica a
los oyentes los cambios en el texto. Un documento es un ejemplar de una clase que
implementa el interfaz Document o su subinterfaz StyledDocument. Podemos
personalizar un documento, dndole las caractersticas que necesitemos (por ejemplo,
hacer que limite el nmero de caracteres que puede contener). Tambin hemos dicho
que un documento notifica sus cambios a los oyentes interesados. Se utiliza un oyente
de Document (DocumentListener) para reaccionar cuando se inserta o se elimina texto
de un documento, o cuando cambia el estilo de alguna parte del texto.
Todos los componentes de Texto Swing soportan comandos de edicin estndar
como cortar, copiar, pegar y la insercin de caracteres. Cada comando de edicin est
representada e implementado por un objeto Action. Esto hace sencillo el asociar un
comando con un componente GUI, como un tem de men o un botn, y construir un
GUI alrededor de un componente de texto. Un componente de texto usa un objeto
EditorKit para crear y manejar estas acciones. Adems de manejar un conjunto de

- 104 -
6-. Interfaces de Usuario.

acciones para un componente de texto, un kit de editor tambin sabe leer y escribir
documentos en un formato particular. El paquete text de Swing proporciona estos tres
kits de editor:
- DefaultEditorKit: Lee y escribe texto sin estilo. Proporciona un conjunto bsico
de comandos de edicin. Los dems kits de editor descienden de este.
- StyledEditorKit: Lee y escribe texto con estilo y proporciona un conjunto de
acciones mnimo para texto con estulo. Esta clase es una subclase de
DefaultEditorKit y es el kit de editor usado por defecto por JTextPane.
- HTMLEditorKit: Lee, escribe y edita HTML. Esta es una subclase de
StyledEditorKit.

6.3-. SWT.
6.3.1-. Introduccin.

No slo existen AWT y Swing para la creacin de GUIs. Otro representante


importante es SWT. Describiremos a continuacin qu es, por qu surge y sobre todo
por qu no se ha utilizado para el desarrollo de este proyecto.
El Standard Widget Toolkit (SWT) ha sido creado por IBM como reemplazo de
AWT y Swing. De manera ms precisa, el SWT es un conjunto de widgets (widgets son
controles o componentes) para desarrolladores Java que ofrece una API portable y una
integracin muy ligada con la interfaz grfica de usuario nativa al sistema operativo de
cada plataforma. As, cada plataforma debe adaptar el SWT para sus grficos nativos.
Esto parece que entra en contradiccin con la filosofa de Java de ser independiente de
la plataforma, pero ofrece ventajas en la unicidad del aspecto del GUI diseado sea cual
sea la plataforma sobre la que se ejecute. Hasta el momento los entornos a los que se ha
portado SWT son Windows, Linux GTK, Linux Motif, Solaris Motif, AIX Motif,
HPUX Motif, Photon QNX, y Mac OS X.

6.3.2-. Evolucin de los grficos en Java.

Los grficos en Java han tenido un largo y exitoso desarrollo. Se empez como ya
sabemos con el paquete bsico AWT, vindose ampliado por el paquete Swing.
Actualmente est empezando a hablarse de SWT, y parece que pueda llegar a
imponerse. Ahondemos un poco en esta evolucin:
- AWT: Primer acercamiento de Java al desarrollo de interfaces grficas (GUI).
Permite mostrar ventanas con controles variados como cajas de texto y botones.
Las GUIs con AWT son fciles de desarrollar, y usan los controles propios del
sistema operativo en el que se programa, por ejemplo, en windows aparecer una
ventana de texto tpica de windows, en Mac, una ventana con sus respectivas
caractersticas Mac, etc. El problema que se presenta es que algunos sistema
operativos difieren de otros en el conjunto de controles, por lo que Sun slo
implement los controles comunes a los sistemas operativos a los que se dirige

- 105 -
6-. Interfaces de Usuario.

Java, que por lo general, es un conjunto reducido y simple respecto de los


realmente disponibles.
- SWING: Introducido posteriormente, motivado por la creciente demanda de los
desarrolladores de tener una implementacin no nativa, esto es, independiente de
la plataforma, de controles de ms alto nivel como rboles, tablas y texto. Con esto
se gana en funcionalidad, pero con el inconveniente de hacer las aplicaciones
Swing demasiado especficas de Java. Sun aadi una emulacin look and feel
para aproximar el aspecto de las aplicaciones Swing al sistema operativo sobre las
que se ejecuta, pero no abarca las nuevas versiones de los sistemas operativos
(Windows Me, 2000 en adelante, por ejemplo). Adems, al estar implementado
sobre Java y no de forma nativa en el sistema operativo, los tiempos de respuesta
de las interfaces Swing son sensiblemente ms lentas que las nativas.
- SWT (Standard Widget Toolkit): Ofrece un conjunto de elementos que hacen uso
directo de los controles nativos a travs de la Interfaz Nativa de Java (JNI). Si los
controles no estn ofrecidos por el sistema operativo, SWT crea los suyos propios
segn las necesidades. Esto significa que se necesita cdigo nativo para poder
funcionar en cada sistema operativo, pero IBM ha sido capaz de adaptar SWT a un
buen nmero de sistemas. Es muy destacable la importancia de SWT porque es el
entorno grfico de desarrollo que viene con Eclipse y debe ser utilizado en los
plugins desarrollados para el mismo. Eclipse, como ya sabemos, es la herramienta
que se ha utilizado para el desarrollo de este proyecto.

6.3.3-. Fundamentos de SWT.

SWT se compone esencialmente de tres elementos:

1. En el nivel inferior se encuentra una librera nativa que interacciona


directamente con el sistema operativo. Es la denominada JNI, que hemos
nombrado anteriormente. Al ser la parte ms dependiente de la plataforma,
debe ser portada en funcin de la misma.
2. Por encima de la anterior capa est la clase Display, la interfaz por la que el
SWT se comunica con la interfaz grfica.
3. El nivel superior lo forma la clase Shell, representa el tipo de ventana de ms
alto nivel y que es donde se alojan los widgets, controles o componentes. El
shell es la parte de la interfaz que est directamente controlada por el sistema
de ventanas del sistema operativo. La clase Shell es hija de la clase Display, en
cuyo caso es la ventana o marco principal a partir de la cual se construye el
resto de la interfaz, o bien hija de otro shell, siendo el ejemplo ms comn las
ventanas de dilogo.

No vamos a entrar en detalles de cdigo de SWT. Sin embargo, para tener una
ligera idea, finalizaremos con un ejemplo: el tpico Hello World.

import org.eclipse.swt.widgets.*;

public class HelloWorld {

- 106 -
6-. Interfaces de Usuario.

public static void main(String[] args) {


Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Hola Mundo");
shell.setSize(200, 100);
shell.open();

while (!shell.isDisposed() {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}

Comentemos el cdigo. Se identifican las partes de las que hablamos


anteriormente.

Display display = new Display();

Display representa la pantalla y su conexin con el sistema gestor de ventanas del


sistema operativo en el que nos encontramos. El objeto display contendr a su vez una
lista de objetos shell. El shell es una ventana abierta sobre la pantalla. Es la clase raz de
los componentes y controles. Aadimos un shell a un display con el cdigo:

Shell shell = new Shell(display);


shell.open();

El siguiente fragmento de cdigo es el denominado bucle de eventos. Ha de ser


programado explcitamente y su funcin es detectar y ejecutar eventos. Es la forma en
que liberamos la CPU para otros menesteres ajenos a la interfaz grfica cuando no se
han producido eventos a los que dedicar ciclos de proceso para atender:

while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}

Por ltimo observamos que los recursos del sistema han de ser liberados por el
programador (display.dispose();). La liberacin del objeto display conlleva la
finalizacin de todos los shells hijos contenidos.
Esto no es ms que una pequea introduccin. Para ahondar en el tema se puede ir
a la web del proyecto Eclipse, www.eclipse.org/swt.

- 107 -
6-. Interfaces de Usuario.

6.3.4-. Ventajas y desventajas de SWT.

Por ltimo, es importante comentar las ventajas y desventajas de este paquete, y


explicar por qu se ha elegido Swing para la realizacin del proyecto. Hoy en da hay
una lucha importante entre defensores y detractores de Swing y SWT. Podramos
destacar algunos aspectos:

- No elija SWT por su fidelidad a la plataforma, ya que esto no es una gran virtud.
Normalmente los usuarios no tiene problema en utilizar interfaces alejados de su
S.O. nativo, siempre que estos sean buenos y fciles de usar. Vase el ejemplo
de Firefox, Winamp, etc.
- Se utiliza un planteamiento de mnimo comn denominador de las plataformas
soportadas. Es decir, puede haber una caracterstica muy tpica de Windows pero
que no est disponible slo porque sta no existe en Motif.
- Si las necesidades del proyecto se alejan de las de las necesidades del proyecto
Eclipse la dificultad aumenta ya que SWT fue creado como soporte para dicho
proyecto y est orientado hacia l, dejando de lado caractersticas que Eclipse no
utiliza.
- SWT tiene muchos fallos. Es una plataforma relativamente joven y se nota.
- Para el que ya conoce Swing, elegir SWT por pensar que Swing es feo es un
gran error. Se pueden hacer aplicaciones realmente atractivas en Swing.

Aparte de los puntos anteriores, a la hora de decidir entre Swing y SWT para
realizar el proyecto se tuvo en cuenta la escasa cantidad de documentacin que se puede
encontrar de este ltimo, dado que es una tecnologa joven y emergente. Por estas
razones, la eleccin fue Swing.

6.4-. Conclusiones.

Llegados a este punto, realicemos una breve recapitulacin. Hemos descrito en


este captulo las herramientas ms importantes para la realizacin de interfaces grficas
de usuario, prestando especial atencin al paquete Java Swing. Hemos visto la gran
cantidad de elementos que ste nos permite implementar y sus ventajas frente al AWT.
Tambin hemos hablado de la tecnologa SWT. Las explicaciones presentadas en este
captulo servirn para comprender mejor la herramienta implementada. Pero antes de
pasar a la descripcin de dicha herramienta es necesario hablar de los Analizadores
XML, tema que abordaremos en el siguiente captulo.

- 108 -

También podría gustarte