Académique Documents
Professionnel Documents
Culture Documents
- 77 -
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.
- 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
Window
Panel
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.
- 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.
- 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.
- 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.
- 84 -
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 -
- 89 -
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).
- 90 -
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. -
- 93 -
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.
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.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|.= =.---------.= =============
- 99 -
//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.
- 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.
- 102 -
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
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
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.
- 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.
- 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 -
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 -