Ya me he estado inclinando mucho con Ubuntu, pero ya regrese a Java, y como siempre intentando publicar cosas nuevas o que si existen, estas llegan a ser muy confusas o complicadas de entender, en esta ocasión les traigo hasta ustedes la utilización de SWT en applets Java.
SWT ha empezado a gustarme, ya que tiene una excelente integración con el escritorio ya se ha windows, linux, mac u otro, y aunque SWT recibe muchas criticas por ser denominado “incompleto”, quiero aplaudir al impresionante trabajo de los desarrolladores, ya que unificar todas las diferentes API de componentes visuales en una, es una tarea titánica…
Recientemente estuve intentando integrar SWT dentro de un applet y la verdad es que los ejemplos que se encuentran en internet son escasos y confusos además de no funcionar en Linux, y de los que funcionan en windows tienen problemas con manejo de cambio de Foco con TAB y la invocación del botón predeterminado.
Finalmente logre desarrollar una pequeña clase para utilizar SWT en applet

Y se utiliza como:
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class MiSWTApplet extends SWTApplet {
static {
Display.setAppName("MiSWTApplet");
}
@Override
protected void createGUI(Shell shell) {
shell.setLayout(new RowLayout());
new Button(shell, SWT.PUSH).setText("Botón 1");
new Button(shell, SWT.PUSH).setText("Botón 2");
new Text(shell, SWT.SINGLE | SWT.BORDER).setMessage("Texto...");
}
@Override
protected void destroyGUI() {
}
}
Realmente la que hace todo el trabajo es la clase SWTApplet:
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JApplet;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
abstract public class SWTApplet extends JApplet {
static {
System.setProperty("sun.awt.xembedserver", "true");
}
private Display display;
private Shell shell;
private Canvas canvas;
private Control focusControl;
protected Display getDisplay() {
return display;
}
abstract protected void createGUI(Shell shell);
abstract protected void destroyGUI();
private void buildSWTBase() {
display = new Display();
// activar soporte para TAB y SHIF-TAB
display.addFilter(SWT.FocusIn, new Listener() {
@Override
public void handleEvent(Event event) {
focusControl = (Control)event.widget;
}
});
// -----------------------------------
shell = SWT_AWT.new_Shell(display, canvas);
createGUI(shell);
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
destroyGUI();
display.dispose();
}
@Override
public void start() {
// agregar contenedor Swing
canvas = new Canvas();
canvas.setFocusable(true);
this.setLayout(new BorderLayout());
this.add(canvas, BorderLayout.CENTER);
// ------------------------
// crear interface SWT
new Thread() {
@Override
public void run() {
buildSWTBase();
};
}.start();
// -------------------
// activar soporte para TAB y SHIF-TAB
canvas.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
final KeyEvent _e = e;
display.syncExec(new Runnable() {
@Override
public void run() {
if (_e.getKeyCode() == KeyEvent.VK_TAB
&& _e.getModifiers() == 0)
focusControl.traverse(SWT.TRAVERSE_TAB_NEXT);
else if (_e.getKeyCode() == KeyEvent.VK_TAB
&& _e.getModifiers() == KeyEvent.SHIFT_MASK)
focusControl.traverse(SWT.TRAVERSE_TAB_PREVIOUS);
else if (_e.getKeyCode() == KeyEvent.VK_ENTER
&& _e.getModifiers() == 0)
if (shell.getDefaultButton() != null &&
shell.getDefaultButton().isVisible())
shell.getDefaultButton().notifyListeners(
SWT.Selection, null);
}
});
}
});
// -----------------------------------
}
}
Como funciona eso: Bueno, primero para empezar por que no funciona con GTK. Se debe a que para los Unix es necesario utilizar XEmbed protocol para poder incorporar una interfaces GTK sobre un display X11 (que es java), así que solo es necesario activar el soporte para XEmbed.
static {
System.setProperty("sun.awt.xembedserver", "true");
}
Segundo, una vez logrado visualizar el Shell SWT dentro de un Applet los acceso rápidos estándar como TAB (para establecer el foco en el siguiente componente) y Shif+TAB (para regresar el foco) no funcionan, ya que estos eventos son capturados por el objeto Canvas, para solucionarlo es necesario transferir estos eventos de teclado a la interface SWT en el applet.
canvas.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
final KeyEvent _e = e;
display.syncExec(new Runnable() {
@Override
public void run() {
if (_e.getKeyCode() == KeyEvent.VK_TAB
&& _e.getModifiers() == 0)
focusControl.traverse(SWT.TRAVERSE_TAB_NEXT);
else if (_e.getKeyCode() == KeyEvent.VK_TAB
&& _e.getModifiers() == KeyEvent.SHIFT_MASK)
focusControl.traverse(SWT.TRAVERSE_TAB_PREVIOUS);
else if (_e.getKeyCode() == KeyEvent.VK_ENTER
&& _e.getModifiers() == 0)
if (shell.getDefaultButton() != null &&
shell.getDefaultButton().isVisible())
shell.getDefaultButton().notifyListeners(
SWT.Selection, null);
}
});
}
});
Esta clase es preliminar, pero es una muy buena base para comenzar a utilizar SWT en un applet.
Ahora para poder hacer el deploy del applet en Web es necesario cargar la librería SWT especifica para cada sistema operativo y arquitectura. Esto se hace utilizando Applet con JNLP.
El archivo HTML debe quedar:
<applet name="MiSWTApplet" title="MiSWTApplet" alt="MiSWTApplet" width="300" height="100" codebase="." code="mipaquete.MiSWTApplet"> <param name="jnlp_href" value="miswtapplet.jnlp"/> </applet>
Y el archivo JNLP (miswtapplet.jnlp) debe quedar:
<?xml version="1.0" encoding="UTF-8"?> <jnlp spec="6.0+" codebase="." href="miswtapplet.jnlp"> <information> <title>MiSWTApplet</title> <vendor>Dan Jared</vendor> </information> <security> <all-permissions/> </security> <resources> <j2se version="1.6+"/> <jar href="miswtapplet.jar" main="true"/> <jar href="alguna-dependencia.jar"/> </resources> <resources os="Windows" arch="x86"> <jar href="swt-win32-windows-x86.jar" /> </resources> <resources os="Windows" arch="x86_64"> <jar href="swt-win32-windows-x86_64.jar" /> </resources> <resources os="Windows" arch="amd64"> <jar href="swt-win32-windows-x86_64.jar" /> </resources> <resources os="Linux" arch="ppc"> <jar href="swt-gtk-linux-ppc.jar" /> </resources> <resources os="Linux" arch="x86_64"> <jar href="swt-gtk-linux-x86_64.jar" /> </resources> <resources os="Linux" arch="amd64"> <jar href="swt-gtk-linux-x86_64.jar" /> </resources> <resources os="Linux"> <jar href="swt-gtk-linux-x86.jar" /> </resources> <resources os="SunOS" arch="sparc"> <jar href="swt-gtk-solaris-sparc.jar" /> </resources> <resources os="SunOS" arch="x86"> <jar href="swt-gtk-solaris-x86.jar" /> </resources> <applet-desc name="MiSWTApplet" main-class="mipaquete.MiSWTApplet" width="300" height="100"> </applet-desc> </jnlp>
Otro punto muy importante es firmar los jar tanto los jars “miswtapplet.jar” así como los jar de SWT. Para esto ya es algo más común así que solo les dejare una liga de como hacer esto:
Este se me hizo muy bueno: Signing jars for java.net Web Start applications