Vous êtes sur la page 1sur 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. El componente se hace visible. El componente obtiene el foco del teclado. Cambia la tabla o la seleccin de una lista.
Tabla 6: Eventos y Oyentes Asociados en Swing.

MouseMotionListener ComponentListener FocusListener ListSelectionListener

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. 1. fondo (si es opaco) ............. ............. ............. ............. ............. ............. 2. dibujo 3. borde personalizado (si existe) (si existe) ............. ....()....... ............. ............. ............. ............. ============= =...()......= =...........= =...........= =...........= ============= 4. hijos (si existen) ============= =...()......= =.---------.= =.|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 Conocidos simplemente como campos de texto, los controles de texto pueden mostrar y editar slo una lnea de texto y estn basados en action como los botones. Se utilizan para obtener una pequea cantidad de informacin textual del usuario y toman 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 del texto con el teclado y el ratn, por esto los componentes de texto plano son ms fciles de Clases Swing

Controles de Texto

JTextField y su subclase JPasswordField

Plano

JTextArea

- 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 configurar componentes de texto formateado, porque muchas de sus funcionalidades no estn disponibles a 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

Formateado

JEditorPane y su subclase JTextPane

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 -

Vous aimerez peut-être aussi