Sei sulla pagina 1di 114

EL ARCHIPILAGO ECLIPSE

(PARTE 4 DE 4)

Miguel ngel Abin
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 2 de 114
EL ARCHIPILAGO ECLIPSE
(PARTE 4 DE 4)

Fecha de ltima revisin: 27.05.2014

Miguel ngel Abin
mabian ARROBA aidima PUNTO es







Conozco mquinas que son ms complicadas que la gente.
Thomas Pynchon. V

La gente suele preguntarme: Por qu escribe usted en una lengua moribunda?. Esa
pregunta tiene varias respuestas. En primer lugar, me gusta escribir historias de fantasmas,
y para eso nada hay ms adecuado que una lengua moribunda. Cuanto ms muerta est una
lengua, ms vivo est el fantasma. A los fantasmas les encanta el yiddish y, por lo que s,
todos lo hablan. [...] Por otra parte, el yiddish puede ser una lengua moribunda, pero es la
nica que conozco bien. Fue la lengua de mi madre, y ustedes saben que una madre nunca
est realmente muerta.
I. B. Singer. Discurso en la ceremonia de entrega de los premios Nobel (1978)


En 1968, los Beatles publicaron el doble disco conocido como el lbum blanco.
Visto en retrospectiva, el disco es el testimonio de un grupo que haba dejado atrs los
alaridos de las fans y que estaba buscando su propia voz, lejos de la psicodelia y del
rock and roll. En el lbum blanco hay de todo, como en un bazar: confusin (musical y
personal), pop, rock'n'roll, distorsin, experimentacin (musical y comercial), baladas,
aullidos. No obstante, el disco no es un caos informe ni un revoltijo desconcertante: hay
un cierto orden interno, una cierta coherencia. Los Beatles no siguieron el camino
esbozado en este disco, bien porque los conflictos personales estaban destrozando a la
banda, bien porque ese camino no coincida con lo que la gente esperaba de un grupo
tan conocido.
Eclipse me recuerda mucho al lbum blanco. La plataforma Eclipse tiene de todo:
uno puede trabajar, entre otros lenguajes, con Java, C/C++, PHP, JavaScript, Ruby,
Pascal, Eiffel, Python y COBOL (el no muerto, el Nosferatu de los lenguajes informticos:
espero que nunca le muerda). Nadie le impide agregar a Eclipse los plug-ins
(extensiones) que desee y trabajar con un magnfico IDE, hecho a medida, para ASP,
JSP, XML, XHTML o HTML. Es ms, puede escribir sus propios plug-ins y
comercializarlos. Tantas posibilidades no se traducen por ahora en un Helter Skelter:
la comunidad de desarrolladores y los publicistas que rodean a Eclipse estn trabajando
mucho y muy bien, con metas muy claras. Con todo, hay mucho de experimentacin, en
este caso informtica y comercial, dentro y alrededor de Eclipse.
Copyright (c) 2005-2014, Miguel ngel Abin. Este documento puede ser distribuido slo
bajo los trminos y condiciones de la licencia de Documentacin de javaHispano v1.0 o
posterior (la ltima versin se encuentra en http://www.javahispano.org/licencias/).

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 3 de 114
Al proyecto Eclipse le deseo mejor suerte que los Beatles tras el lbum blanco. Si el
proyecto se fragmenta en exceso, es posible que a los subproyectos les ocurra lo mismo
que a los componentes del grupo. A saber: que ninguno alcanz la popularidad y el
reconocimiento que haban tenido cuando estaban unidos.
John Lennon dijo en 1980, poco antes de morir: Si los aos sesenta o los Beatles
tenan un mensaje, era aprender a nadar. Y una vez has aprendido, nadar. Esta serie de
artculos es una rpida leccin de natacin, impartida con un solo fin: invitarle, si no lo ha
hecho ya, a zambullirse en las aguas del ocano Eclipse. No tiene nada que perder, y s
mucho que ganar.






14. SWT: el nuevo componente grfico para Java

El Standard Widget Toolkit (SWT) de la plataforma Eclipse ha sido el aspecto de
Eclipse que mayores rechazos, adhesiones y controversias ha provocado en la
comunidad de Java. SWT constituye la respuesta de IBM, para el desarrollo de interfaces
de usuario, a AWT y a Swing (la historia de SWT y su papel en la estrategia comercial de
IBM se explicarn en la prxima parte de esta serie de artculos). De acuerdo con la
documentacin oficial de Eclipse, he aqu la descripcin del componente Standard
Widget Toolkit: "El componente SWT est diseado para proporcionar acceso eficaz y
transportable a los servicios de interfaz de usuario del sistema operativo sobre el cual se
implementa". Dicho de otra manera, tambin oficial: [SWT es] un conjunto de
componentes grficos y una biblioteca grfica integrada con el sistema de ventanas
especfico del sistema operativo, pero con una API independiente del SO. Tanto SWT
como JFace son bibliotecas estructuradas en paquetes con clases e interfaces escritas
en Java.
Widget es una palabra inglesa que se usa para referirse a un dispositivo cuyo
nombre no se conoce o no importa, o bien a un dispositivo que todava no existe; una
traduccin aproximada sera cachivache o trasto. Chocara mucho leer frases como el
cachivache pequeo se coloca en el centro del cachivache grande en un artculo tcnico
en espaol; en cambio, en ingls suenan incluso simpticas.
La documentacin oficial de Eclipse (http://www.eclipse.org) establece que un
widget es cualquier objeto de la interfaz grfica de usuario que puede colocarse dentro
de otro widget (versin tecnolgica de la frase Una gallina es lo que usan los huevos
para producir otros huevos; el ser humano no ha avanzado mucho explicando las cosas,
la verdad). Veamos una definicin ms aclaratoria: Un widget es un objeto de la interfaz
grfica de usuario, responsable de la interaccin con el usuario.
En la documentacin y la bibliografa de Eclipse suelen usarse de manera
intercambiable las palabras widget y control (elemento de la interfaz grfica con
contrapartida en el sistema operativo; es decir, gestionado por el SO). Esta equivalencia
no resulta del todo cierta, pues no todos los widgets son controles. Consideremos, vaya
por caso, un control de tipo rbol: sus nodos y subnodos son widgets (elementos de la
interfaz grfica), pero no controles. La razn para esto es prctica: si el rbol se encarga
de dibujar los nodos y subnodos, se evita consumir los recursos del sistema operativo
que se necesitaran si cada nodo fuera un control.


El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 4 de 114
Suele decirse que Swing es un componente de peso ligero (lightweight), mientras
que SWT y AWT son de peso pesado (heavyweight). Aunque el significado de estos
trminos dista mucho de ser unnime, suele aceptarse que peso ligero significa que
hay una asociacin o correspondencia uno a uno (one-to-one mapping) entre los widgets
del componente y los de la plataforma (controles). Un componente de peso pesado
simplifica mucho la programacin grfica: todas las implementaciones de los sucesos
(apretar una tecla, mover el ratn...) vienen dadas por el sistema operativo, mejor dicho,
por el gestor de ventanas del sistema operativo. Su principal desventaja radica que
consume muchos recursos del sistema operativo (memoria, punteros, ciclos de CPU).
Consideremos, por ejemplo, que creamos un objeto java.awt.Button: al instante, el gestor
de ventanas del SO crear su propio botn. Cuando el usuario pulse el botn, el suceso
ir, primero, de la biblioteca grfica del SO a la mquina virtual de Java; luego, ir a la
lgica vinculada al objeto Button de AWT, que decidir qu hay que hacer.
En un componente de peso ligero, los widgets son dibujados por el componente, no
por el SO. En consecuencia, cada componente debe encargarse de implementar
sucesos como mover el ratn o apretar una tecla. A cambio, su rendimiento resulta, en
general, mejor que el de uno pesado (en cuanto a recursos, es ms facil y menos
exigente dibujar widgets que dejar que los cree el SO). Consideremos, por ejemplo, una
ventana con cien o doscientas etiquetas. En Swing, la ventana (un JFrame) se
comportar mejor que en AWT o SWT, pues las etiquetas se dibujan sobre la ventana y,
por tanto, no hay que preocuparse por liberar sus recursos (son dibujos). En estos dos
ltimos componentes grficos, las etiquetas sern creadas por el SO, que tendr que
conservarlas en memoria en todo momento y supervisar sus sucesos y el estado de cada
una.
Otro ejemplo: consideremos una tabla con un milln de filas. En Swing, el tiempo
que se tardara en dibujarla apenas diferira del empleado para dibujar una tabla de diez
mil filas. En SWT, el tiempo que se tardara en dibujar la tabla de un milln de filas sera
de dos rdenes de magnitud superior al necesario para dibujar la tabla de diez mil filas,
pues cada fila sera un widget mantenido por el sistema operativo (omito aqu cualquier
consideracin sobre la memoria que empleara SWT). Por regla general, la escalabilidad
de los componentes de peso ligero es mucho mayor que la de los componentes de peso
pesado.


Es SWT un AWT con muchos ms widgets? Por fuera, s; pero por dentro hay
muchas diferencias. Tanto AWT como SWT usan las funciones de la API grfica de las
plataformas donde se ejecutan, pero lo hacen de modo muy distinto. AWT usa un
sistema de componentes gemelos donde cada widget AWT tiene asociado un
componente en el gestor de ventanas del sistema operativo. Cada widget AWT tiene
asociado cdigo nativo, escrito en C o C++, que hace llamadas a las bibliotecas grficas
de la plataforma (en Windows, Win32 o MFC) y que controla el comportamiento de los
widgets. En cada JDK (Java Distribution Kit) se incluyen las clases Java de AWT y el
cdigo mquina resultante de compilar el cdigo nativo (el cdigo mquina cambia para
cada plataforma, pero no las clases Java).
De resultas del diseo basado en componentes gemelos, AWT tiene un nmero
muy limitado de widgets, pues slo puede incluir componentes presentes en todas las
plataformas donde se implementa. Por ejemplo, no hay un widget rbol en AWT, pues no
existe en Motif y, por tanto, en esa plataforma no hay un componente gemelo rbol al
que AWT puede llamar.
En SWT, los widgets estn escritos en Java, no en cdigo nativo; y los mtodos
grficos de la plataforma se llaman a travs de una capa que se explicar ms
adelante. Para cada plataforma, esta capa expone los mtodos de la API (interfaz de
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 5 de 114
programacin de aplicaciones) grfica de la plataforma, de suerte que las clases SWT
(escritas en Java) pueden llamar a los mtodos de la API grfica. A diferencia de AWT,
las clases SWT cambian en cada plataforma. Aparte de que hay muchos ms widgets en
SWT que en AWT, la gran ventaja de SWT es que toda la lgica de los widgets est
escrita en Java (en AWT, la lgica est mezclada con cdigo nativo de cada plataforma).


El propsito original de Swing consista en proporcionar a las aplicaciones escritas
en Java el mismo aspecto en todas las plataformas (con la posibilidad de imitar hasta
cierto punto la apariencia propia de cada una). Aunque con Swing pueden producirse,
con esfuerzo, aplicaciones en Java de aspecto similar a las aplicaciones propias de cada
plataforma, su rendimiento siempre ha sido pobre. Resulta destacable que Swing haya
mejorado bastante su eficacia en las versiones 1.4 y 5.0 (antes 1.5) de Java.
Posiblemente, la competencia que supone SWT ha influido beneficiosamente en el
desarrollo de Swing.
El motivo del pobre rendimiento con Swing radica en que el cdigo que interacciona
directamente con los widgets de cada plataforma est escrito en C o C++ (forma parte de
las bibliotecas de AWT especficas de cada plataforma) y, en consecuencia, no est
disponible para Swing, que est escrito en Java. Tambin la API que proporcionan los
widgets propios de cada plataforma est escrita en C o C++, y Swing no puede acceder
directamente a ella. Por estos motivos, Swing trabaja con la API grfica que le
proporciona AWT. En Swing, cada componente es dibujado como una imagen en el
componente que lo contiene, lo que requiere que Swing trabaje bit a bit con las interfaces
grficas. Cuando se quiere mostrar una interfaz al usuario, Swing a travs de AWT
enva el mapa de bits correspondiente al gestor de ventanas propio de la plataforma
donde se trabaja. Como puede suponerse, este planteamiento dista mucho de ser eficaz;
sus limitaciones se aprecian enseguida en dispositivos como agendas electrnicas o
telfonos mviles, donde la memoria est muy limitada.
En cuanto a la personalizacin de los controles Swing para cada plataforma (lo que
se conoce como pluggable look and feel o pluggable L&F), los resultados han sido
sumamente mediocres: en parte porque la apariencia no coincide exactamente con la
que deberan tener, y en parte porque Sun no ha ido actualizando Swing a las nuevas
versiones de los sistemas operativos. As, por ejemplo, la apariencia y sensacin de
Windows (Windows L&F) que proporciona Swing ha sido (hasta la versin 1.4.2 de Java)
la misma para Windows 95, Windows 98, Windows 2000, Windows Millenium (curioso
experimento fallido, por cierto) y Windows XP. Como usted mismo habr comprobado, la
apariencia de las aplicaciones para Windows cambiaba, y mucho, de una versin del
sistema operativo a otro.


En comparacin con Swing, el SWT de Eclipse ha roto las reglas del juego
mediante el empleo de una estrategia sumamente ingeniosa y eficaz: usa la API JNI de
Java (Java Native Interface, interfaz nativa de Java). JNI permite que los programas en
Java llamen a mtodos nativos (mtodos propios de la plataforma, generalmente escritos
en C o C++) y que reciban los resultados que stos devuelven. Cuando se compila un
archivo con cdigo JNI-C (cdigo en C donde se implementan mtodos declarados de
tipo JNI), se genera una biblioteca compartida en Windows, una DLL o biblioteca de
enlace dinmico, que permite acceder desde Java a los mtodos declarados en el
cdigo JNI-C.
Para ilustrar cmo se trabaja con JNI, considero aqu el ejemplo de un mtodo
nativo que calcula nmeros de Fibonacci.
En primer lugar, el mtodo nativo se declara en una clase llamada MetodoNativo:
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 6 de 114

public class MetodoNativo {

// declaracin Java del mtodo
public native int fibonacci(int n);

// Carga la biblioteca compartida llamada native.
static {
System.loadLibrary("native");
}

}

En segundo lugar, se compila la clase anterior y, luego, se usa la herramienta javah
de la siguiente forma (omito cualquier consideracin sobre el CLASSPATH):

javah jni MetodoNativo

Con el paso anterior, se crea un archivo MetodoNativo.h que contiene lo siguiente:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MetodoNativo */

#ifndef _Included_MetodoNativo
#define _Included_MetodoNativo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: MetodoNativo
* Method: fibonacci
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_MetodoNativo_fibonacci
(JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif


En tercer lugar, la implementacin en C del mtodo fibonacci() se guarda en un
archivo ImplementacionMetodoNativo.c:

#include <jni.h>
#include MetodoNativo.h

/* implementacin en C de la funcin que calcula el nesimo nmero de Fibonacci */
int fibonacci(int n) {
if (n <= 1)
return 0;
if (n == 2)
return 1;

Declaracin del mtodo Java_MetodoNativo_fibonacci().
El argumento JNIEnv* es un puntero al entorno de
ejecucin del mtodo.
El argumento jobject es una referencia a la clase donde se
especifica el mtodo (MetodoNativo.java)
El argumento jint es el tipo C que corresponde al tipo
Java int, declarado como tipo de retorno del mtodo
fibonacci ().
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 7 de 114
return (fibonacci(n-1) + fibonacci(n 2));
}

/* implementacin de Java_MetodoNativo_fibonacci() */
JNIEXPORT jint JNICALL
Java_MetodoNativo_fibonacci(JNIEnv *env, jobject obj, jint n) {
return fibonacci(n);
}






Por ltimo, el archivo anterior se compila con un compilador de C o C++, que crear
un biblioteca compartida (en Windows, una DLL). A partir de ese momento, el mtodo
nativo fibonacci() podr usarse desde cualquier clase de Java.


La tcnica que usa SWT para llamar mediante JNI a las API grficas de cada
sistema operativo (escritas en C o C++) consiste en establecer, siempre que sea posible,
una correspondencia uno a uno entre los mtodos en Java de cada widget SWT y las
llamadas a la API grfica propia de cada sistema operativo. Ms adelante, veremos
cdigo JNI-C de SWT donde se aprecia esa correspondencia.
Las razones por las que SWT se basa en dicha estrategia son tres: eficacia,
velocidad e integracin con la plataforma. Un widget SWT llama directamente al gestor
de ventanas especfico de la plataforma; as se evita que Java tenga que enviar,
mediante AWT, las interfaces en forma de mapas de bits. Con SWT se logra una
integracin casi completa con cada plataforma. No olvidemos que la integracin con la
plataforma no se reduce a la apariencia y la sensacin (L&F): caractersticas como
copiar y pegar o arrastrar y soltar son automticas si se usa el SWT, pero no lo son
tanto si se usa Swing. Pese al tiempo transcurrido desde que salieron las primeras
versiones de Swing, an existen acciones que no producen en algunas plataformas los
resultados que esperara el usuario habituado a stas.
Tal es la integracin de SWT con la plataforma, que refleja inmediatamente los
cambios en la apariencia y sensacin de la interfaz de usuario del sistema operativo
subyacente. As, un cambio de piel (skin) de Windows XP provocar que todas las
interfaces de usuario construidas con componentes SWT cambien al instante su
apariencia y sensacin. Una piel o skin es un conjunto de grficos que incluye todas las
piezas necesarias para cambiar el aspecto y sensacin de la interfaz grfica. Los grficos
pueden incluir imgenes para botones, barras, mens, etc. Skinning es la accin de
aplicar una piel. Cuando se aplica una piel a Windows, se altera su apariencia y
sensacin: cambian los colores, los botones, etc. (El trmino skinning se us
originalmente en el videojuego Quake, juego tremendamente popular por su carcter
intimista y conciliador. Para dar variedad al juego se inventaron varias pieles, que
permitan al usuario cargar una serie de grficos que cambiaban la apariencia del
personaje principal, un pacfico y sosegado ciudadano.)
La integracin no se detiene en la apariencia y la sensacin de Windows: SWT
permite trabajar con los objetos binarios reutilizables de Microsoft (COM). De hecho, con
unas pocas llamadas a mtodos SWT se puede incluir controles ActiveX y documentos
OLE en las aplicaciones SWT.


La declaracin del mtodo Java_MetodoNativo_fibonacci() en
ImplementacionMetodoNativo.c debe coincidir con la del mtodo
Java_MetodoNativo_fibonacci() en MetodoNativo.h.
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 8 de 114




































Figura 14. Bloc de notas visto con distintas pieles de Windows. Se ha utilizado
la herramienta WindowBlinds 3, disponible en http://www.windowblinds.net



SWT usa los widgets propios de cada plataforma siempre que sea posible, excepto
cuando uno no existe en todas las plataformas. En ese caso, SWT lo simula en las
plataformas que no cuentan con l. Dicho de otro modo: SWT usa para los widgets un
enfoque basado en el mnimo comn denominador. Por ejemplo, Motif no proporciona
por omisin un widget de tipo rbol; consecuentemente, el SWT proporciona un widget
rbol con la misma API que la implementacin propia de Windows. Ningn usuario de
Motif notar nada raro cuando use un componente SWT rbol: como ste no existe de
serie en Motif, el usuario carecer de ideas preconcebidas sobre cmo debe comportarse
(salvo que provenga de Windows). A diferencia de AWT, SWT proporciona todos los
controles que se suponen imprescindibles en cualquier interfaz grfica moderna.
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 9 de 114
Una vez obtenida la correspondencia uno a uno entre los mtodos en Java y los
mtodos propios de la API grfica de la plataforma, el desarrollador puede olvidarse del
cdigo JNI-C y de los detalles de bajo nivel del sistema operativo, y limitarse a utilizar los
mtodos pblicos que proporcionan las clases de SWT. Por as decirlo, simplificando un
poco, SWT encapsula de modo transparente el sistema operativo mediante JNI,
permitiendo as utilizar todas las caractersticas de los widgets propios de cada
plataforma. Acta, en definitiva, como una fina capa entre Java y las bibliotecas de la API
grfica especfica de cada SO. En comparacin con Swing, SWT evita el uso de una
capa gruesa y ralentizadora como la de AWT (vese la figura 15).

Casi todo el cdigo de las clases SWT se limita a actuar como puente entre el
mundo de Java y el de la plataforma: excepto en el caso de los componentes SWT sin
equivalente en la plataforma, apenas se almacena informacin sobre los componentes
SWT. No hace falta mucho ms: SWT usa, siempre que puede, la informacin que
proporciona la API grfica de cada plataforma.
Cualquier aplicacin escrita en Java podra utilizar la JNI para establecer una
correspondencia entre los mtodos Java y las capacidades grficas propias de la
plataforma usada. La ventaja de usar SWT radica en que evita a los programadores
escribir su propio cdigo JNI (tarea que, desde luego, dista mucho de ser trivial y
requiere un buen conocimiento de la plataforma con la cual se trabaja).





























Fig. 15. Funcionamiento interno de los dos componentes grficos


Componente
grfico Swing
AWT
Biblioteca
grfica del SO
Swing
Componente
grfico SWT
Biblioteca
grfica del SO
JNI-C
SWT
Miguel ngel Abin, marzo de 2005
escrito en C escrita en C escrito en Java
escrito en Java escrita en C
r
FUNCIONAMIENTO INTERNO DE SWING y SWT

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 10 de 114
Para ver cmo funcionan en SWT los mtodos JNI, podemos considerar el mtodo
setMenu() de la clase Java OS (clase que representa el sistema operativo de la
plataforma y que forma parte de SWT):

public static final native boolean SetMenu (int hWnd, int hMenu);

Este mtodo asigna un men a una ventana. La palabra reservada native indica al
compilador de Java dos cosas: a) la implementacin del cdigo no est escrita en Java;
b) la implementacin se guarda en un archivo (os.c) que no es el de la clase OS
(os.java). En Windows, el cdigo JNI-C correspondiente al mtodo setFocus() es


JNIEXPORT jboolean JNICALL OS_NATIVE(SetMenu)
(JNIEnv *env, jclass that, jint arg0, jint arg1) {

jboolean rc = 0;
OS_NATIVE_ENTER(env, that, SetMenu_FUNC);
rc = (jboolean)SetMenu((HWND)arg0, (HMENU)arg1);
OS_NATIVE_EXIT(env, that, SetMenu_FUNC);
return rc;

}

Como puede verse, la implementacin en Java del mtodo SetMenu() de la clase
OS llama a un mtodo del sistema operativo tambin llamado SetMenu(). (Tal como se
adelant, hay una relacin uno a uno entre los mtodos de SWT y los mtodos grficos
de la plataforma.)
Cada plataforma con una implementacin del SWT tiene una biblioteca compartida
(en Windows, una biblioteca dinmica o DLL) y uno o ms archivos JAR. La biblioteca
compartida, especfica de cada plataforma, resulta de compilar el cdigo JNI-C que
establece una correspondencia uno a uno entre los mtodos Java y los mtodos de la
API grfica propia del SO. En Windows, esta biblioteca contiene, entre otro mucho
cdigo, el cdigo mquina resultante de compilar el cdigo JNI-C del mtodo setMenu()
que se ha usado antes como ejemplo.
Los archivos JAR contienen las clases Java de SWT Button, Tree, List, Text,
Label, etc., que llaman a los mtodos JNI-C correspondientes (los cuales, a su vez,
llaman a los mtodos nativos de la plataforma). Estas clases comunes, por tener las
mismas declaraciones de sus mtodos pblicos para todas las plataformas,
permiten que el cdigo Java que use SWT se ejecute sin necesidad de cambios en
cualquier otra plataforma donde exista una implementacin de SWT. En ese sentido,
SWT resulta a la par transportable y especfico de la plataforma, por contradictorio que
parezca (en SWT, todas las interfaces directas a la API grfica especfica del SO estn
escritas en Java, excepto la de ms bajo nivel). Tal y como dice IBM en su pgina web:
Un importante beneficio de usar SWT es que, una vez se desarrolla una interfaz de
usuario en Linux, es tambin una interfaz de primera clase cuando se aplica a Windows.
Lo inverso tambin es cierto.


Un ejemplo completo aclarar el porqu del contradictorio carcter del SWT:
consideremos un widget SWT Button, subclase de la clase abstracta Control, y
supongamos que trabajamos con implementaciones de SWT en Windows y Solaris
(olvidemos temporalmente que hay ms plataformas).
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 11 de 114
En Windows, la clase Button tiene el siguiente cdigo (por brevedad, omito todos los
comentarios, salvo el de copyright, y algunos de los mtodos):


package org.eclipse.swt.widgets;

/*
* Copyright (c) 2000, 2002 IBM Corp. All rights reserved.
* This file is made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*/

import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.events.*;


public class Button extends Control {
Image image;
static final int ButtonProc;
static final TCHAR ButtonClass = new TCHAR (0,"BUTTON", true);
static final int CheckWidth, CheckHeight;
static {
int hBitmap = OS.LoadBitmap (0, OS.OBM_CHECKBOXES);
if (hBitmap == 0) {
CheckWidth = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CXSMICON :
OS.SM_CXVSCROLL);
CheckHeight = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CYSMICON :
OS.SM_CYVSCROLL);
} else {
BITMAP bitmap = new BITMAP ();
OS.GetObject (hBitmap, BITMAP.sizeof, bitmap);
OS.DeleteObject (hBitmap);
CheckWidth = bitmap.bmWidth / 4;
CheckHeight = bitmap.bmHeight / 3;
}
WNDCLASS lpWndClass = new WNDCLASS ();
OS.GetClassInfo (0, ButtonClass, lpWndClass);
ButtonProc = lpWndClass.lpfnWndProc;
}

public Button (Composite parent, int style) {
super (parent, checkStyle (style));
}

public void addSelectionListener (SelectionListener listener) {
checkWidget ();
if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
TypedListener typedListener = new TypedListener (listener);
addListener (SWT.Selection,typedListener);
addListener (SWT.DefaultSelection,typedListener);
}

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 12 de 114
int callWindowProc (int msg, int wParam, int lParam) {
if (handle == 0) return 0;
return OS.CallWindowProc (ButtonProc, handle, msg, wParam, lParam);
}

void click () {
OS.SendMessage (handle, OS.BM_CLICK, 0, 0);
}

public Point computeSize (int wHint, int hHint, boolean changed) {
checkWidget ();
int border = getBorderWidth ();
int width = border * 2, height = border * 2;
if ((style & SWT.ARROW) != 0) {
if ((style & (SWT.UP | SWT.DOWN)) != 0) {
width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
height += OS.GetSystemMetrics (OS.SM_CYVSCROLL);
} else {
width += OS.GetSystemMetrics (OS.SM_CXHSCROLL);
height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
}
if (wHint != SWT.DEFAULT) width = wHint + (border * 2);
if (hHint != SWT.DEFAULT) height = hHint + (border * 2);
return new Point (width, height);
}
int extra = 0;
int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
if ((bits & (OS.BS_BITMAP | OS.BS_ICON)) == 0) {
int oldFont = 0;
int hDC = OS.GetDC (handle);
int newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
TEXTMETRIC lptm = new TEXTMETRIC ();
OS.GetTextMetrics (hDC, lptm);
int length = OS.GetWindowTextLength (handle);
if (length == 0) {
height += lptm.tmHeight;
} else {
extra = Math.max (8, lptm.tmAveCharWidth);
TCHAR buffer = new TCHAR (getCodePage (), length + 1);
OS.GetWindowText (handle, buffer, buffer.length ());
RECT rect = new RECT ();
int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
OS.DrawText (hDC, buffer, length, rect, flags);
width += rect.right - rect.left;
height += rect.bottom - rect.top;
}
if (newFont != 0) OS.SelectObject (hDC, oldFont);
OS.ReleaseDC (handle, hDC);
} else {
if (image != null) {
Rectangle rect = image.getBounds ();
width = rect.width;
height = rect.height;
extra = 8;
}
}
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 13 de 114
if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
width += CheckWidth + extra;
height = Math.max (height, CheckHeight + 3);
}
if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
width += 10; height += 7;
}
if (wHint != SWT.DEFAULT) width = wHint + (border * 2);
if (hHint != SWT.DEFAULT) height = hHint + (border * 2);
return new Point (width, height);
}

int defaultBackground () {
if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
return OS.GetSysColor (OS.COLOR_BTNFACE);
}
return super.defaultBackground ();
}

int defaultForeground () {
return OS.GetSysColor (OS.COLOR_BTNTEXT);
}

public int getAlignment () {
checkWidget ();
if ((style & SWT.ARROW) != 0) {
if ((style & SWT.UP) != 0) return SWT.UP;
if ((style & SWT.DOWN) != 0) return SWT.DOWN;
if ((style & SWT.LEFT) != 0) return SWT.LEFT;
if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
return SWT.UP;
}
if ((style & SWT.LEFT) != 0) return SWT.LEFT;
if ((style & SWT.CENTER) != 0) return SWT.CENTER;
if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
return SWT.LEFT;
}

String getNameText () {
return getText ();
}

public String getText () {
checkWidget ();
int length = OS.GetWindowTextLength (handle);
if (length == 0) return "";
TCHAR buffer = new TCHAR (getCodePage (), length + 1);
OS.GetWindowText (handle, buffer, length + 1);
return buffer.toString (0, length);
}

public void setText (String string) {
checkWidget ();
if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
int newBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
int oldBits = newBits;
newBits &= ~(OS.BS_BITMAP | OS.BS_ICON);
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 14 de 114
if (newBits != oldBits) {
OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
}
TCHAR buffer = new TCHAR (getCodePage (), string, true);
OS.SetWindowText (handle, buffer);
}

LRESULT WM_GETDLGCODE (int wParam, int lParam) {
LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
if (result != null) return result;
if ((style & SWT.ARROW) != 0) {
return new LRESULT (OS.DLGC_STATIC);
}
return result;
}

LRESULT WM_KILLFOCUS (int wParam, int lParam) {
LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
if ((style & SWT.PUSH) != 0 && getDefault ()) {
menuShell ().setDefaultButton (null, false);
}
return result;
}


}


En Solaris 8, la clase Button presenta este cdigo (por brevedad, omito todos los
comentarios, salvo el de copyright, y algunos de los mtodos):

/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.widgets;


import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.motif.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.events.*;


public class Button extends Control {
String text = "";
Image image, bitmap, disabled;
static final byte [] ARM_AND_ACTIVATE;
static {
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 15 de 114
String name = "ArmAndActivate";
int length = name.length();
char [] unicode = new char [length];
name.getChars (0, length, unicode, 0);
byte [] buffer = new byte [length + 1];
for (int i = 0; i < length; i++) {
buffer[i] = (byte) unicode[i];
}
ARM_AND_ACTIVATE = buffer;
}

public Button (Composite parent, int style) {
super (parent, checkStyle (style));
}

public void addSelectionListener(SelectionListener listener) {
checkWidget();
if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
TypedListener typedListener = new TypedListener(listener);
addListener(SWT.Selection,typedListener);
addListener(SWT.DefaultSelection,typedListener);
}

public Point computeSize (int wHint, int hHint, boolean changed) {
checkWidget();
int border = getBorderWidth ();
int width = border * 2, height = border * 2;
if ((style & SWT.ARROW) != 0) {
width += display.scrolledMarginX;
height += display.scrolledMarginY;
if (wHint != SWT.DEFAULT) width = wHint + (border * 2);
if (hHint != SWT.DEFAULT) height = hHint + (border * 2);
return new Point (width, height);
}
XtWidgetGeometry result = new XtWidgetGeometry ();
result.request_mode = OS.CWWidth | OS.CWHeight;
int [] argList2 = {OS.XmNrecomputeSize, 1};
OS.XtSetValues(handle, argList2, argList2.length / 2);
OS.XtQueryGeometry (handle, null, result);
int [] argList3 = {OS.XmNrecomputeSize, 0};
OS.XtSetValues(handle, argList3, argList3.length / 2);
width += result.width;
height += result.height;
int [] argList = {OS.XmNlabelType, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
if (argList [1] == OS.XmSTRING) {
int [] argList1 = {OS.XmNlabelString, 0};
OS.XtGetValues (handle, argList1, argList1.length / 2);
int xmString = argList1 [1];
if (OS.XmStringEmpty (xmString)) height += getFontHeight (font.handle);
if (xmString != 0) OS.XmStringFree (xmString);
}
if (wHint != SWT.DEFAULT || hHint != SWT.DEFAULT) {
int [] argList4 = new int [] {OS.XmNmarginLeft, 0, OS.XmNmarginRight, 0,
OS.XmNmarginTop, 0, OS.XmNmarginBottom, 0};
OS.XtGetValues (handle, argList4, argList4.length / 2);
if (wHint != SWT.DEFAULT) width = wHint + argList4 [1] + argList4 [3] + (border * 2);
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 16 de 114
if (hHint != SWT.DEFAULT) height = hHint + argList4 [5] + argList4 [7] + (border * 2);
}
return new Point (width, height);
}

public int getAlignment () {
checkWidget();
if ((style & SWT.ARROW) != 0) {
int [] argList = {OS.XmNarrowDirection, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
int direction = argList [1];
if (direction == OS.XmARROW_UP) return SWT.UP;
if (direction == OS.XmARROW_DOWN) return SWT.DOWN;
if (direction == OS.XmARROW_LEFT) return SWT.LEFT;
if (direction == OS.XmARROW_RIGHT) return SWT.RIGHT;
return SWT.UP;
}
int [] argList = {OS.XmNalignment, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
int alignment = argList [1];
if (alignment == OS.XmALIGNMENT_BEGINNING) return SWT.LEFT;
if (alignment == OS.XmALIGNMENT_CENTER) return SWT.CENTER;
if (alignment == OS.XmALIGNMENT_END)return SWT.RIGHT;
return SWT.CENTER;
}
boolean getDefault () {
if ((style & SWT.PUSH) == 0) return false;
return this == menuShell ().defaultButton;
}

String getNameText () {
return getText ();
}

public String getText () {
checkWidget();
if ((style & SWT.ARROW) != 0) return "";
return text;
}

public void setAlignment (int alignment) {
checkWidget();
if ((style & SWT.ARROW) != 0) {
int [] argList = {OS.XmNarrowDirection, OS.XmARROW_UP};
if ((alignment & SWT.UP) != 0) argList [1] = OS.XmARROW_UP;
if ((alignment & SWT.DOWN) != 0) argList [1] = OS.XmARROW_DOWN;
if ((alignment & SWT.LEFT) != 0) argList [1] = OS.XmARROW_LEFT;
if ((alignment & SWT.RIGHT) != 0) argList [1] = OS.XmARROW_RIGHT;
OS.XtSetValues (handle, argList, argList.length / 2);
return;
}
if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
int [] argList = {OS.XmNalignment, OS.XmALIGNMENT_BEGINNING};
if ((alignment & SWT.CENTER) != 0) argList [1] = OS.XmALIGNMENT_CENTER;
if ((alignment & SWT.RIGHT) != 0) argList [1] = OS.XmALIGNMENT_END;
OS.XtSetValues (handle, argList, argList.length / 2);
}
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 17 de 114

public void setText (String string) {
checkWidget();
if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
if ((style & SWT.ARROW) != 0) return;
text = string;
char [] text = new char [string.length ()];
string.getChars (0, text.length, text, 0);
int mnemonic = fixMnemonic (text);
byte [] buffer = Converter.wcsToMbcs (getCodePage (), text, true);
int xmString = OS.XmStringParseText (
buffer,
0,
OS.XmFONTLIST_DEFAULT_TAG,
OS.XmCHARSET_TEXT,
null,
0,
0);
if (xmString == 0) error (SWT.ERROR_CANNOT_SET_TEXT);
if (mnemonic == 0) mnemonic = OS.XK_VoidSymbol;
int [] argList = {
OS.XmNlabelType, OS.XmSTRING,
OS.XmNlabelString, xmString,
OS.XmNmnemonic, mnemonic,
};
OS.XtSetValues (handle, argList, argList.length / 2);
if (xmString != 0) OS.XmStringFree (xmString);
}

int xFocusIn (XFocusChangeEvent xEvent) {
super.xFocusIn (xEvent);
if (handle == 0) return 0;
if ((style & SWT.PUSH) != 0) {
menuShell ().setDefaultButton (this, false);
}
return 0;
}

}


Como puede observarse, la clase Button en Solaris presenta un cdigo muy distinto
del correspondiente a la misma clase en Windows, pero ambas mantienen la misma
declaracin es decir, los mismos argumentos y el mismo tipo de retorno para todos los
mtodos pblicos. Por ejemplo, el mtodo pblico setText() de Button mantiene la misma
declaracin tanto en Solaris como en Windows: public void setText (String string). (Lo
mismo sucede en todas las dems plataformas para las que est disponible SWT.)
En cuanto a la implementacin de los mtodos pblicos, vara completamente de
una a otra cada plataforma. En el caso de setText(), se usan en Windows llamadas a
mtodos como OS.GetWindowLong(), que llama, a su vez, al mtodo GetWindowLong()
de la biblioteca grfica Win32; en Solaris se usan llamadas a mtodos como
OS.XmStringParseText(), que llama, a su vez, al mtodo XmStringParseText() de la
bibliotecas grfica Motif. Tal como se dijo antes, la clase OS representa el sistema
operativo de la plataforma.
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 18 de 114
Los mtodos que no son pblicos gozan de completa libertad en cuanto a
declaracin. Generalmente, no tienen por qu existir en todas las plataformas. Por
ejemplo, no hay un mtodo con una declaracin int callWindowProc(int p0, int p1, int p2)
en la clase Button de Solaris, mtodo que goza de buena salud en Windows.
Como ya se adelant hace unas pginas, que los mtodos pblicos de los widgets
SWT se declaren igual en todas las plataformas causa que el SWT sea transportable. En
el ejemplo de Button, la implementacin de cada mtodo en Solaris no ser transportable
a Windows, y viceversa; pero el cdigo Java que utilice los mtodos pblicos de Button s
lo ser, puesto que ambas plataformas tienen implementaciones del SWT.
Continuando con el ejemplo de setText(), la sentencia miBoton.setText("Soy un
botn SWT") har llamadas en Windows y Solaris, a travs de JNI, a mtodos nativos
completamente diferentes; pero funcionar en ambas plataformas (dando distintas
resultados grficos, claro est). El cdigo Java que llama a SWT no necesita conocer la
implementacin de las clases SWT ni el cdigo JNI-C encargado de llamar a la API
grfica correspondiente. Ms an: si lo hiciera se incumplira el principio de encapsulado,
fundamental en la programacin orientada a objetos.
Las bibliotecas JNI-SWT deben compilarse para cada plataforma, lo cual crea un
archivo con extensin .dll en Windows y otro con extensin .so en Solaris. En la pgina
web de Eclipse se puede descargar el cdigo JNI-C de la biblioteca JNI-SWT para cada
plataforma, as como el cdigo compilado para cada plataforma. Un programa que utilice
SWT emplear las bibliotecas Win32 o MFC (propias de Windows) cuando se ejecuta en
Windows (98/ME/2000/XP), y las bibliotecas de Motif cuando se ejecuta en Solaris.


La correspondencia casi exacta entre los objetos grficos de SWT widgets, tipos
de letra, colores, imgenes y los del sistema operativo hace que el recolector de basura
de Java no sirva para liberar los recursos asociados a esos objetos; pues la tarea natural
del recolector es liberar los recursos asociados a objetos que viven en la mquina
virtual de Java y que ya no se utilizan, no liberar recursos del sistema operativo donde se
ejecuta la MVJ. Por esto, la liberacin de los recursos asociados a objetos SWT debe
establecerla el programador. Por ejemplo, una ventana repleta de controles puede
cerrarse de varias maneras uso cerrar en el sentido de hacerla desaparecer de la vista
del usuario; pero el programador deber llamar explcitamente al mtodo dispose() del
display correspondiente si realmente quiere liberar los recursos de la ventana y de sus
controles. En caso contrario, puede suceder que la aplicacin se cuelgue o funcione muy
lentamente si contiene muchas ventanas que ya no se necesitan y cuyos recursos no se
han liberado. Para evitar fallos de memoria y la disminucin del rendimiento, se
recomienda liberar los recursos asociados a un objeto SWT en cuanto se deje de
necesitarlo.
SWT sigue la estrategia de que liberar los recursos de un control padre conlleva la
liberacin de los recursos de todos los controles hijos. Dicho de otro modo: al llamar al
mtodo dispose() del padre, se llama a cada mtodo dispose() de los hijos.
Mtodos como dispose() resultan necesarios cuando se trabaja con componentes
grficos o con sockets, pues llaman a mtodos nativos que saben cmo liberar los
recursos asociados del sistema operativo. Si desea ms informacin sobre el uso de
dispose() con sockets, puede consultar el apartado 3.3 del tutorial java.net y java.nio.
Cmo hacer un chat en Java, http://www.javahispano.org/tutorials.item.action?id=7).
Esas llamadas a mtodos nativos son inevitables, ya que los componentes grficos de
peso pesado y las conexiones de red dependen por completo del SO.


http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 19 de 114
En el caso de los objetos SWT correspondientes a colores (Color), imgenes
(Image) y tipos de letra (Font), el programador debe ser cuidadoso. De un lado, dichos
objetos carecen de objetos padre. De otro, los recursos que consumen no se liberan
cuando se llama al mtodo dispose() de los componentes donde se usan tales objetos.
Estas dos caractersticas no se deben a ningn error de diseo. Antes al contrario:
responden a un entendimiento cabal de la naturaleza de esos objetos. Si, por ejemplo,
las imgenes tuvieran que crearse asociadas a componentes padre (ventanas, botones,
listas, mens...), todos los componentes con una misma imagen necesitaran sendas
instancias de la clase Image. Esta situacin sera muy incmoda para el programador
(quien tendra que escribir la instaciacin una y otra vez) y para el sistema operativo
(imaginmoslo como un grun que se preguntara por qu demonios le obligan a
mantener tantos objetos Image, cuando en realidad corresponden a un misma imagen, y
que amenazara con colgar el sistema como protesta). A consecuencia de la libertad de
la que gozan esos objetos, resulta obligatorio que no se destruyan cuando se destruyen
los componentes que los usan. Si varios componentes usaran un mismo objeto Image y
al destruir uno se destruyera el objeto Image, en qu estado se encontraran los
restantes componentes? Sin imagen, que ya estara en el cubo de la basura.
Como los objetos Color, Image y Font no se destruyen cuando desaparecen los
componentes que los usan, el programador debe liberarlos explcitamente llamando a
dispose(). En el apartado dedicado a JFace veremos cmo se puede simplificar la
liberacin de los recursos que consumen estos objetos.


Toda la interfaz grfica de Eclipse se basa en SWT. Ahora bien, ello no significa que
este componente grfico se pueda usar slo con Eclipse: las bibliotecas SWT se pueden
descargar independientemente de Eclipse y pueden usarse para construir aplicaciones
independientes. En la ltima versin de Eclipse (3.0.2), lanzada el 11 de marzo de 2005
(la versin 3.1M5a, an no definitiva, sali en febrero de este ao), los componentes
SWT y JFace se hallan disponibles para las siguientes plataformas:

Windows 98/ME/2000/XP

Windows PocketPC 2002 (Strong ARM)

Linux (x86/Motif)

Linux (x86/GTK 2)

Linux (AMD 64/GTK 2)

Linux (IA 64/GTK 2)

Solaris 8 (SPARC/Motif)

AIX (PPC/Motif)

HP-UX (HP9000/Motif)

HP-UX (IA 64/Motif)


Como la licencia de SWT coincide con la de Eclipse (Common Public License, ya
explicada en el primer artculo de esta serie:
http://www.javahispano.org/articles.article.action?id=75), cualquier programador puede
usar este componente sin pagar regalas. Para ello, debe configurar el CLASSPATH de
su aplicacin para que incluya el archivo jar del SWT (dependiendo de la plataforma,
pueden ser varios) y la propiedad java.library.path para que incluya la biblioteca
compartida JNI-SWT propia de la plataforma usada (esta biblioteca resulta de compilar
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 20 de 114
todo el cdigo JNI-C que usan las clases SWT; en Windows tiene un nombre del tipo swt-
win32.xxxx.dll).


En las siguientes figuras se muestra el aspecto de Eclipse en varias plataformas.
Como Eclipse usa exclusivamente componentes SWT, su aspecto cambia en cada
plataforma.











































Fig. 16. SWT en accin: Eclipse en Linux-Motif. Extrado de la documentacin
oficial de Eclipse.

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 21 de 114












































Fig. 17. SWT en accin: Eclipse en Linux/Gnome2

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 22 de 114









































Fig. 18. SWT en accin: Eclipse en Windows XP


http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 23 de 114









































Fig. 19. SWT en accin: Eclipse en Mac OS X


El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 24 de 114

15. Ejemplos de uso del Standard Widget Tool (SWT)

Esta seccin no pretende, ni mucho menos, ser una introduccin completa a SWT.
Sus objetivos son mucho ms modestos: explicar qu se necesita para programar con
este componente grfico, presentar algunos aspectos de su uso y dar unos cuantos
ejemplos representativos de cmo se usan los widgets SWT. Dar una explicacin
completa del funcionamiento de SWT queda fuera de las metas de esta serie de artculos
(definidas en el primero, http://www.javahispano.org/articles.article.action?id=75).

Usando SWT, el tpico programa HolaMundo quedara as:




import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;


public class Saludos {

public static void main(String args[]){
// Se crea un display que servir como contenedor para el shell.
Display display = new Display();

// Se coloca el display dentro del shell.
Shell shell = new Shell(display);

// Se establece el tamao y el texto del shell.
shell.setSize(250, 120);
shell.setText("Mi primera aplicacin con SWT");

// Se crea una etiqueta centrada en la ventana y se le da un texto.
Label etiqueta= new Label(shell, SWT.CENTER);
etiqueta.setText("Saludos a los lectores de javaHispano");
etiqueta.setBounds(shell.getClientArea());

// Se muestra el shell; un shell es invisible salvo que se llame a open().
shell.open ();

// Se entra en un bucle para leer y enviar los sucesos del usuario.
// Si no hay ningn suceso que tratar, el mtodo sleep() hace que el
// programa espere el suceso siguiente sin consumir ciclos de CPU.
// Se sale del bucle cuando el usuario cierra el shell.
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}

// Se cierra el display y se liberan los recursos que empleaba del sistema operativo
// Siempre es conveniente liberar explcitamente los recursos
// que no se van a necesitar. En este caso no es necesario llamar a dispose(),
// pues si se llega a aqu es porque el programa va a terminar, lo que implica que
// se liberarn los recursos asociados; pero es una buena prctica acostumbrarse
// a hacerlo.
Ejemplo 1: Saludos.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 25 de 114
display.dispose ();
}

}


Para que un programa con SWT pueda compilarse y ejecutarse en el entorno de
Eclipse, se necesitan dos pasos previos.

El primero consiste en indicar al compilador dnde est el cdigo Java de SWT; es
decir, dnde se encuentran las clases SWT. stas se almacenan en el archivo swt.jar.
Para indicar a Eclipse dnde debe buscar el archivo swt.jar hay que seguir varios pasos.
En primer lugar, hay que apretar, sobre el nombre del proyecto de Java, el botn derecho
del ratn (vase la figura 20). A continuacin, hay que seleccionar la opcin Properties.
En la ventana que aparece debe seleccionarse Java Build Path (panel de la derecha) y
la pestaa Libraries (vase la figura 21). Acto seguido, debe incluirse swt.jar con el
botn Add External JARs... (vase la figura 22).
Segn el FAQ ms actualizado de Eclipse
(http://www.eclipse.org/eclipse/faq/eclipse-faq.html), swt.jar se encuentra dependiendo
de la plataforma en

win32: INSTALLDIR\eclipse\plugins\org.eclipse.swt.win32_3.0.1\ws\win32\

Linux GTK: INSTALLDIR/eclipse/plugins/org.eclipse.swt.gtk_3.0.1/ws/gtk/

Linux Motif: INSTALLDIR/eclipse/plugins/org.eclipse.swt.motif_3.0.1/ws/motif/

Photon QNX: INSTALLDIR/eclipse/plugins/org.eclipse.swt.photon_3.0.1/ws/photon/

Mac OS X: INSTALLDIR/eclipse/plugins/org.eclipse.swt.carbon_3.0.1/ws/carbon/


INSTALLDIR es el directorio donde se ha instalado Eclipse. Dependiendo de la
versin de SWT que se use, cambiar el nmero separado por puntos que aparece en
las rutas (en vez de 3.0.1, podra ser 3.1.0, por ejemplo).
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 26 de 114





































Figura 20. Ntese que la vista que se usa es la de paquetes

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 27 de 114

























Figura 21. Hay que apretar el botn Add External JARs...
























Figura 22. Hay que seleccionar el archivo swt.jar (en otra plataforma, se encontrar
en otro directorio)



El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 28 de 114
El segundo paso que se requiere para ejecutar el programa consiste en indicar a
Eclipse dnde est la biblioteca compartida que requiere swt.jar. Una manera consiste en
introducir, cuando se arranca la mquina virtual de Java, la ubicacin de la biblioteca
compartida como argumento de ejecucin. Para ello, basta elegir el men Run, escoger
Run... (vase la figura 23), elegir la pestaa Arguments en la parte derecha de la
pantalla e introducir en el rea de texto VM arguments lo siguiente (vase la figura 24a):

-Djava.library.path=<directorio que contiene la biblioteca compartida para SWT>

Tal y como suceda con swt.jar, la biblioteca se encontrar en una ubicacin dependiente
de la plataforma. Segn el FAQ de Eclipse, las ubicaciones sern del estilo (la lista de
plataformas no es exhaustiva):

Windows: INSTALLDIR\eclipse\plugins\org.eclipse.swt.win32_3.0.1\os\win32\x86

Linux GTK: INSTALLDIR/eclipse/plugins/org.eclipse.swt.gtk_3.0.1/os/linux/x86

Linux Motif: INSTALLDIR/eclipse/plugins/org.eclipse.swt.motif_3.0.1/os/linux/x86

Photon QNX: INSTALLDIR/eclipse/plugins/org.eclipse.swt.photon_3.0.1/os/qnx/x86

Mac OS X: INSTALLDIR/eclipse/plugins/org.eclipse.swt.carbon_3.0.1/os/macosx/ppc





























Figura 23. Se escoge Run...


http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 29 de 114





























Figura 24a. La versin de Eclipse de la captura de pantalla es la 3.1M4

El nombre exacto de la biblioteca JNISWT vara en cada versin de Eclipse (a
veces, tambin vara con la plataforma, aunque no vare la versin). En la versin 3.1M3
de Eclipse para Windows 98/ME/2000/XP, el nombre de la biblioteca es swt-win-32-
3111.dll (vase la figura 24b).
















Figura 24b. Biblioteca JNI-SWT correspondiente a Eclipse 3.1M3



El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 30 de 114
Completados todos los pasos anteriores, la ejecucin de la clase Saludos en
Windows XP producir una ventana similar a la de la figura 25a.













Figura 25a. Resultado de ejecutar la clase Saludos














Figura 25b. Manteniendo en ejecucin la clase Saludos, la ventana cambia de
aspecto cuando se cambia el estilo de Windows XP por el clsico de Windows.



Como ya se seal en el apartado anterior, para desarrollar o ejecutar aplicaciones
SWT no se necesita el entorno de desarrollo Eclipse. Para ejecutar en Windows una
aplicacin SWT sin Eclipse, hay que aadir el archivo swt.jar al CLASSPATH e incluir la
biblioteca dinmica swt-win-32-xxxx.dll en el java.library.path. Tanto swt.jar como la DLL
se pueden descargar sin el resto de Eclipse.
Por ejemplo, en el caso de que ambos archivos estn en C:\SWT, la siguiente orden
compilar la aplicacin Saludos desde la lnea de rdenes:

javac -classpath C:\SWT\swt.jar Saludos.java

La siguiente orden ejecutar Saludos desde la lnea de rdenes:

java -classpath C:\SWT\swt.jar -Djava.library.path=C:\SWT Saludos

Para el resto de las plataformas, el proceso resulta similar a ste.



http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 31 de 114









La clase Saludos, si bien muy simple, alberga la estructura de cualquier aplicacin SWT:

1) Se crea un objeto Display.

2) Se crea un objeto Shell que sirve como ventana principal de la
aplicacin.

3) Se crean dentro del shell los widgets (componentes grficos) que se
deseen.

4) Se configuran los tamaos de los widgets (normalmente, en este paso
se registran los sucesos a los cuales atendern los widgets).

5) Se abre la ventana del shell.

6) Se entra en un bucle donde se comprueban los sucesos que se van
produciendo.

7) Se cierra el objeto Display y se liberan los recursos asociados.


La clase Display (contenida en el paquete org.eclipse.swt.widgets) acta como
puente entre el SWT y las operaciones del sistema de interfaz grfica de la plataforma.
Segn la documentacin de esta clase, su principal funcin es implementar el bucle de
sucesos de SWT mediante el modelo de sucesos de la plataforma. Adems, proporciona
mtodos para acceder a informacin sobre el sistema operativo y para controlar y
gestionar los recursos del sistema donde se ejecuta SWT. En resumen, un objeto Display
se comporta como un intermediario entre la interfaz de usuario y el componente o
componentes que lo implementan en una plataforma.
Por lo general, el programador salvo que escriba aplicaciones multihilo debe
preocuparse solamente de: a) crear un objeto Display antes de crear ninguna ventana; y
b) cerrarlo cuando ya no se necesite.
El mtodo dispose() se encarga de liberar los recursos que el display consuma del
sistema de ventanas especfico de la plataforma (memoria, punteros). Al llamarlo, se
eliminan todos los shells que tena el display.


Las instancias de la clase Shell (contenida en el paquete org.eclipse.swt.widgets)
vienen a ser ventanas gestionadas por el gestor de ventanas propio de la plataforma.
Cuando el usuario mueve o cambia el tamao de una ventana, SWT pasa el tratamiento
de estas acciones a la API grfica del SO. Esta clase tiene varios constructores que
admiten como argumento un objeto shell: con ellos se pueden generan shells de dilogo
o secundarios (shell significa cscara).
El mtodo dispose() de esta clase acta de forma similar al mtodo homnimo de la
clase Display.


Nota: La manera ms sencilla de evitar la configuracin del
CLASSPATH y del argumento -Djava.library.path desde la lnea de
rdenes es colocar el fichero o los ficheros JAR en el directorio lib/ext
del JRE (Java Runtime Environment), y la biblioteca compartida JNI-
SWT en el directorio bin del JRE.

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 32 de 114
Si comparamos SWT con Swing, los componentes de Swing seran equivalentes a
los widgets del SWT, y los marcos y ventanas (frames and windows), a los shells.


En el constructor de la etiqueta habr visto que hay un segundo argumento en el
constructor:

Label etiqueta= new Label(shell, SWT.CENTER);

SWT.CENTER (o CENTER, por abreviar) es un estilo. Los estilos son constantes
enteras que se emplean para establecer el aspecto y comportamiento de los widgets. En
este ejemplo, el estilo CENTER indica que el texto de la etiqueta debe centrarse respecto
a ella. Todos los estilos estn definidos en la clase org.eclipse.swt.SWT. Una vez se
asigna un estilo a un widget, aqul no puede cambiarse. La clase Shell que acabamos de
ver admite los siguientes estilos: BORDER, H_SCROLL, V_SCROLL, CLOSE, MIN,
MAX, RESIZE, TITLE, SHELL_TRIM y DIALOG_TRIM.
Un widget puede aceptar varios estilos:

Label etiqueta = new Label(shell, SWT.CENTER | SWT.HORIZONTAL | SWT.SEPARATOR);

















Figura 26. Ejemplo de distintos estilos de un mensaje de dilogo


El paquete org.eclipse.swt.widgets incluye un conjunto de widgets o componentes
SWT formado, entre otros, por estos elementos:

- Button. SWT no tiene una clase individual para un botn redondo, de flecha, etc.:
todos son instancias de Button.

- Label. Una etiqueta muestra una cadena de texto, una imagen o una lnea vertical
u horizontal separadora.

- Text. Muestra un texto susceptible de ser editado, ya sea de una lnea o de varias.

- Slider. Control que representa un intervalo de valores numricos.

- ProgressBar. Control que indica el porcentaje cumplido de una tarea (descargar
un archivo, cargar una aplicacin, etc.).

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 33 de 114
- Combo. Control que permite seleccionar un valor de una lista desplegable o
introducir directamente el valor deseado.

- List. Control que permite seleccionar (de forma simple o mltiple) elementos de
una lista de cadenas de texto.

- Composite. Control que permite agrupar otros controles. Equivaldra a un
contenedor (container) de Swing.

- Group. Control formado a partir de un Composite con ttulo y borde.

- Canvas. Control que permite operaciones grficas de todo tipo (dibujar un
octgono azul, por ejemplo)

- Menu. Control que contiene elementos seleccionables de tipo men.

- MenuItem. Elemento seleccionable que representa un elemento en un men.

- Table. Control seleccionable que muestra una lista de elementos de una tabla.

- TableColumn. Elemento seleccionable que representa una columna de una tabla.

- TableItem. Objeto seleccionable que representa un elemento de una tabla.

- ToolBar. Control compuesto que permite disear elementos de barras de
herramientas.

- ToolItem. Objeto seleccionable que representa un elemento de una barra de
herramientas.

- Tree. Control seleccionable en forma de rbol que muestra una lista jerrquica de
elementos.

- TreeItem. Objeto que representa una jerarqua de objetos en un control Tree.

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 34 de 114
































Figura 27. Funcionamiento interno de SWT



Antes de dar algunos ejemplos del uso de estos componentes, creo pertinente
incluir aqu algunos comentarios sobre el tratamiento de sucesos en SWT. El tratamiento
de los sucesos en el SWT resulta muy similar al de Swing y al de AWT: a cada widget se
le aade una clase Listener mediante un mtodo del estilo addXXXListener(), cuyo
argumento es la clase que implementa la correspondiente interfaz de tipo Listener.
Asimismo, existen clases adaptadoras clases que implementan por omisin las
interfaces Listener, de manera que el programador necesite escribir slo el cdigo de
los sucesos que verdaderamente le interesan.








Plataforma
Display Shell
Composite
Widget
Widget
Widget
Widget
Bibliotecas
grficas
JNI
FUNCIONAMIENTO INTERNO DEL COMPONENTE
SWT
Miguel ngel Abin, 2005

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 35 de 114
























Nota: Si no tiene experiencia con el tratamiento de sucesos en
Swing o AWT, le resultar til saber lo siguiente:

1) Cada suceso se asocia con una accin del usuario (pulsar una
tecla, mover el ratn...).

2) Cada suceso tiene asociado una interfaz de Java llamada
Listener (oyente).

3) Es tarea del programador crear una clase Listener que
implemente la interfaz Listener correspondiente y en la que se
especifique qu respuesta debe darse cuando se produzca un suceso.

4) Para aadir una clase Listener a un control se usan mtodos
del estilo addXXXListener().

5) Las clases Adapters (adaptadoras) son clases que
implementan las interfaces Listener con una implementacin por
omisin para cada mtodo. En vez de una clase Listener, el
programador puede asociar un Adapter a un componente, de manera
que slo tenga que implementar los mtodos que necesite. Por
ejemplo, a la interfaz FocusListener le corresponde la clase
adaptadora FocusAdapter.
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 36 de 114


Figura 28. Tabla con los sucesos y las clases Listener ms importantes


http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 37 de 114

He aqu un ejemplo de cdigo para tratar sucesos (corresponde a un componente
SWT de tipo Button):





import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;

/**
* Esta clase genera un botn que inicialmente permanece apretado.
*
* La clase Button admite los siguientes estilos: BORDER, CHECK, PUSH,
* RADIO, TOGGLE, FLAT, ARROW (con UP, DOWN), LEFT, RIGHT y CENTER.
*
* BORDER crea un botn con borde.
* CHECK crea un botn de casilla de verificacin.
* PUSH crea un botn estndar (valor por omisin).
* RADIO crea un botn de opcin.
* TOGGLE crea un botn que mantiene su estado pulsado o no pulsado.
* FLAT crea un botn sin efectos de relieve 3D (plano).
* ARROW crea un botn en forma de flecha (UP y DOWN marcan el sentido de sta).
* LEFT, RIGHT, CENTER alinean el texto asociado al botn.
*/

public class EjemploBoton {

public static void main(String args[]) {
// Se crea un display que servir como contenedor para el shell.
Display display = new Display();

// Se coloca el display dentro del shell.
Shell shell = new Shell(display);

// Se establece el tamao y el texto del shell.
shell.setSize(250, 120);
shell.setText("Ventana hecha con el SWT");

// Se establece el tipo, eltamao y el texto del botn.
// Un botn TOGGLE permanece presionado tras pulsarlo, hasta que se vuelve a
// pulsar.
Button boton = new Button(shell, SWT.TOGGLE);
boton.setSize(150, 50);
boton.setText("Soy un botn de tipo TOGGLE");

// Tratamiento de sucesos: muy similar a como se hace en Swing.
// Ntese que hay que implementar todos los mtodos de cada interfaz
// Listener.
boton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
System.out.println("Se ha seleccionado el botn");
}
public void widgetDefaultSelected(SelectionEvent e) {
System.out.println("Se ha seleccionado el botn");
Ejemplo 2: EjemploBoton.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 38 de 114
}
});

boton.addMouseListener(new MouseListener() {
public void mouseDown(MouseEvent e) {
System.out.println("Se ha movido el ratn hacia abajo");
}
public void mouseUp(MouseEvent e) {
System.out.println("Se ha movido el ratn hacia arriba");
}
public void mouseDoubleClick(MouseEvent e) {
System.out.println("Se ha hecho doble click en el botn");
}
});


// Se muestra el shell; un shell es invisible salvo que se llame a open().
shell.open();

// Se entra en un bucle para leer y enviar los sucesos del usuario.
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}

// Se cierra el display y se liberan los recursos del sistema operativo
// asociados.
display.dispose();
}

}


















Figura 29. Resultado de ejecutar la clase EjemploBoton


http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 39 de 114

Si en la clase EjemploBoton interesara procesar slo el suceso Selection, sera
mucho ms rpido usar la correspondiente clase adaptadora:

// Tratamiento del suceso Selection con adaptadores.
boton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
System.out.println("Se ha seleccionado el botn");
}
});


El ejemplo anterior quedara as:




import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;

public class EjemploBoton2 {

public static void main(String args[]){
// Se crea un display que servir como contenedor para el shell.
Display display = new Display();

// Se coloca el display dentro del shell.
Shell shell = new Shell(display);

// Se establece el tamao y el texto del shell.
shell.setSize(250, 120);
shell.setText("Ventana hecha con el SWT");

// Se establece el tipo, el tamao y el texto del botn.
Button boton = new Button(shell, SWT.TOGGLE);
boton.setSize(150, 50);
boton.setText("Soy un botn de tipo TOGGLE");

// Tratamiento del suceso Selection con adaptadores.
boton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
System.out.println("Se ha seleccionado el botn");
}
});

shell.open ();

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

display.dispose ();
}
Ejemplo 3: EjemploBoton2.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 40 de 114

}


Con todo, existe una relevante diferencia entre el SWT y Swing: un programa que
use SWT y no disponga de algn bucle que se encargue de leer y procesar los sucesos
del sistema operativo terminar en cuanto se llegue al final del mtodo main(). Por
ejemplo, el usuario slo ver una ventana que se cierra al momento si ejecuta las clases
anteriores sin este cdigo (si su mquina es lo bastante rpida, puede que ni siquiera
llegue a ver la ventana):

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

Asociada a esta diferencia entre SWT y Swing, est el hecho de que los sucesos de
SWT slo se entregan al programa (y, en consecuencia, slo pueden procesarse)
cuando se llama a un mtodo SWT. En los ejemplos anteriores, el mtodo
readAndDispatch() se encarga de entregar al programa en ejecucin los sucesos
generados por el usuario. Sin l, el comportamiento del botn sera anmalo: no
respondera a las acciones del usuario (defecto, dicho sea de paso, que los usuarios
desprecian).


A continuacin, incluyo unos cuantos ejemplos de uso de los principales controles
SWT. Cuando se especifican coordenadas, hay que tener en cuenta que (0, 0)
corresponde a la esquina superior izquierda, que los puntos situados por debajo del
origen tienen su componente y positiva y que los puntos a la derecha del origen tiene su
componente x positiva.





import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.*;

/**
* Esta clase genera una ventana con una imagen y una barra de mens
* Se necesita incluir el paquete org.eclips.swt.graphics.Image
* para poder trabajar con imgenes en SWT.
*
* La clase Menu acta como un contenedor para los objetos MenuItem.
* La clase Menu admite los siguientes estilos: BAR, DROP_DOWN y POP_UP.
*
* BAR crea una barra de mens.
* DROP_DOWN crea un men desplegable.
* POP_UP crea un men contextual.
*
*
* La clase MenuItem admite los siguientes estilos: CHECK, CASCADE, PUSH, RADIO y
Ejemplo 4: EjemploMenu1.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 41 de 114
* SEPARATOR.
*
* CHECK crea un men de casilla de verificacin.
* CASCADE crea un men en cascada con un submen.
* PUSH crea un elemento estndar de men.
* RADIO crea un men de opcin.
* SEPARATOR crea un separador de elementos de men.
*
*/

public class EjemploMenu1{

public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(200, 200);
shell.setText("Ejemplo 1 de mens");
shell.setImage(new Image(display,"c:\\eclipse.jpg"));

Menu menu = new Menu(shell, SWT.BAR);

shell.setMenuBar(menu);
shell.open();

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

display.dispose();
}

}


















Figura 30. Resultado de ejecutar la clase EjemploMenu1

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 42 de 114




import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Image;

/**
* Esta clase genera una ventana una barra de mens que tiene dos mens con submens.
* Se necesita incluir el paquete org.eclips.swt.graphics.Image
* para poder trabajar con imgenes en SWT.
*
*/


public class EjemploMenu2 {

public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 300);
shell.setText("Ejemplo 2 de mens");
shell.setImage(new Image(display, "c:\\Eclipse.jpg"));

// Se crea la barra de mens. Se pueden crear ms, pero slo una
// puede ser visible en un instante dado.
Menu barra = new Menu(shell, SWT.BAR);

// Se crea un MenuItem llamado archivo.
MenuItem archivo = new MenuItem(barra, SWT.CASCADE);
archivo.setText("Archivo");

// Se crea el men de archivos y se asocia al MenuItem archivo de la barra
// de mens.
Menu menuArchivo = new Menu(shell, SWT.DROP_DOWN);
archivo.setMenu(menuArchivo);
MenuItem abrir = new MenuItem(menuArchivo, SWT.RADIO);
abrir.setText("Abrir");

// Se aade al men de archivos una lnea separadora.
MenuItem separador = new MenuItem(menuArchivo, SWT.SEPARATOR);

// Se aade al men Archivo un elemento Salir.
MenuItem salir = new MenuItem(menuArchivo, SWT.PUSH);
salir.setText("Salir");

// Se crea un MenuItem llamado editar.
MenuItem editar = new MenuItem(barra, SWT.CASCADE);
editar.setText("Edicin");





Ejemplo 5: EjemploMenu2.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 43 de 114
// Se crea el men de edicin y se asocia al MenuItem editar de la barra de
// mens.
Menu menuEditar = new Menu(shell, SWT.DROP_DOWN);
editar.setMenu(menuEditar);
MenuItem cortar = new MenuItem(menuEditar, SWT.PUSH);
cortar.setText("Cortar");

// Se aade al men de edicin un elemento Copiar.
MenuItem copiar = new MenuItem(menuEditar, SWT.PUSH);
copiar.setText("Copiar");

// Se aade al men de edicin un elemento Pegar.
MenuItem pegar = new MenuItem(menuEditar, SWT.PUSH);
pegar.setText("Pegar");

// Tratamiento de los sucesos del usuario. Es obligatorio
// incluir el mtodo widgetDefaultSelected, aunque est
// vaco.

abrir.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
System.out.println("Apret Abrir");
}
public void widgetDefaultSelected(SelectionEvent e) { }
});

salir.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
System.exit(0); // se sale de la aplicacin
}
public void widgetDefaultSelected(SelectionEvent e) { }
});

cortar.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
System.out.println("Apret Cortar");
}
public void widgetDefaultSelected(SelectionEvent e) { }
});

copiar.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
System.out.println("Apret Copiar");
}
public void widgetDefaultSelected(SelectionEvent e) { }
});

pegar.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
System.out.println("Apret Pegar");
}
public void widgetDefaultSelected(SelectionEvent e) { }
});

shell.setMenuBar(barra);
shell.open();

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 44 de 114
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}

}




































Figura 31. Resultado de ejecutar la clase EjemploMenu2


http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 45 de 114



import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase genera un cuadro de texto multilnea.
* Se necesita incluir el paquete org.eclips.swt.graphics.Image
* para poder trabajar con imgenes en SWT.
*
* La clase Label admite los siguientes estilos: BORDER, CENTER,
* LEFT, RIGHT, WRAP y SEPARATOR (con HORIZONTAL, SHADOW_IN,
* SHADOW_OUT, SHADOW_NONE y VERTICAL).
*
* BORDER crea una etiqueta con borde.
* CENTER, LEFT y RIGHT alinean el texto de la etiqueta con respecto a la etiqueta.
* WRAP hace que el texto dentro de la etiqueta se pueda dividir en varias lneas, si
* resulta necesario.
* SHADOW_IN (usado con SEPARATOR) crea un separador que parece empotrado
* en la ventana.
* SHADOW_OUT (usado con SEPARATOR) crea un separador que parece sobresalir
* de la ventana.
* SHADOW_NONE (usado con SEPARATOR) crea un separador sin sombra.
* SEPARATOR y VERTICAL generan una lnea vertical.
* SEPARATOR y HORIZONTAL generan una lnea horizontal.
*
*
* La clase Text admite los siguientes estilos: BORDER, SINGLE,
* READ_ONLY, LEFT, CENTER, RIGHT, WRAP, PASSWORD y MULTI
* (con H_SCROLL, V_SCROLL)
*
* BORDER crea un cuadro de texto con borde.
* SINGLE crea un cuadro de texto que slo permite una lnea.
* MULTI crea un cuadro de texto que admite varias lneas.
* READ_ONLY crea un cuadro de texto cuyo contenido no se puede editar.
* CENTER, LEFT y RIGHT alinean el texto del cuadro de texto con respecto a l.
* WRAP hace que el texto dentro del cuadro de texto se pueda dividir en varias lneas, si
* resulta necesario.
* PASSWORD crea un cuadro de texto que muestra asteriscos cuando se escribe en l.
* H_SCROLL crea una barra de desplazamiento horizontal.
* V_SCROLL crea una barra de desplazamiento vertical.
*/

public class EjemploCuadroTexto1 {

public static void main(String args[]) {
Display display = new Display();

Shell shell = new Shell(display);

shell.setSize(280, 230);
shell.setText("Ejemplo 1 de cuadro de texto");

Ejemplo 6: EjemploCuadroTexto1.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 46 de 114
// Se crean los componentes grficos.
Label l1 = new Label(shell, SWT.NONE);
l1.setText("Nombre del usuario:");
l1.setBounds(90, 10, 100, 25);

final Text nombreUsuario = new Text(shell, SWT.BORDER);
nombreUsuario.setBounds(90, 35, 100, 25);

Label etiqueta2 = new Label(shell, SWT.NULL);
etiqueta2.setText("Contrasea:");
etiqueta2.setBounds(90, 70, 100, 25);

final Text contrasenya = new Text(shell, SWT.BORDER);
contrasenya.setEchoChar('*');
contrasenya.setBounds(90, 95, 100, 25);

Button validarUsuario = new Button(shell, SWT.PUSH);
validarUsuario.setText("Validar usuario");
validarUsuario.setBounds(100, 150, 85, 28);

// Tratamiento de sucesos: muy similar a como se hace en Swing.
Listener listener = new Listener() {
public void handleEvent(Event suceso) {
System.out.println(
"El nombre del usuario es: " + nombreUsuario.getText());
System.out.println(
"La contrasea es: " + contrasenya.getText());
}
};
validarUsuario.addListener(SWT.Selection, listener);

shell.open();

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

}
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 47 de 114





















Figura 32. Resultado de ejecutar la clase EjemploCuadroTexto1






import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.Image;

/**
* Esta clase genera un cuadro de texto multilnea.
* Se necesita incluir el paquete org.eclips.swt.graphics.Image
* para poder trabajar con imgenes en SWT.
*
*/

public class EjemploCuadroTexto2 {

public static void main(String args []) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 300);
shell.setImage(new Image(display, "c:\\Eclipse.jpg"));
shell.setText("Ejemplo 2 de cuadro de texto");

// Se crea el cuadro de texto multlinea.
Text texto = new Text(shell, SWT.MULTI);

// El primer argumento indica la coordenada x del extremo inferior izquierdo del cuadro de
// texto; el segundo, la coordenada y del extremo superior izquierdo; los otros dos indican la
// anchura y la altura del cuadro de texto, respectivamente.

Ejemplo 7: EjemploCuadroTexto2.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 48 de 114
texto.setBounds(10, 10, 200, 28);
texto.setText( "Lnea 1" + System.getProperty("line.separator") + "Lnea 2");

shell.open();

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

display.dispose();
}

}
























Figura 33. Resultado de ejecutar la clase EjemploCuadroTexto2





import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;

/**
* Esta clase genera tres cuadros de texto y muestra por consola el texto seleccionado
* cuando se pasa de uno a otro.
*
*/

Ejemplo 8: EjemploCuadroTexto3.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 49 de 114

public class EjemploCuadroTexto3 {

public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(200, 200);
shell.setText("Ejemplo 3 de cuadro de texto");

// primer cuadro de texto
Text texto1 = new Text(shell, SWT.SINGLE | SWT.BORDER);
texto1.setBounds(30, 10, 100, 20);
texto1.setTextLimit(11);
texto1.setText("javaHispano");

// segundo cuadro de texto
Text texto2 = new Text(shell, SWT.SINGLE | SWT.BORDER);
texto2.setBounds(30, 40, 100, 20);
texto2.setTextLimit(11);

// tercer cuadro de texto
Text texto3 = new Text(shell, SWT.SINGLE | SWT.BORDER);
texto3.setBounds(30, 70, 100, 20);
texto3.setTextLimit(11);

// gestin de eventos
FocusListener focusListener = new FocusListener() {
public void focusGained(FocusEvent e) {
// Si obtiene el foco se selecciona todo lo que hay en el cuadro de texto.
Text texto = (Text) e.widget;
texto.selectAll();
}
public void focusLost(FocusEvent e) {
// Si pierde el foco, muestra el texto seleccionado o un mensaje que
// indica que el cuadro de texto estaba vaco.
Text texto = (Text) e.widget;
if ( texto.getSelectionCount() > 0 ) {
if ( texto.getLocation().y == 10 ) {
System.out.println("Ha seleccionado en el cuadro de texto 1: " + texto.getText());
}
if ( texto.getLocation().y == 40 ) {
System.out.println("Ha seleccionado en el cuadro de texto 2: " + texto.getText());
}
if ( texto.getLocation().y == 70 ) {
System.out.println("Ha seleccionado en el cuadro de texto 3: " + texto.getText());
}
}
else {
System.out.println("No ha seleccionado nada: el cuadro de texto estaba vaco.");
}
}
}; // fin focusListener

texto1.addFocusListener(focusListener);
texto2.addFocusListener(focusListener);
texto3.addFocusListener(focusListener);
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 50 de 114

shell.open();

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

display.dispose();
}

}


















Figura 34. Resultado de ejecutar la clase EjemploCuadroTexto3





import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.*;

/**
* Esta clase muestra cmo se usan las etiquetas con SWT.
*
* La clase Label admite los siguientes estilos: BORDER, CENTER,
* LEFT, RIGHT, WRAP y SEPARATOR (con HORIZONTAL, SHADOW_IN,
* SHADOW_OUT, SHADOW_NONE y VERTICAL).
*
* BORDER crea una etiqueta con borde.
* CENTER, LEFT y RIGHT alinean el texto de la etiqueta con respecto a la etiqueta.
* WRAP hace que el texto dentro de la etiqueta se pueda dividir en varias lneas, si
* resulta necesario.
* SHADOW_IN (usado con SEPARATOR) crea un separador que parece empotrado
* en la ventana.

Ejemplo 9: EjemploEtiqueta.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 51 de 114
* SHADOW_OUT (usado con SEPARATOR) crea un separador que parece sobresalir
* de la ventana.
* SHADOW_NONE (usado con SEPARATOR) crea un separador sin sombra.
* SEPARATOR y VERTICAL generan una lnea vertical.
* SEPARATOR y HORIZONTAL generan una lnea horizontal.
*
*/

public class EjemploEtiqueta {

public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell();
shell.setLayout(new GridLayout(1, false));
shell.setText("Ejemplo de etiquetas");

// Se crea una etiqueta.
Label etiqueta1 = new Label(shell, SWT.NONE);
etiqueta1.setText("Etiqueta plana");

// Se crea una etiqueta con borde
Label etiqueta2 = new Label(shell, SWT.BORDER);
etiqueta2.setText("Etiqueta con borde");

// Se crea un separador.
Label etiqueta3 = new Label(shell, SWT.SEPARATOR);

// Se crea un separador horizontal con sombra.
Label etiqueta4= new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL |
SWT.SHADOW_IN);
etiqueta4.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

// Se crea una etiqueta con el logotipo de Eclipse.
Image imagen = new Image(display, "c:\\Eclipse.jpg");
Label etiqueta5 = new Label(shell, SWT.NONE);
etiqueta5.setImage(imagen);

shell.open();
shell.pack();

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

display.dispose();
}

}


El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 52 de 114





































Figura 35. Resultado de ejecutar la clase EjemploEtiqueta





import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;

/**
* Esta clase genera una lista con tres elementos.
*
* La clase List admite los siguientes estilos: BORDER, H_SCROLL,
* V_SCROLL, SINGLE y MULTI.
*
* BORDER crea un borde alrededor de la lista.
Ejemplo 10: EjemploLista1.java

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 53 de 114
* H_SCROLL crea una barra de desplazamiento horizontal para la lista.
* V_SCROLL crea una barra de desplazamiento vertical para la lista.
* MULTI permite seleccionar a la vez varios elementos.
*/

public class EjemploLista1 {

public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 300);
shell.setText("Ejemplo 1 de lista");

List lista = new List(shell, SWT.SINGLE | SWT.BORDER);
lista.setBounds(40, 40, 80, 60);

lista.add("Bolgrafo");
lista.add("Lpiz");
lista.add("Calculadora");

shell.open();

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

}
















Figura 36. Resultado de ejecutar la clase EjemploLista1
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 54 de 114



import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;

/**
* Esta clase genera una lista con tres elementos que admite selecciones
* mltiples.
*/

public class EjemploLista2 {

public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 250);
shell.setText("Ejemplo 2 de lista");

// El objeto Lista debe definirse como final si se quiere acceder a l desde
// el mtodo addSelectionListener(). El argumento SWT.MULTI hace que
// se puedan seleccionar varios elementos a la par.
final List lista = new List(shell, SWT.MULTI | SWT.BORDER);
lista.setBounds(40, 40, 80, 60);

lista.add("Bolgrafo");
lista.add("Lpiz");
lista.add("Calculadora");

Button boton = new Button(shell, SWT.PUSH | SWT.BORDER);
boton.setBounds(50, 150, 180, 25);
boton.setText("Seleccione un elemento de la lista");

// Gestin de sucesos: si se presiona el botn se muestran los
// elementos seleccionados. El mtodo getSelection() devuelve
// un vector de Strings.
boton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
String elementosSeleccionados[] = lista.getSelection();
for (int i = 0; i< elementosSeleccionados.length; i++) {
System.out.println(elementosSeleccionados[i]);
}
}
});

shell.open();

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

}
Ejemplo 11: EjemploLista2.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 55 de 114





















Figura 37. Resultado de ejecutar la clase EjemploLista2




import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;

/**
* Esta clase genera una lista con un men contextual (pop-up) que almacena dos
* mens, uno de ellos con dos submens.
*
*/

public class EjemploLista3 {

public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 250);
shell.setText("Ejemplo 3 de lista");

List lista = new List(shell, SWT.SINGLE | SWT.BORDER);
lista.setBounds(80, 40, 100, 60);

lista.add("Elemento 1");
lista.add("Elemento 2");
lista.add("Elemento 3");

// Se crea el men y se aade a la lista.
Menu menu = new Menu(shell, SWT.POP_UP);
lista.setMenu(menu);


Ejemplo 12: EjemploLista3.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 56 de 114
// Se crea el men Archivo.
MenuItem archivo = new MenuItem(menu, SWT.CASCADE);
archivo.setText("Archivo");
Menu menuArchivo = new Menu(menu);
archivo.setMenu(menuArchivo);

// Se aaden al men Archivo los submens Nuevo y Cerrar
MenuItem nuevo = new MenuItem(menuArchivo, SWT.CHECK);
nuevo.setText("Nuevo");
MenuItem cerrar = new MenuItem(menuArchivo, SWT.CHECK);
cerrar.setText("Cerrar");

// Se crea el men Salir
MenuItem salir = new MenuItem(menu, SWT.PUSH);
salir.setText("Salir");

shell.open();

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

}




























Figura 38. Resultado de ejecutar la clase EjemploLista3
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 57 de 114



import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;

/**
* Esta clase muestra un cuadro combinado en que el usuario puede introducir
* elementos hasta alcanzar el valor lmite LIMITE. Una vez alcanzado el lmite,
* por cada elemento que se aada se borrar uno de los que ya haba.
*
* La clase Combo admite los siguientes estilos: BORDER, DROP_DOWN,
* READ_ONLY y SIMPLE.
*
* BORDER crea un borde alrededor del cuadro combinado.
* DROP_DOWN crea un cuadro combinado desplegable.
* READ_ONLY crea un cuadro combinado que no permite que el usuario introduzca nuevos
* elementos o modifique los ya existentes.
* SIMPLE crea un cuadro de texto en el que los elementos del cuadro siempre se muestran
* como una lista.
*
*/

public class EjemploCuadroCombinado {

// Nmero mximo de elementos que admite el cuadro combinado.
final static int LIMITE = 5;

public static void main(String args[]) {
Display display = new Display();

Shell shell = new Shell(display);
shell.setSize(210, 100);
shell.setText("Ejemplo de cuadro combinado");

final Combo cuadroComb = new Combo(shell, SWT.BORDER | SWT.DROP_DOWN);
cuadroComb.setSize( 200, 50);

// Tratamiento de sucesos: mientras no se alcance LIMITE, el texto que
// introduce el usuario se van aadiendo a la lista de elementos
// susceptibles de ser seleccionados.
cuadroComb.addListener(SWT.DefaultSelection,new Listener() {
public void handleEvent(Event event) {
String texto = cuadroComb.getText();
if ( (cuadroComb.indexOf(texto) == -1) && (cuadroComb.getItemCount() >= LIMITE) ) {
cuadroComb.remove(0);
}
cuadroComb.add(texto);
}
});

shell.open();

while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
Ejemplo 13: EjemploCuadroCombinado.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 58 de 114
}
}
}

}













Figura 39. Resultado de ejecutar la clase EjemploCuadroCombinado






import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
* Esta clase muestra una tabla con cuatro ciudades europeas y su distancia a Madrid.
*
* La clase Table admite los siguientes estilos: BORDER, H_SCROLL, V_SCROLL, SINGLE,
* MULTI, CHECK, FULL_SELECTION y HIDE_SELECTION.
*
* BORDER crea una tabla con borde.
* H_SCROLL crea una tabla con una barra de desplazamiento horizontal.
* V_SCROLL crea una tabla con una barra de desplazamiento vertical.
* SINGLE crea una tabla que no permite seleccionar a la vez ms de una celda.
* MULTI crea una tabla que permite la seleccin de varias celdas a la vez.
* CHECK crea una tabla con cuadros de verificacin.
* FULL_SELECTION crea una tabla en la que, al seleccionar una celda, se selecciona
* toda la fila.
* HIDE_SELECTION crea una tabla que esconde las celdas seleccionadas cuando la
* la tabla pierde el foco.
*
* La clase TableColum representa una columna de una tabla y admite tres estilos: LEFT,
* RIGHT y CENTER, que alinean la columna a la izquierda, a la derecha o al centro.
*
* La clase TableItem representa una fila de una tabla y no admite ningn estilo.
*/

public class EjemploTabla1 {

public static void main(String args[]) {

Ejemplo 14: EjemploTabla1.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 59 de 114
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 250);
shell.setText("Ejemplo 1 de tabla");

// Una objeto Table es un widget compuesto. Por ello, conviene usar
// algn tipo de esquema (layout). En este caso se usar
// el esquema de tipo FillLayout, que distribuye
// equitativamente entre los componentes el espacio disponible.
shell.setLayout(new FillLayout());

// Se crea la tabla, que permite la seleccin mltiple de filas.
Table tabla = new Table(shell, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
tabla.setHeaderVisible(true);
tabla.setLinesVisible(true);

// Se crean las columnas.
TableColumn columna1 = new TableColumn(tabla, SWT.CENTER);
TableColumn columna2 = new TableColumn(tabla, SWT.CENTER);

// Se establece el ancho y el nombre de cada columna.
columna1.setText("Ciudad");
columna1.setWidth(90);
columna2.setText("Distancia");
columna2.setWidth(90);

// Se crean y se rellenan las filas.
TableItem fila1 = new TableItem(tabla, SWT.NONE);
String tmp1[] = {"Pars", "1100 km"};
fila1.setText(tmp1);

TableItem fila2 = new TableItem(tabla, SWT.NONE);
String tmp2[] = {"Luxemburgo", "1600 km"};
fila2.setText(tmp2);

TableItem fila3 = new TableItem(tabla, SWT.NONE);
String tmp3[] = {"Berln","1800 km"};
fila3.setText(tmp3);

// Otra manera de rellenar las filas.
TableItem fila4 = new TableItem(tabla, SWT.NONE);
fila4.setText(0, "Atenas");
fila4.setText(1, "3500 km");

shell.open();

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

}


El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 60 de 114






















Figura 40. Resultado de ejecutar la clase EjemploTabla1





import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase muestra por consola el contenido de todas las celdas de la fila seleccionada por
* el usuario.
*
*/

public class EjemploTabla2 {

public static void main (String [] args) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 300);
shell.setText("Ejemplo 2 de tabla");

// Tabla que admite la seleccin simultnea de varios elementos.
final Table tabla = new Table (shell, SWT.BORDER | SWT.V_SCROLL |
SWT.FULL_SELECTION);
tabla.setLinesVisible (true);
tabla.setHeaderVisible (true);

// Se da nombre a las columnas.
for (int i = 1; i < 3; i++) {
Ejemplo 15: EjemploTabla2.java

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 61 de 114
TableColumn columna = new TableColumn (tabla, SWT.NULL);
columna.setText ("Columna " + i);
}

// Se rellena la tabla.
for (int i = 1; i < 11; i++) {
TableItem celda = new TableItem (tabla, SWT.NONE);
celda.setText (0, "celda (" + i + " ,1)");
celda.setText (1, "celda (" + i + " ,2)");
}

// Se vuelve a calcular el ancho preferido de cada columna.
for (int i = 0; i < 2; i++) {
tabla.getColumn (i).pack();
}

tabla.setSize (800, 800);

// Gestin de sucesos: al seleccionar una celda se muestra por consola su texto.
tabla.addListener (SWT.Selection, new Listener () {
public void handleEvent (Event suceso) {
String celda = null;
TableItem celdas[] = tabla.getSelection();
if ( (celdas != null) && (celdas.length >= 1) ) {
System.out.println("Se han seleccionado las celdas: ");
System.out.println (celdas[0].getText(0));
System.out.println (celdas[0].getText(1));
}
}
});

shell.open();


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

display.dispose();
}

}

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 62 de 114



























Figura 41. Resultado de ejecutar la clase EjemploTabla2






import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase muestra un panel de lengetas (TabFolder) con tres lengetas. Una contiene
* un cuadro desplegable (Combo); otra, una etiqueta (Label), y la otra un cuadro de texto (Text).
*/

public class EjemploTabFolder {

public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 300);
shell.setText("Ejemplo de panel de lengetas (TabFolder)");
shell.setLayout(new FillLayout());

// Se crea el panel de lengetas
TabFolder panelLengueta = new TabFolder(shell, SWT.NONE);
Ejemplo 16: EjemploTabFolder.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 63 de 114

// Se crea una lengeta y se llena con un cuadro desplegable.
TabItem lengueta1 = new TabItem(panelLengueta, SWT.NONE);
lengueta1.setText("Lengeta 1");
Combo desplegable = new Combo(panelLengueta, SWT.BORDER);
desplegable.add("Soy un cuadro desplegable");
lengueta1.setControl(desplegable);

// Se crea una lengeta y se llena con una etiqueta.
TabItem lengueta2 = new TabItem(panelLengueta, SWT.NONE);
lengueta2.setText("Lengeta 2");
Label etiqueta = new Label(panelLengueta, SWT.BORDER);
etiqueta.setText("Soy una etiqueta");
lengueta2.setControl(etiqueta);

// Se crea una lengeta y se llena con un cuadro de texto.
TabItem lengueta3 = new TabItem(panelLengueta, SWT.NONE);
lengueta3.setText("Lengeta 3");
Text cuadroTexto = new Text(panelLengueta, SWT.NONE);
cuadroTexto.setText("Soy un cuadro de texto");
lengueta3.setControl(cuadroTexto);

shell.open();

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

}




















Figura 42. Resultado de ejecutar la clase EjemploTabFolder
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 64 de 114



import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase genera un rbol del que cuelgan varios nodos.
*
* La clase Tree acta como un contenedor de objetos TreeItem.
* La clase Tree admite los siguientes estilos: BORDER,
* H_SCROLL, V_SCROLL, SINGLE, MULTI y CHECK.
*
* BORDER crea un rbol con borde.
* H_SCROLL y V_SCROLL crean un rbol con una barra de desplazamiento horizontal o
* vertical, respectivamente
* SINGLE crea un rbol que slo permite seleccionar un nodo o elemento a la vez.
* MULTI crea un rbol que permite que se seleccionen a la vez varios nodos o elementos.
* CHECK crea un rbol con cuadros de verificacin.
*
* Los mtodos ms usados de Tree son:
* 1) getSelection() devuelve un vector con los TreeItems que estn seleccionados.
* 2) getSelectionCount() devuelve el nmero de elementos seleccionados.
* 3) removeAll() borra todos los elementos del rbol.
* 4) selectAll() selecciona todos los elementos del rbol.
* 5) deselectAll() quita la seleccin de todos los elementos seleccionados del rbol.
* 6) setSelection(TreeItem[]) Seleccionan los elementos establecidos en el vector pasado como
* argumento.
*
* Los mtodos ms usados de TreeItem son:
* 1) getChecked() devuelve true si el elemento est marcado, y false en caso contrario.
* 2) getExpanded () devuelve true si el elemento est expandido, y false en caso contrario.
* 3) setChecked (boolean) establece si el elemento est marcado o no.
* 4) setExpanded(boolean) establece si el elemento est expandido o no.
* 5) setImage(Image) establece una imagen para el elemento. Si el argumento es null, no se
* mostrar ninguna imagen.
* 4) setText(String) establece el texto del elemento.
*/

public class EjemploArbol {

public static void main(String args[]) {

Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 300);
shell.setText("Ejemplo de rbol");
shell.setLayout(new FillLayout());

// Se crea el rbol.
Tree arbol = new Tree(shell, SWT.BORDER);

// Se crea el nodo 1 y sus subnodos.
TreeItem nodo1 = new TreeItem(arbol, SWT.NONE);
Ejemplo 17: EjemploArbol.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 65 de 114
nodo1.setText("Nodo 1");
TreeItem nodo11 = new TreeItem(nodo1, SWT.NONE);
nodo11.setText("Nodo 1.1");
TreeItem nodo111 = new TreeItem(nodo11, SWT.NONE);
nodo111.setText("Nodo 1.1.1");

// Se crea el nodo 2 y sus subnodos.
TreeItem nodo2 = new TreeItem(arbol, SWT.NONE);
nodo2.setText("Nodo 2");
TreeItem nodo21 = new TreeItem(arbol, SWT.NONE);
nodo21.setText("Nodo 2.1");
TreeItem nodo22 = new TreeItem(arbol, SWT.NONE);
nodo22.setText("Nodo 2.2");

// Se expande el nodo 1 y su subnodo.
nodo1.setExpanded( true);
nodo11.setExpanded(true);

shell.open();

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

display.dispose();
}

}



















Figura 43. Resultado de ejecutar la clase EjemploArbol

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 66 de 114




import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
* Esta clase muestra botones, de distintos tipos, organizados segn el layout
* RowLayout, que permite organizar los controles una fila o una columna, sin forzar a que tengan
* el mismo tamao (si no caben en una sola fila o columna, se muestran en varias).
*
* Por ahora, SWT admite seis layouts: FillLayout, StackLayout, GridLayout, FormLayout,
* RowLayout y CustomLayout.
*/


public class EjemploRowLayout {

public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(250, 250);
shell.setText("Ejemplo de RowLayout");

// columnas horizontales
shell.setLayout(new RowLayout(SWT.HORIZONTAL));

for (int i = 0; i < 9; i++) {
Button boton = new Button(shell, SWT.ARROW);
boton.setText("Botn no. " + i);
}
for (int i = 0; i < 9; i++) {
Button boton = new Button(shell, SWT.PUSH);
boton.setText("Botn no. " + i);
}
for (int i = 0; i < 9; i++) {
Button boton = new Button(shell, SWT.RADIO);
boton.setText("Botn no. " + i);
}
shell.open();

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

}
Ejemplo 18: EjemploRowLayout.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 67 de 114






















Figura 44. Resultado de ejecutar la clase EjemploRowLayout





import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase genera 25 etiquetas organizadas segn el layout GridLayout, que
* permite crear mltiples filas y columnas, es decir, una red de controles.
*
* Por ahora, SWT admite seis layouts: FillLayout, StackLayout, GridLayout, FormLayout,
* RowLayout y CustomLayout.
*/

public class EjemploGridLayout {

public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setSize(400, 300);

// El primer argumento indica es el nmero de columnas.
// El segundo argumento (booleano) indica si se desea tomar el espacio mnimo
// para columna (false) o no (true).
shell.setLayout(new GridLayout(4, false));

for (int i = 0; i < 25; i++) {
Label etiqueta = new Label(shell, SWT.BORDER | SWT.CENTER);
etiqueta.setText("Etiqueta no. " + i);
Ejemplo 19: EjemploGridLayout.java

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 68 de 114
}
shell.open();

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

}













Figura 45. Resultado de ejecutar la clase EjemploGridLayout






import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.graphics.*; // incluye la clase Color

/**
* Esta clase genera una ventana con una etiqueta, un botn y un rea de texto, organizados
* mediante el layout FormLayout. Como una imagen vale ms que mil palabras, la
* mejor explicacin para lo que hace esta clase est en la figura 46.
*
* La clase FormLayout utiliza la clase FormData para colocar los controles donde correspon-
* da, con el tamao adecuado. FormData permite especificar la anchura y la longitud de
* un control dentro de un FormLayout.
* A su vez, la clase FormData usa la clase FormAttachment para especificar los bordes
* de un control en el layout. Estos bordes se pueden dar como posiciones absolutas en pxeles
* (poco recomendable) o como porcentajes (en tanto por ciento) del ancho o del alto del
* compuesto en que se haya el control.
* Mirando la figura 46, se puede deducir la correspondencia entre el cdigo y la interfaz.
*/


public class EjemploFormLayout {

public static void main(String args[]) {
Ejemplo 20: EjemploFormLayout.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 69 de 114

Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(400, 400);
shell.setText("Ejemplo 1 de FormLayout");

FormLayout layout= new FormLayout();
shell.setLayout (layout);

Label etiqueta1 = new Label (shell, SWT.CENTER | SWT.BORDER);
etiqueta1.setText("Etiqueta 1");
etiqueta1.setBackground(new Color(null, 191, 191, 255));

Label etiqueta2= new Label(shell, SWT.CENTER | SWT.BORDER);
etiqueta2.setText("Etiqueta 2");
etiqueta2.setBackground(new Color(null, 255, 255, 179));

Label etiqueta3= new Label(shell, SWT.CENTER | SWT.BORDER);
etiqueta3.setText("Etiqueta 3");
etiqueta3.setBackground(new Color(null, 255, 202, 149));

FormData data1 = new FormData();
data1.left = new FormAttachment(0, 20);
data1.right = new FormAttachment(25, 0);
etiqueta1.setLayoutData(data1);

// El control a la izquierda de etiqueta2 es etiqueta1.
FormData data2 = new FormData();
data2.left = new FormAttachment(etiqueta1, 15);
data2.right= new FormAttachment(90, -15);
etiqueta2.setLayoutData(data2);

// El control encima de etiqueta3 es etiqueta1.
FormData data3 = new FormData();
data3.left = new FormAttachment(25, 15);
data3.right = new FormAttachment(100, -15);
data3.top = new FormAttachment(etiqueta2, 18);
data3.bottom = new FormAttachment(100, -21);

etiqueta3.setLayoutData(data3);

shell.pack();
shell.open();


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

}

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 70 de 114




























Figura 46. Resultado de ejecutar la clase EjemploFormLayout
(1: etiqueta1; 2: etiqueta2; 3: etiqueta3)





import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase genera un dilogo de directorios y muestra por la consola el directorio
* seleccionado.
*
* La clase DirectoryDialog admite los siguientes estilos:
* 1) OPEN permite que el usuario escoja un directorio.
* 2) MULTI permite que el usuario escoja varios directorios a la vez.
*
* Los mtodos ms usados de DirectoryDialog son:
* 1) open() abre el cuadro de dilogo y devuelve el nombre del directorio seleccionado.
* Si no se ha seleccionado ninguno, devuelve null.
* 2) setFilterPath() permite especificar una cierta cadena de caracteres para la bsqueda
* de directorios
* 4) setMessage() permite colocar un mensaje sobre el cuadro de dilogo.
*/
Ejemplo 21: EjemploDialogoDirectorios.java
Margen
izquierdo
(1): 20
Margen
izquierdo (2
y 3): 15
25%
Margen
derecho (2 y
3): -15
90%
100%
100%
18
21
Miguel ngel Abin, marzo de 2005

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 71 de 114
public class EjemploDialogoDirectorios {

public static void main(String args[]) {

Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 400);
shell.setText("Ejemplo dilogo de directorios");

DirectoryDialog dialogo = new DirectoryDialog(shell);
dialogo.setMessage("Elija un directorio");

String directorio = dialogo.open();

if (directorio != null) {
System.out.println("Directorio seleccionado:" + directorio);
}

shell.open();
display.dispose();
}

}





























Figura 47. Resultado de ejecutar la clase EjemploDialogoDirectorios


El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 72 de 114




import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase genera un dilogo de archivos y muestra por consola el archivo elegido.
*
* La clase DialogFile admite los siguientes estilos:
* 1) SAVE permite hacer dilogos para guardar archivos.
* 2) OPEN permite que el usuario escoja un nico archivo.
* 3) MULTI permite que el usuario escoja varios archivos a la vez.
*
* Los mtodos ms usados de DialogFile:
* 1) open() abre el cuadro de dilogo y devuelve el nombre del archivo seleccionado.
* Si no se ha seleccionado ninguno, devuelve null. Si se trabaja con el estilo MULTI,
* este mtodo devolver el nombre de un solo archivo. Si se quiere saber todos los
* que han sido seleccionados, debe usarse getFileNames().
* 2) setFilterExtensions() permite especificar una cierta extensin para los archivos que
* se buscan.
*/

public class EjemploDialogoArchivos {

public static void main(String args[]) {

Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 400);
shell.setText("Ejemplo de dilogo de directorios");

FileDialog dialogo = new FileDialog(shell, SWT.SINGLE);
dialogo.setFilterExtensions(new String[] {"*.java"});

String archivo = dialogo.open();
if (archivo != null) {
System.out.println("Ha seleccionado el archivo " + archivo);
}

shell.open();

display.dispose();
}

}

Ejemplo 22: EjemploDialogoArchivos.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 73 de 114


























Figura 48. Resultado de ejecutar la clase EjemploDialogoArchivos





import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase genera un dilogo de mensaje con tres botones y muestra por consola la opcin
* elegida.
*
* Los estilos que admite la clase MessageBox son:
* 1) ICON_ERROR, ICON_INFORMATION, ICON_QUESTION, ICON_WARNING e
* ICON_WORKING permiten elegir el icono del dilogo.
* 2) OK o OK | CANCEL para elegir botones del tipo OK o OK/CANCELAR.
* 3) YES | NO, YES | NO | CANCEL para elegir botones del tipo SI, NO, CANCELAR.
* 4) RETRY | CANCEL para elegir botones del tipo REINTENTAR/CANCELAR.
* 5) ABORT | RETRY | IGNORE para elegir botones del tipo ANULAR/REINTENTAR/OMITIR.
*
* Los iconos indican lo siguiente:
* ERROR_ICON: error.
* ICON_INFORMATION: se muestra un mensaje al usuario
* ICON_QUESTION: se necesita que el usuario d una respuesta (SI, NO, CANCELAR...)
* ICON_WARNING: se avisa al usuario de que la pregunta puede tener consecuencias no
deseadas.
* ICON_WORKING: la aplicacin que se ejecuta est realizando alguna tarea.

Ejemplo 23: EjemploDialogoMensaje1.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 74 de 114
*/

public class EjemploDialogoMensaje1 {

public static void main(String args[]) {

Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(0, 0);
shell.setText("Ejemplo 1 de dilogo de mensaje");

MessageBox dialogo = new MessageBox(shell, SWT.YES | SWT.NO | SWT.CANCEL |
SWT.ICON_QUESTION);

dialogo.setMessage("Qu extrao. Problemas. Desea continuar?");

int respuesta = dialogo.open();

if (respuesta == SWT.YES) {
System.out.println("Ha elegido continuar");
}
else if (respuesta == SWT.NO) {
System.out.println("Ha elegido no continuar");
}
else if (respuesta == SWT.CANCEL) {
System.out.println("Ha elegido cancelar");
}

shell.open();

display.dispose();
}

}














Figura 49. Resultado de ejecutar la clase EjemploDialogoMensaje1



http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 75 de 114




import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase genera una ventana con un botn de tipo PUSH. Al pulsarlo, aparece un
* mensaje de dilogo con botones ANULAR/REINTENTAR/OMITIR. Al elegir una opcin,
* se muestra por consola la elegida.
*
*/

public class EjemploDialogoMensaje2 {

public static void main(String args[]) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new RowLayout());


shell.setSize(300, 300);
shell.setText("Ejemplo 2 de mensaje de dilogo");

Button pulsar = new Button(shell, SWT.PUSH);
pulsar.setText("Pulse aqu");
pulsar.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
int respuesta = 0;

MessageBox dialogo = new MessageBox(shell, SWT.ICON_WARNING |
SWT.ABORT | SWT.RETRY | SWT.IGNORE);
dialogo.setMessage("Mensaje para el usuario");

respuesta = dialogo.open();

if (respuesta == SWT.ABORT) {
System.out.println("Se ha seleccionado el botn ANULAR");
}
if (respuesta == SWT.RETRY) {
System.out.println("Se ha seleccionado el botn REINTENTAR");
}
if (respuesta == SWT.IGNORE) {
System.out.println("Se ha seleccionado el botn OMITIR");
}
}
});

shell.open();

while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
Ejemplo 24: EjemploDialogoMensaje2.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 76 de 114
}

}









































Figura 50. Resultado de ejecutar la clase EjemploDialogoMensaje2



http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 77 de 114




import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.graphics.*; // incluye la clase Color

/**
* Esta clase genera un dilogo de color y muestra por consola las componentes
* cromticas RGB del color elegido. Si no se elige ningn color, la aplicacin
* termina.
*
* La clase ColorDialog permite seleccionar un color de una paleta de colores. Su
* mtodo open() abre el cuadro de dilogo y devuelve el color seleccionado en
* forma de un objeto de tipo RGB. Si no se selecciona ningn color, open() devuelve
* null.
*/

public class EjemploDialogoColor {

public static void main(String args[]) {

Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 400);

Color color = null;

ColorDialog dialogo = new ColorDialog(shell);
if (color !=null) {
dialogo.setRGB(color.getRGB());
}
else {
dialogo.setRGB(null);
}

while(true) {
if (dialogo.open() != null) {
// Se haba elegido un color antes.
if (color != null) {
// Es crucial la limpieza del objeto color por parte del programador.
// En SWT, el recolector de basura no funciona: los objetos deben
// liberarse usando su mtodo dispose().
color.dispose();
}
color = new Color(display, dialogo.getRGB());
System.out.println("Rojo: " + color.getRed());
System.out.println("Azul: " + color.getBlue());
System.out.println("Verde: " + color.getGreen());
}
// No se ha elegido un color.
else {
System.exit(0);
}
Ejemplo 25: EjemploDialogoColor.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 78 de 114
}
}

}
























Figura 51. Resultado de ejecutar la clase EjemploDialogoColor. (Reconozco
que queda mucho ms vistoso en un Macintosh, pero no tengo ninguno a mano.)






import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase muestra un cuadro de dilogo desde donde se puede seleccionar un
* tipo de letra (nombre, tamao, negrita/cursiva/...) y crea una etiqueta con la
* leyenda "Colabore con javaHispano" con el tipo de letra elegido.
*
* La clase FontDialog permite al usuario seleccionar un tipo de letra de las disponibles
* en el sistema. Como algunos tipos de letras son especficos de la plataforma en la que
* se trabaja, SWT trabaja con la clase FontData como intermediaria.
* El mtodo open() de la clase FontDialog devuelve un objeto FontData que representa
* al color seleccionado (si no se selecciona nada, open() devuelve null).
* FontData admite argumentos como los de la siguiente lnea
* FontData defaultFont = new FontData("Courier", 14, SWT.BOLD);
*/


Ejemplo 26: EjemploDialogoTipoLetra.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 79 de 114
public class EjemploDialogoTipoLetra {

public static void main(String args[]) {

Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(300, 100);
shell.setText("Ejemplo de dilogo para elegir tipo de letra");
shell.setLayout(new FillLayout(SWT.CENTER));

FontDialog fd = new FontDialog(shell);
FontData fontData = fd.open();

if (fontData != null) {

Font f = new Font(display, fontData);

Label etiqueta = new Label(shell, SWT.BORDER | SWT.CENTER);
etiqueta.setText("Colabore con javaHispano");
etiqueta.setFont(f);

// En SWT, el recolector de basura no funciona: los objetos deben
// liberarse usando su mtodo dispose().
f.dispose();
}
// Si no se ha elegido nada, se sale de la aplicacin.
else {
display.dispose();
System.exit(0);
}

shell.open();

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

display.dispose();
}

}












El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 80 de 114








































Figura 52. Resultado de ejecutar la clase EjemploDialogoTipoLetra. Haga caso al
mensaje, por favor

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 81 de 114



import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase llama a la clase EjemploGrupo para mostrar un grupo
* de controles.
*/

public class PrincipalGrupo {

public static void main(String args[]) {

Display display = new Display();
Shell shell = new Shell(display);

shell.setSize(200, 200);
shell.setText("Ejemplo de grupo");

EjemploGrupo ejGrupo = new EjemploGrupo(shell);
ejGrupo.setLayout(new FillLayout(SWT.CENTER));
ejGrupo.pack();
shell.open();

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

display.dispose();
}

}





import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

/**
* Esta clase representa a un grupo con varios controles.
*
* La clase Group admite los estilos SHADOW_ETCHED_IN,
* SHADOW_ETCHED_OUT, SHADOW_IN, SHADOW_OUT y SHADOW_NONE y
* NO_RADIO_GROUP
* Todos, excepto el ltimo, no tienen efecto en Windows (en Motif s, por ejemplo).
*
* La clase Composite admite los estilos BORDER (borde),
* H_SCROLL (barra de deslizamiento horizontal) y
* V_SCROLL (barra de deslizamiento vertical).
Ejemplo 27a: PrincipalGrupo.java
Ejemplo 27b: EjemploGrupo.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 82 de 114
*/

public class EjemploGrupo extends Composite {

public EjemploGrupo(Composite comp) {
super(comp, SWT.V_SCROLL | SWT.H_SCROLL);

Group grupo = new Group(this, SWT.SHADOW_NONE);
grupo.setText("Grupo de controles");
grupo.setLayout(new RowLayout(SWT.VERTICAL));

Button boton1 = new Button (grupo, SWT.PUSH | SWT.CENTER);
boton1.setText("Botn normal");

Button boton2 = new Button(grupo, SWT.RADIO | SWT.CENTER);
boton2.setText("Botn redondo");

Label etiqueta = new Label(grupo, SWT.BORDER | SWT.CENTER);
etiqueta.setText("Etiqueta");

Text areaTexto = new Text(grupo, SWT.BORDER | SWT.CENTER | SWT.MULTI |
SWT.V_SCROLL);
areaTexto.setText("rea de texto multilnea");
}

}

























Figura 53. Resultado de ejecutar la clase PrincipalGrupo



http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 83 de 114




import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.browser.*;

/**
* Esta clase abre un navegador con el URL http://www.galeria.sonic.pl/DaliGal/Gal12/1935_02.htm.
* El navegador que se abra depender de la configuracin del sistema.
*
* La clase Browser permite incluir el navegador web del usuario en una aplicacin
* con SWT y usarlo para ver cdigo HTML sin que se necesite escribir cdigo que
* actualice cada cierto tiempo lo que se muestra en el navegador.
*
* La clase Browser slo est disponible en Eclipse 3.0 y posteriores (cuando escribo
* esto todava no se encuentre disponible para algunas plataformas).
* En las versiones 2.x de Eclipse, en Windows se hara este programa empleando el
* paquete org.eclipse.swt.ole.win32.* y la clase SWT OleControlSite.
*
*/

public class EjemploNavegador {

public static void main(String args[]) {
Display display = new Display();

Shell shell = new Shell(display);
shell.setText("Ejemplo de apertura de un navegador desde SWT");
shell.setSize(800, 600);

Label etiqueta = new Label(shell, SWT.BORDER | SWT.CENTER);
etiqueta.setBounds(190, 0, 400, 25);
etiqueta.setText("La URL es http://www.galeria.sonic.pl/DaliGal/Gal12/1935_02.htm");

try {
Browser navegador = new Browser(shell, SWT.BORDER);
navegador.setUrl("http://www.galeria.sonic.pl/DaliGal/Gal12/1935_02.htm");
navegador.setBounds(1, 1, 799, 599);
}

// Si no se encuentra ningn navegador, se lanzar una
// excepcin SWTError.
catch(SWTError e) {
System.out.println("No se encuentra ningn navegador en su sistema.");
e.printStackTrace();
System.exit(-1);
}

shell.open();

while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
Ejemplo 28: EjemploNavegador.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 84 de 114

display.dispose();
}

}






































Figura 54. Resultado de ejecutar la clase EjemploNavegador

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 85 de 114
16. JFace

Si ha ojeado los ejemplos del apartado anterior, habr notado que los controles
SWT vienen a ser una versin ampliada y camalenica de los controles AWT, disponibles
desde la primera versin de Java. As pues, SWT est muchsimo ms limitado que
Swing, basado en la arquitectura Modelo-Vista-Controlador. Las facilidades que la
plataforma Eclipse proporciona para construir interfaces grficas espectaculares no
provienen de SWT, sino de la unin de SWT con JFace. En otras palabras, lo que luce
de Eclipse es JFace.

JFace es una biblioteca grfica construida sobre SWT. JFace usa los componentes
SWT (lo contrario no es cierto) para construir controles ms complejos. He aqu algunas
de las caractersticas ms relevantes de JFace (por motivos de espacio, omito cualquier
explicacin sobre la manera como se implementan):

Permite separar los componentes de la interfaz grfica de usuario y las
respuestas a sus sucesos. Consideremos, vaya por caso, una interfaz con
muchos botones que respondan de la misma manera (lanzando un
cuadro de dilogo, cerrando la aplicacin...). En SWT habra que escribir
el mismo cdigo de tratamiento del suceso para todos los botones (SWT
exige que cada suceso sea declarado y procesado individualmente). En
cambio, JFace permite que el programador defina una respuesta comn
en un objeto Action y que la asigne a todos los botones. En general, una
respuesta o accin puede ser compartida por todos los componentes o
widgets que uno quiera (botones, mens, rboles...).
La separacin entre componentes y respuestas a sucesos conlleva dos
ventajas. Por un lado, evita duplicar cdigo. Por otro, permite que los
diseadores de interfaces grficas y los programadores trabajen
independientemente, sin mezclar el cdigo de unos y otros.

Proporciona clases de tipo Viewer (visor), que se encargan de tareas
comunes como ordenar o actualizar los componentes. Estas clases
permiten trabajar con elementos del modelo en lugar de con widgets. Por
ejemplo, la clase TreeViewer tiene mtodos que permiten trabajar con los
objetos del modelo del usuario, en lugar de trabajar con objetos grficos
del tipo TreeItem, ms primitivos.

Define cuadros de dilogo y asistentes (wizards; un asistente es un
dilogo especializado que gua al usuario para realizar tareas como
instalar un impresora o conectarse a Internet), que responden a muchas
necesidades habituales de los programadores (MessageDialog,
InputDialog, PreferenceDialog...).

Permite registrar objetos como Color, Font o Image, de manera que los
recursos asociados puedan liberarse cuando ya no se usen aqullos. En
SWT resulta conveniente destruir enseguida los objetos Color, Font e
Image que ya no se utilizen, pues no hay un recolector de basura
automtico que se relama pensando en los recursos hurfanos que va a
devorar ni esos objetos se destruyen cuando se elimina el componente
donde se usan. Si el programador no libera explcitamente los recursos
que no necesita, se perjudica el rendimiento del sistema y se favorece
que aparezcan fallos de memoria. Con JFace, en cambio, se pueden usar
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 86 de 114
clases como ColorRegistry, FontRegistry o ImageRegistry, que liberan
automticamente todos los recursos asociados a colores, tipos de letra o
imgenes cuando se destruye el componente para el cual se crearon.

La estructura tpica de una aplicacin que usa JFace se muestra en el siguiente
ejemplo:





import org.eclipse.jface.window.*;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;

/**
* Esta clase es la versin de HolaMundo con SWT/JFace.
*/

public class SaludosJFace extends ApplicationWindow {

// Constructor.
public SaludosJFace() {
super(null);
}

public static void main(String[] args) {
SaludosJFace saludo = new SaludosJFace();

// La ventana aparecer hasta que el usuario la cierre.
saludo.setBlockOnOpen(true);

// Se muestra la ventana del modo dictado por el objeto
// Composite devuelto por el mtodo createContents().
saludo.open();

//Una vez cerrada la ventana, se liberan sus recursos.
Display.getCurrent().dispose();
}

// Asocia un objeto Composite para controlar la interfaz grfica.
protected Control createContents(Composite padre) {
Label etiqueta= new Label(padre, SWT.CENTER);
etiqueta.setText("Saludos con JFace");

return padre;
}

}
Ejemplo 29: SaludosJFace.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 87 de 114







Figura 55. Resultado de ejecutar la clase SaludosJFace


Para que el ejemplo funcione, se precisa aadir los siguientes archivos JAR
mediante la pestaa Libraries en el Java Build Path de Eclipse (vase la figura 56; el
ejemplo es para Windows y para la versin 3.0.1 de Eclipse):

INSTALLDIR\eclipse\plugins\org.eclipse.jface_3.0.1\jface.jar

INSTALLDIR\eclipse\plugins\org.eclipse.core.runtime_3.1.0\runtime.jar

INSTALLDIR\eclipse\plugins\org.eclipse.ui.workbench_3.1.0\workbench.jar

INSTALLDIR\eclipse\plugins\org.eclipse.core.boot.3.0.1\boot.jar
































Figura 56. Configuracin de Eclipse para trabajar con JFace



El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 88 de 114

La clase ms importante de JFace es ApplicationWindow. Para el usuario, un objeto
ApplicationWindow es una ventana principal que puede contener controles. Esta clase
crea su propio shell y permite personalizarlo de manera ms rpida y verstil que con
SWT. Tambin separa, por un lado, el aspecto de la interfaz grfica de usuario y, por
otro, su comportamiento.
ApplicationWindow cuenta con mtodos como addMenuBar(), addToolBar() y
setDefaultImage(), los cuales permiten incluir al instante barras de mens, barras de
herramientas e imgenes.
En la jerarqua de clases de JFace, ApplicationWindow desciende directamente de
la clase Window (contenida en el paquete org.eclipse.jface.window). Window es una
clase abstracta con unos mtodos que sus subclases deben sobreescribir:
close: Libera los recursos SWT.
configureShell: Establece las propiedades del shell antes de que se abra la
ventana.
createContents: Crea los controles antes de que se abra la ventana.
getInitialSize: Especifica el tamao inicial para el shell.
getInitialLocation: Especifica la posicin inicial del shell.
getShellListener: Recibe los sucesos del shell.
getToolTipText: Aade sugerencias o descripciones emergentes (tooltips).
handleFontChange: Implementa la respuesta a cambios en el tipo de letra.
HandleShellCloseEvent: Especifica el comportamiento del shell cuando se
cierra.
Todas las instancias de las subclases de Window son invisibles hasta que se llama
a su mtodo open().


Veamos otros ejemplos de uso del componente JFace:




import org.eclipse.jface.window.*;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;

/*
* Esta clase muestra una ventana que muestra un mensaje SWT de SI/NO cuando se intenta
* cerrarla.
*
* El mtodo createContents() se sobreescribe para crear y devolver los controles SWT
* que aparecern en la ventana.
*
* Al reescribir el mtodo canHandleShellCloseEvent() se establece si la
* ventana maneja el suceso de cierre o si no hace nada.
* Si no se reescribe, la implementacin por defecto devuelve true, lo
* cual produce que se llame al mtodo handleShellCloseEvent().
*
* El mtodo handleShellCloseEvent() se llama cuando se aprieta el botn de cierre,
* el men de cierre o la tecla ESCAPE. Por omisin, este ltimo mtodo cierra
Ejemplo 30: MensajeJFace.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 89 de 114
* la ventana mediante close(). Al reescribirlo, se define el comportamiento
* de la ventana cuando se intente cerrarla.
*
* El mtodo getInitialLocations() devuelve la posicin inicial para el shell.
*
* El mtodo getInitialSize() devuelve el tamao inicial del shell.
*
* El mtodo getShell() devuelve el shell asociado a la ventana.
*
*/

public class MensajeJFace extends ApplicationWindow {

public MensajeJFace() {
super(null);
}

public static void main(String[] args) {
ApplicationWindow ventana = new MensajeJFace();
ventana.setBlockOnOpen(true);
ventana.open();
Display.getCurrent().dispose();
}

protected Control createContents(Composite padre) {
getShell().setText("Ejemplo de uso de mensajes con JFace");
Composite contenedor = new Composite(padre, SWT.BORDER);
return contenedor;
}

// Comportamiento al intentar cerrar la ventana
protected boolean canHandleShellCloseEvent() {
boolean bool = false;

MessageBox cuadroMensaje = new MessageBox(getShell(), SWT.YES |
SWT.NO | SWT.ICON_QUESTION);
cuadroMensaje.setText("Mensaje con JFace");
cuadroMensaje.setMessage("Desea cerrar la aplicacin?");

int respuesta = cuadroMensaje.open();
if (respuesta == SWT.NO) {
return bool;
}
else {
bool = true;
return bool;
}
}

// Tamao inicial
protected Point getInitialSize() {
return new Point(400, 300);
}

// Posicin inicial
protected Point getInitialLocation() {
return new Point(400, 300);
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 90 de 114
}

}





























Figura 57. Resultado de ejecutar la clase MensajeJFace







import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.jface.dialogs.*;

/**
* Esta clase muestra un dilogo personalizado con tres botones. Al apretar
* uno, se muestra un mensaje informativo donde aparece el botn seleccionado.
* Ntese que el dilogo JFace se crea sobre un shell definido mediante SWT, no
* mediante JFace. Podra usarse tambin con una ApplicationWindow.
*
*/

Ejemplo 31: DialogoPersonalizado1.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 91 de 114
public class DialogoPersonalizado1 {

public static void main(String[] args) {
Display display = new Display();

final Shell shell = new Shell(display);
shell.setText("Ejemplo de dilogo JFace personalizado");
shell.setBounds(100, 100, 200, 100);
shell.setLayout(new FillLayout());

final Button boton = new Button(shell, SWT.PUSH);
boton.setText("Pulse aqu");
boton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
String tipo[] = {"Botn 1", "Botn 2", "Botn 3"};
MessageDialog dialogo = new MessageDialog(shell,
"Mensaje para el usuario", null,
"Mensaje informativo", MessageDialog.INFORMATION,
tipo, 2);
int botonPulsado = dialogo.open();
String texto ;
if (botonPulsado == -1) {
texto = "No se ha apretado ningn botn";
}
else {
botonPulsado++; // El primer botn tiene el ndice 0
texto = "Se ha apretado el botn " + botonPulsado;
}

MessageDialog.openInformation(shell, "Mensaje", texto);
}
});

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

display.dispose();
}

}


El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 92 de 114




























Figura 58. Resultado de ejecutar la clase DialogoPersonalizado1








import org.eclipse.swt.widgets.*;
import org.eclipse.jface.dialogs.IDialogConstants;

/**
* Esta clase muestra un dilogo personalizado con una etiqueta, un cuadro
* de texto y dos botones. La implementacin del dilogo est en la clase
* Dialogo. Al apretar uno de los botones, se muestra un mensaje por consola.
*
* Ntese que el dilogo JFace se crea sobre un shell definido mediante SWT, no
* mediante JFace. Podra usarse tambin con una ApplicationWindow
*
*/

public class DialogoPersonalizado2 {

public static void main(String args[]) {

Ejemplo 32a: DialogoPersonalizado2.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 93 de 114
Display display = new Display();

Shell shell = new Shell(display);
shell.setSize(250, 120);

Dialogo dialogo = new Dialogo(shell);
dialogo.create();

int respuesta = dialogo.open();
if (respuesta == IDialogConstants.ABORT_ID) {
System.out.println("Ha apretado el botn de ANULAR");
}
else if (respuesta == IDialogConstants.CLOSE_ID) {
System.out.println("Ha apretado el botn de CERRAR");
}
else {
System.out.println("Ha cancelado el cuadro de dilogo");
}
display.dispose();
}

}





import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
* Esta clase contiene la implementacin de un dilogo personalizado con una
* etiqueta, un cuadro de texto y dos botones. JFace proporciona facilidades
* para crear directamente los botones ms usuales.
*
*/

public class Dialogo extends Dialog {

protected Dialogo(Shell shell) {
super(shell);
}

protected void configureShell(Shell shell) {
super.configureShell(shell);
}

// Se configura la interfaz grfica del dilogo.
protected Control createDialogArea(Composite padre) {
Composite composite = (Composite) super.createDialogArea(padre);
composite.setLayout(new FillLayout(SWT.VERTICAL));

Label etiqueta = new Label(composite, SWT.CENTER);
Ejemplo 32b: Dialogo.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 94 de 114
etiqueta.setText("Ejemplo 2 de dilogo personalizado");

Text texto = new Text(composite, SWT.CENTER | SWT.BORDER);
texto.setText("Pulse uno de los dos botones");

return composite;
}

// Se configuran los botones para la barra de botones.
protected void createButtonsForButtonBar(Composite padre) {
createButton(padre, IDialogConstants.ABORT_ID, IDialogConstants.ABORT_LABEL,
true);
createButton(padre, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL,
false);
}

// Tratamiento de sucesos. Se devuelve el identificador
// del botn apretado. Cuando se llame al mtodo open() de
// un objeto Dialogo, se devolver ese identificador.
protected void buttonPressed(int IdBoton) {
if (IdBoton== IDialogConstants.ABORT_ID
|| IdBoton== IDialogConstants.CLOSE_ID) {
setReturnCode(IdBoton);
close();
}
}

}













Figura 59. Resultado de ejecutar la clase DialogoPersonalizado2













http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 95 de 114
Para explicitar la separacin que permite JFace entre la interfaz grfica y su
comportamiento, incluyo el siguiente ejemplo, que usa una subclase de la clase Action.





import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.*; // necesario para el MessageDialog de JFace
import org.eclipse.jface.window.*;

/*
* Esta clase muestra cmo se puede usar un objeto Action para gestionar
* los sucesos de varios controles (en este ejemplo, dos mens). Mediante
* el objeto Action se consigue responder con un mensaje de informacin
* a sucesos de dos objetos distintos. Se utiliza la clase MessageDialog de JFace.
*
* Al reescribir el mtodo canHandleShellCloseEvent() se establece si la
* ventana maneja el suceso de cierre o si no hace nada.
* Si no se reescribe, la implementacin por defecto devuelve true, lo
* cual produce que se llame al mtodo handleShellCloseEvent().
*
* El mtodo handleShellCloseEvent() se llama cuando se aprieta el botn de cierre,
* el men de cierre o la tecla ESCAPE. Por omisin, este ltimo mtodo cierra
* la ventana mediante close(). Al reescribirlo, se define el comportamiento
* de la ventana cuando se intente cerrarla.
*
* El mtodo createContents() se sobreescribe para crear y devolver los
* controles SWT que aparecern en la ventana.
*
* El mtodo createMenuManager se sobreescribe para especificar y devolver
* los mens de la ventana.
*
* El mtodo createToolBarManager se sobreescribe para especificar y devolver
* los elementos de la barra de herramientas.
*
* El mtodo getShell() devuelve el shell asociado a la ventana.
*
*/

public class EjemploAction extends ApplicationWindow {

private InformacionAction infoAction;

public EjemploAction() {
super (null);
infoAction = new InformacionAction(this);
addMenuBar();
addToolBar(SWT.WRAP);
}

public static void main(String args[]) {
EjemploAction ventana = new EjemploAction();
ventana.setBlockOnOpen(true);
Ejemplo 33a: EjemploAction.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 96 de 114
ventana.open();
Display.getCurrent().dispose();
}

protected Control createContents(Composite padre) {
Group grupo = new Group(padre, SWT.CENTER);
return grupo;
}

protected MenuManager createMenuManager(){
MenuManager barraMenus = new MenuManager("");

MenuManager menu1 = new MenuManager("Ayuda");
barraMenus.add(menu1);
menu1.add(infoAction);

MenuManager menu2 = new MenuManager("Ms ayuda");
barraMenus.add(menu2);
menu2.add(infoAction);

return barraMenus;
}

protected ToolBarManager createToolBarManager(int estilo) {
return new ToolBarManager(estilo);
}

// Como no se ha reescrito el mtodo canHandleShellCloseEvent(),
// se llamar a este mtodo cuando se intente cerrar la ventana.
protected void handleShellCloseEvent() {
String tipo[] = {IDialogConstants.CANCEL_LABEL, IDialogConstants.OK_LABEL};
MessageDialog dialogo = new MessageDialog( getShell(), "Adis", null,
"Desea cerrar la aplicacin?", MessageDialog.WARNING,
tipo, 0);
if (dialogo.open() == 1) { // respuesta: OK
close();
}
}

}





import org.eclipse.jface.window.*;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.*; //necesaria para el MessageDialog de JFace

/**
* Esta clase muestra extiende la clase Action y define un comportamiento
* comn (mostrar un mensaje de informacin) para los mens de la
* clase EjemploAction. Se utiliza la clase MessageDialog de JFace.
*
*/

Ejemplo 33b: InformacionAction.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 97 de 114
public class InformacionAction extends Action {

private ApplicationWindow ventana;

public InformacionAction(ApplicationWindow aw) {
ventana = aw;
setText("Informacin");
}

public void run() {
String[] tipo = {IDialogConstants.OK_LABEL};
MessageDialog dialog = new MessageDialog(ventana.getShell(), "Se ha lanzado la accin", null,
"Mensaje de informacin", MessageDialog.INFORMATION, tipo, 0);
dialog.open();
}

}




























Figura 60. Resultado de ejecutar la clase EjemploAction


El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 98 de 114

A menudo, los programadores trabajan con datos que proceden de fuentes
distintas. Independientemente de la procedencia de los datos, stos suelen mostrarse de
maneras bien distintas: mediante listas, tablas, rboles, etc. Para mostrar los datos, hay
ciertos pasos que suelen ser siempre los mismos: obtener los datos (de una base de
datos, de un archivo de texto, de una coleccin), mostrarlos en un cierto orden
(alfabtico, por caso), asociarlos a cadenas de texto, ocultar algunos y buscar otros...
Tal como se adelant al principio de este apartado, JFace proporciona un
mecanismo para trabajar rpidamente con pasos como los anteriores: el componente
Viewer (visor), compuesto por la clase Viewer y sus subclases e interfaces relacionadas.
Dicho componente se basa en la arquitectura Modelo-Vista-Controlador, en la que se
basan Swing y JFace.


La arquitectura MVC separa los objetos del dominio (el modelo) de la interfaz de
usuario (la vista) y de la lgica que los controla (el controlador). Consideremos, por
ejemplo, un componente de tipo lista. Su modelo son los datos; la vista es la
representacin en pantalla de la lista; por ltimo, el controlador es la parte del
componente que gestiona la interaccin con el usuario (pulsacin de teclas, del ratn,
etc.). Usando juiciosamente esta arquitectura, un mismo modelo se puede mostrar
mediante muchas vistas: por ejemplo, una serie de datos se puede mostrar como un
grfico circular, como una curva o como una tabla.
En la arquitectura MVC ms general posible, el modelo se encarga de acceder a la
capa de almacenamiento de datos, especifica las reglas de negocio (una cuenta no debe
tener un saldo negativo, por ejemplo), controla las vistas y los controladores y notifica a
las vistas los cambios de los datos. El controlador se encarga de gestionar los sucesos
de entrada (verbigracia, si el usuario apretara un botn Aceptar, el controlador llamara
al mtodo actualizar() de la vista y al mtodo actualizarSaldo() del modelo). La vista, en
fin, se encarga de recibir los datos del modelo y de mostrarlos al usuario; para ello,
conserva un registro del controlador al que est vinculado y suele tener algn mtodo de
actualizacin que puede ser llamado por el controlador o por el modelo.

En la figura 62 se muestra cmo procesa la arquitectura MVC los sucesos de los
usuarios:

1) El usuario genera un suceso.

2) El controlador recibe el suceso y lo transforma en una peticin al modelo.

3) El modelo se actualiza y avisa a la vista de que debe actualizarse.

4) La vista pide datos al modelo para poder actualizarse; luego, actualiza la
representacin de los datos.

5) El controlador retoma el control.

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 99 de 114












































Figura 61. Representacin esttica de la arquitectura MVC. Dibujo de Juan Carlos
Dueas Lpez



El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 100 de 114







































Figura 62. Representacin dinmica de la arquitectura MVC. Dibujo de Juan
Carlos Dueas Lpez


En el caso concreto de JFace, una clase Viewer (visor) corresponde a la parte de la
vista y se encarga de presentar una interfaz ms simple que la del widget que debe
mostrar los datos. Entre los mtodos ms usados de la interfaz se encuentran los que
sirven para aadir o eliminar elementos de la coleccin de datos mostrados por el widget.
De manera general, los visores (viewers) tienen asociados proveedores de
contenidos (content providers) y proveedores de etiquetas (label providers). Cuando un
visor recibe un suceso, pregunta al visor qu debe hacer, es decir, qu elemento o
elementos debe mostrar u ocultar. En una estructura de datos como un rbol, el
proveedor de contenidos almacena la informacin sobre el hijo o el padre de cada

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 101 de 114
elemento almacenado en la estructura. Asimismo, mediante llamadas a mtodos de tipo
refresh(), update(), add() y remove(), el proveedor de contenidos avisa al visor de los
cambios en el modelo. Los proveedores de etiquetas son utilizados por los visores para
averiguar qu texto y qu imagen deben asociarse a cada elemento del modelo.
Los widgets de tipo Table, List, Tree, etc., tienen asociados subclases de Viewer
(TableViewer, ListViewer, TreeViewer, TableTreeViewer, TextViewer,
CheckboxTreeViewer, CheckboxTableViewer), por medio de las cuales se manipulan los
datos. En las siguientes pginas se muestran dos ejemplos de uso de la clase
ListViewer. En uno no se usan explcitamente proveedores de contenido ni de etiquetas;
en el otro s.






import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.*;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;

/*
* Esta clase utiliza un visor ListViewer para controlar los elementos
* de una lista. Si se hace doble clic sobre un elemento, ste se muestra por
* consola.
*
* Las subclases de Viewer (ListViewer, TreeViewer, TableViewer...) permiten
* trabajar con objetos de un dominio (elementos) y mostrarlos como widgets
* SWT, sin que el programador tenga que preocuparse de pasar del elemento
* al widget, ni viceversa, ni de mantenerlos sincronizados.
*
*/

public class EjemploViewer extends ApplicationWindow {

private ListViewer visor;

public EjemploViewer() {
super(null);
}

public static void main(String args[]) {
EjemploViewer ventana = new EjemploViewer();
ventana.setBlockOnOpen(true);
ventana.open();

Display.getCurrent().dispose();
}

protected Control createContents(Composite padre) {
visor = new ListViewer(padre, SWT.SINGLE);

// Se crean los objetos del dominio.
int i = 1;
while (i <= 10) {
Ejemplo 34: EjemploViewer.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 102 de 114
visor.add(new ElementoLista(i));
i++;
}

// Si se hace doble clic en un elemento de la lista, se
// muestra el elemento por consola.
visor.addDoubleClickListener(
new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent e) {
IStructuredSelection selection =
(IStructuredSelection) e.getSelection();
System.out.println("Ha hecho clic en " +
selection.getFirstElement().toString());
}
});

return visor.getList();
}

}

// Clase que define el modelo de objetos.
class ElementoLista {

private String texto;

public ElementoLista(int i) {
texto = "Elemento nmero " + i;
}
public String toString() {
return texto;
}

}

















Figura 63. Resultado de ejecutar la clase EjemploViewer

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 103 de 114





import org.eclipse.jface.window.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.*;
import org.eclipse.swt.layout.*;

/*
* Esta clase utiliza Nota, ListaNotas, ListaNotasContentProvider y
* ListaNotasLabelProvider para manipular una lista de notas. Al
* seleccionar el nombre de un alumno, se muestra por consola su
* nota.
*
*/

public class EjemploViewer2 extends ApplicationWindow {

public EjemploViewer2() {
super(null);
}

public static void main(String[] args) {
EjemploViewer2 ventana = new EjemploViewer2();
ventana.setBlockOnOpen(true);
ventana.open();
Display.getCurrent().dispose();
}
public Control createContents(Composite padre) {
getShell().setText("Lista de notas de Ampliacin de Mecnica Cuntica");
Composite composite = new Composite(padre, SWT.NONE);

FillLayout layout = new FillLayout(SWT.HORIZONTAL);
composite.setLayout(layout);
Label etiqueta= new Label(padre, SWT.CENTER);
etiqueta.setText("Saludos con JFace");

ListViewer visorLista = new ListViewer(composite, SWT.H_SCROLL);
visorLista.setContentProvider(new ListaNotasContentProvider());
visorLista.setInput(new ListaNotas());
visorLista.setLabelProvider(new ListaNotasLabelProvider());

// Gestin de sucesos. Al seleccionarse un alumno, se muestra
// por consola su nota.
visorLista.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent e) {
IStructuredSelection selection = (IStructuredSelection) e.getSelection();
Nota nota = (Nota) selection.getFirstElement();
System.out.println(nota.getNombreAlumno());
}
});

return composite;
Ejemplo 35a: EjemploViewer2.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 104 de 114
}

}





/**
* Esta clase es el modelo de objetos del ejemplo nmero 35.
* Cada objeto Nota representa la nota de un alumno de la
* asignatura Ampliacin de Mecnica Cuntica.
*
*/

public class Nota {

private String nombreAlumno;
private double calificacion;

public Nota(String nombreAlumno, double calificacion) {
this.nombreAlumno = nombreAlumno;
this.calificacion = calificacion;
}

// Mtodos get
public String getNombreAlumno() {
return nombreAlumno;
}

public String getCalificacion() {
return Double.toString(calificacion);
}

}





import java.util.*;

/**
* Esta clase define una lista de objetos Nota.
*
*/

public class ListaNotas {

private List listaNotas = new ArrayList(8);

public ListaNotas() {
rellenarLista();
}

private void rellenarLista() {
Ejemplo 35b: Nota.java
Ejemplo 35c: ListaNotas.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 105 de 114
listaNotas.add(new Nota("Luis Rodrigo", 6.7));
listaNotas.add(new Nota("Jos ngel Marn", 7.1));
listaNotas.add(new Nota("Gustavo Poler", 9.3));
listaNotas.add(new Nota("Jos Luis Albiach", 7.8));
listaNotas.add(new Nota("Fedrico Monslvez", 6.2));
listaNotas.add(new Nota("Donal Piddington", 9.2));
listaNotas.add(new Nota("Rosa Prez", 6.9));
listaNotas.add(new Nota("Rosa Igual", 7.5));
}

public Object[] getListaNotas() {
return listaNotas.toArray();
}

}






import org.eclipse.jface.viewers.*;

/**
* Esta clase acta como proveedor de contenidos. Para ello, implementa
* IStructuredContentProvider, interfaz que debe implementar cualquier
* proveedor de contenidos que medie entre el visor y su modelo.
*
*/

public class ListaNotasContentProvider implements IStructuredContentProvider {

// Este mtodo devuelve los elementos que deben mostrarse en el visor
// cuando su entrada se establece a un elemento.
public Object[] getElements(Object elementoEntrada) {
return ((ListaNotas) elementoEntrada).getListaNotas();
}

// Este mtodo notifica al proveedor de contenido que la entrada del usuario ha
// cambiado de un objeto a otro.
// En este ejemplo no es necesario implementarlo.
public void inputChanged(Viewer visor, Object objetoAntiguo, Object objetoNuevo) { }

// Libera los contenidos del proveedor de contenidos. Cuando se llama al mtodo
// dispose() del visor, ste llama a este mtodo.
// En este ejemplo no es necesario implementarlo.
public void dispose() { }

}

Ejemplo 35d: ListaNotasContentProvider.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 106 de 114




import org.eclipse.jface.viewers.*;
import org.eclipse.swt.graphics.*;

/**
* Esta clase acta como proveedor de etiquetas. Para ello, implementa
* ILabelProvider, interfaz usada por muchos visores (excepto TableViewer), y
* extiende la clase LabelProvider, que es una implementacin por omisin de
* ILabelProvider y que usa un String para el texto de cada elemento, y
* null para cada imagen.
*
*/

public class ListaNotasLabelProvider extends LabelProvider implements ILabelProvider {

// Devuelve un String para el elemento.
public String getText(Object elemento) {
return ((Nota) elemento).getNombreAlumno();
}
// En general, devuelve una imagen para el elemento.
// En este ejemplo, no devuelve ninguna (null).
public Image getImage(Object elemento) {
return null;
}

}


















Figura 64. Resultado de ejecutar la clase EjemploViewer2

Ejemplo 35e: ListaNotasLabelProvider.java

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 107 de 114

En el siguiente ejemplo se muestra cmo trabajar con asistentes (wizards).




import org.eclipse.swt.widgets.*;
import org.eclipse.jface.wizard.WizardDialog;

/**
* Esta clase muestra un asistente que permite elegir la pgina a la que
* se quiere ir (pgina 1, 2 o 3). Para ello, usa las clases PaginaSeleccion,
* AsistentePagina, Pagina1, Pagina2 y Pagina3.
*
*/

public class EjemploWizard {

public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);

// Se crea el dilogo de asistente y se muestra.
WizardDialog dialogoAsistente = new WizardDialog(shell, new AsistentePagina());
dialogoAsistente.open();

display.dispose();
}

}




import org.eclipse.jface.wizard.Wizard;

/**
* Esta clase especifica las pginas contenidadas en el asistente y su comportamiento
* cuando se pulsa el botn Finish (Finalizar) del asistente.
*
*/

public class AsistentePagina extends Wizard {

public AsistentePagina() {
// Se aaden las pginas.
addPage(new PaginaSeleccion());
addPage(new Pagina1());
addPage(new Pagina2());
addPage(new Pagina3());
}

// Respuesta cuando el usuario aprieta el botn Finish
public boolean performFinish() {
System.out.println("Se sale del asistente");
return true; // true indica que se cierra el asistente
Ejemplo 36a: EjemploWizard.java
Ejemplo 36b: AsistentePagina.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 108 de 114
}

}






import org.eclipse.swt.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;

/**
* Esta clase representa la pgina que permite al usuario elegir a qu pgina
* desea ir. Es una subclase de WizardPage.
*/

public class PaginaSeleccion extends WizardPage {

private Button pagina1;
private Button pagina2;
private Button pagina3;

public PaginaSeleccion() {
super("Pgina de seleccin ");
}

// Se crean los controles de la pgina.
public void createControl(Composite padre) {
Composite compo1 = new Composite(padre, SWT.NONE);
compo1.setLayout(new GridLayout(3, true));

Composite compo2 = new Composite(compo1, SWT.NONE);
compo2.setLayout(new FillLayout(SWT.VERTICAL));

Label etiqueta = new Label(compo1, SWT.LEFT);
etiqueta.setText("A qu pgina desea desplazarse?");

pagina1 = new Button(compo2, SWT.RADIO);
pagina1.setText("Pgina 1");

pagina2 = new Button(compo2, SWT.RADIO);
pagina2.setText("Pgina 2");

pagina3 = new Button(compo2, SWT.RADIO);
pagina3.setText("Pgina 3");

setControl(compo1);
}




Ejemplo 36c: PaginaSeleccion.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 109 de 114
// Se implementa el mtodo getNextPage() de la interfaz IWizardPage,
// La clase WizardPage proporciona una implementacin general de esta interfaz, pero
// se implementa la interfaz directamente porque esa implementacin no basta para la lgica
// de la aplicacin.
public IWizardPage getNextPage() {
if (pagina1.getSelection()) {
return getWizard().getPage("Pgina 1");
}
if (pagina2.getSelection()) {
return getWizard().getPage("Pgina 2");
}
if (pagina3.getSelection()) {
return getWizard().getPage("Pgina 3");
}
// Por omisin, se va a la primera pgina.
return getWizard().getPage("Pgina 1");
}

}





import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*; // incluye la clase Color
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;

/**
* Esta clase representa la pgina 1. Es una subclase de
* WizardPage.
*
*/

public class Pagina1 extends WizardPage {

public Pagina1() {
super("Pgina 1");
}

// Se crean los controles para la pgina.
public void createControl(Composite padre) {
Label etiqueta = new Label(padre, SWT.CENTER);
etiqueta.setText("Est en la pgina 1");
etiqueta.setForeground(new Color(null, 15, 134, 250));
etiqueta.setBackground(new Color(null, 100, 14, 50));
setControl(etiqueta);
}

}


Ejemplo 36d: Pagina1.java
El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 110 de 114





import org.eclipse.swt.graphics.*; // incluye la clase Color
import org.eclipse.swt.widgets.*;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;

/**
* Esta clase representa la pgina 2. Es una subclase de
* WizardPage.
*
*/

public class Pagina2 extends WizardPage {

public Pagina2() {
super("Pgina 2");
}

// Se crean los controles para la pgina.
public void createControl(Composite padre) {
Text cuadroTexto = new Text(padre, SWT.CENTER| SWT.BORDER | SWT.READ_ONLY);
cuadroTexto.setText("Est en la pgina 2");
cuadroTexto.setForeground(new Color(null, 237, 14, 50));
cuadroTexto.setBackground(new Color(null, 15, 14, 50));
setControl(cuadroTexto);
}

}





import org.eclipse.swt.widgets.*;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;

/**
* Esta clase representa la pgina 3. Es una subclase de
* WizardPage.
*
*/

public class Pagina3 extends WizardPage {

public Pagina3() {
super("Pgina 3");
}

// Se crean los controles para la pgina
public void createControl(Composite padre) {
Button boton= new Button(padre, SWT.CENTER | SWT.BORDER );
Ejemplo 36e: Pagina2.java
Ejemplo 36f: Pagina3.java
http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 111 de 114
boton.setText("Est en la pgina 3");
setControl(boton);
}

}





































Figura 65. Resultado de ejecutar la clase EjemploWizard



El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 112 de 114



























Figura 66. Pantalla que aparece cuando se escoge en el asistente la pgina 2


Cuando se desea usar objetos Color, Font o Image de manera que su ciclo de vida
est asociado al widget que los utiliza, se pueden usar las clases ColorRegistry,
FontRegistry e ImageRegistry, respectivamente. As se evita tener que liberar
explictamente los objetos Color, Font e Image innecesarios.
ColorRegistry, FontRegistry e ImageRegistry permiten tambin almacenar
permanentemente colores, tipos de letra e imgenes, de modo que puedan ser
compartidas por distintos widgets o accedidas frecuentemente. El uso tpico de estas
clases se muestra en este ejemplo:

...
String IMAGEN_1 = "imagen1";

// Se crea un descriptor de la imagen y su registro.
ImageRegistry ir = new ImageRegistry();
ImageDescriptor id = ImageDescriptor.createFromFile(...);
registry.put(IMAGEN_1, id);

// Se crea la imagen y se asocia al registro.
// Si se destruye el display asociado al shell, se
// destruye la imagen.
Label etiqueta = new Label(shell, SWT.CENTER);
Image imagen = ir.get(IMAGEN_1);
etiqueta.setImage(imagen);

http://www.javahispano.org
Miguel ngel Abin, 2005-2014 Pgina 113 de 114
Como el lector habr podido apreciar, JFace abastece al desarrollador de una serie
de clases que simplifican ms que SWT la construccin de interfaces grficas. Para la
mayor parte de los usos, se puede usar JFace directamente.
Con JFace no terminan las posibilidades de Eclipse: la plataforma de clientes ricos
de Eclipse (Rich Cliente Platform o RCP) permite construir muy rpidamente
workbenches (bancos de trabajo) de Eclipse y compilarlos en aplicaciones que pueden
ejecutarse sin Eclipse. Un cliente rico es aquel cliente que aprovecha las posibilidades
del sistema operativo donde se ejecuta. El programador puede usar la RCP para
construir el armazn grfico de sus propias aplicaciones, con la ventaja aadida de
disponer de una interfaz grfica impactante, moderna y profesional: la del propio Eclipse.
En la figura 67 se muestra una aplicacin, construida con la RCP de Eclipse, que
permite seguir en directo las cotizaciones burstiles.




























Figura 67. Captura de pantalla extrada de http://eclipse.org/rcp/


Glosar todas funciones de la RCP y ejemplificarlas cae, por mucho, fuera de los
propsitos de esta serie de artculos, pues hay muchsimas cosas ms que contar. Al
lector interesado en saber qu partido puede sacarle a la RCP de Eclipse le recomiendo
que le eche un vistazo a JLibrary (http://jlibrary.javahispano.net/es/index.html), obra de
Martn Prez. Poco de favoritismo hay en mi recomendacin: JLibrary es una aplicacin
bien til, usa con maestra casi todas las funciones relevantes de la RCP y est en
espaol. En definitiva: miel sobre hojuelas. Si no incluyo ninguna captura de pantalla es
por timidez, no vaya a ser que escoja una poco agraciada y luego me caiga encima
alguna lluvia de bien merecidos reproches...

El archipilago Eclipse (parte 4 de 4)
Miguel ngel Abin, 2005-2014 Pgina 114 de 114













In memoriam: Este artculo est dedicado a la memoria de Josefa Jimnez
Melendo (Portillo de Soria, 1917-Valencia, 2005). Se fue en enero, cuando el
cierzo ms azota los pueblos de su Castilla natal, esa Castilla cada vez ms
olvidada y empobrecida, cada vez ms transformada en coto de caza y en
residencia geritrica. En paz descanse.
Sobre el autor:

Miguel ngel Abin naci en Soria. Obtuvo la suficiencia investigadora en el Dpto. de
Fsica Aplicada de la Universidad de Valencia con una tesina sobre electromagnetismo.
Realiz varios cursos de doctorado relacionados con electromagnetismo, electrnica,
semiconductores y cristales fotnicos. Ha recibido becas del IMPIVA (Instituto de la Mediana
y Pequea Industria Valenciana) y de la Universidad Politcnica de Valencia. Curs un
Mster estadounidense en UML y Java y otro sobre tecnologas de Internet/Intranet.
Se incorpor en 1998 a AIDIMA, donde ha participado como investigador en 23
proyectos de investigacin nacionales e internacionales relacionados con la Web semntica,
tecnologas de la informacin, madera en construccin, biosensrica, bioelectrnica,
telecomunicaciones, visin artificial; as como en la Red de Excelencia de la Comisin
Europea INTEROP 2003-2007. Algunos de los proyectos europeos relacionados con las
tecnologas semnticas en los que ha participado son ATHENA y STASIS (http://www.stasis-
project.net/).
El ao 2006 estuvo cuatro meses como investigador invitado en el departamento
Lehrstuhl fr Messsystem und Sensortechnik de la Universidad Politcnica de Munich (TUM),
donde colabor en el desarrollo de nuevos mtodos para la deteccin de defectos en
superficies acabadas y en el diseo e implementacin de sistemas distribuidos de sensores
para el sector del automvil y de energas renovables. En 2007 recibi un premio BANCAJA-
UPV por un proyecto relacionado con la calidad interna de la madera. En 2009 recibi el
premio internacional Schweighofer Innovation Prize -el premio ms prestigioso en el sector
forestal y de la madera- por su aportacin al desarrollo de nuevas tecnologas de evaluacin
no destructiva de la madera en construccin.
Actualmente es Responsable del Departamento de Tecnologa y Biotecnologa de la
Madera y del rea de Construccin de Madera.
Es coautor de 7 libros y guas tcnicas relacionadas con el uso de la madera en la
construccin y la visin artificial. Tambin ha publicado varios artculos cientficos en revistas
como IEEE Transactions on Microwave Theory and Techniques y Wood Science and
Technology. Ha participado como ponente en congresos y conferencias como European
Congress on Computational Methods in Applied Sciences and Engineering, IEEE
International Conference on Multisensor Fusion and Integration for Intelligent Systems,
International Conference on Space Structures (IABSE-IASS) y en reuniones COST
(European Cooperation in Science and Technology). Ha publicado ms de 24 artculos
tcnicos en revistas sectoriales y tcnicas.
Es autor o coautor de 8 patentes, algunas de ellas en trmite. Cuatro de ellas
corresponden a dispositivos y mtodos para detectar la biodegradacin de la madera en
construccin.
Actualmente, entre otros proyectos como WOODTECH, SHBUILDINGS, WOODRUB o
CELLUWOOD, ha trabajado en SEMCONCEPT, un proyecto de I+D+i para aplicar
tecnologas semnticas (ontologas, buscadores semnticos) en el diseo conceptual de
productos industriales.
Sus intereses actuales son la evolucin de la programacin orientada a objetos, Java,
la Web semntica y sus tecnologas, la arquitectura orgnica, el surrealismo y Pars, siempre
Pars.

Potrebbero piacerti anche