Applet Java con SWT

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

SWTApplet

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

Anuncios

Un pensamiento en “Applet Java con SWT

  1. Me estoy volviendo loca para hacer lo mismo y cargar el applet en mi navegador… snif snif. Podrias explciarme como paso de este codigo:
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.swt.widgets.Text;
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.widgets.Button;
    import org.eclipse.swt.widgets.Label;
    import org.eclipse.swt.events.SelectionAdapter;
    import org.eclipse.swt.events.SelectionEvent;
    import org.eclipse.wb.swt.SWTResourceManager;

    public class ejercicios_repaso{

    protected Shell shell;
    private Text txtNumero;
    private Label lblArbol;
    private Text textintoFrase;
    private int numMay;
    private Label lblNumerodemayusculas;
    private Button btnContar;
    private Button btnArbol;
    private Text textTlf;
    private Button btnNewTel;
    private Label lblNewTel;

    /**
    * Launch the application.
    * @param args
    */
    public static void main(String[] args) {
    try {
    ejercicios_repaso window = new ejercicios_repaso();
    window.open();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    /**
    * Open the window.
    */
    public void open() {
    Display display = Display.getDefault();
    createContents();
    shell.open();
    shell.layout();
    while (!shell.isDisposed()) {
    if (!display.readAndDispatch()) {
    display.sleep();
    }
    }
    }

    /**
    * Create contents of the window.
    */
    protected void createContents() {
    shell = new Shell();
    shell.setSize(722, 660);
    shell.setText(“SWT Application”);

    txtNumero = new Text(shell, SWT.BORDER);
    txtNumero.setText(“numero”);
    txtNumero.setBounds(10, 8, 76, 21);

    lblArbol = new Label(shell, SWT.NONE);
    lblArbol.setFont(SWTResourceManager.getFont(“Courier New”, 9, SWT.NORMAL));

    lblArbol.setBounds(10, 50, 309, 391);
    lblArbol.setText(“Arbol:”);

    textintoFrase = new Text(shell, SWT.BORDER);
    textintoFrase.setText(“Intorduzca una frase”);
    textintoFrase.setBounds(346, 23, 226, 21);

    lblNumerodemayusculas = new Label(shell, SWT.NONE);
    lblNumerodemayusculas.setText(“Numero mayusculas:”);
    lblNumerodemayusculas.setBounds(346, 50, 235, 15);

    btnContar = new Button(shell, SWT.NONE);
    btnContar.addSelectionListener(new SelectionAdapter() {
    @Override
    public void widgetSelected(SelectionEvent e) {

    String frase = textintoFrase.getText();

    numMay = contarLetrasMayusculas(frase);
    lblNumerodemayusculas.setText(“Nº MAYUSUCLAS = ” + String.valueOf(numMay));
    }
    });
    btnContar.setBounds(585, 23, 75, 25);
    btnContar.setText(“Contar MAY”);

    btnArbol = new Button(shell, SWT.NONE);
    btnArbol.addSelectionListener(new SelectionAdapter() {
    @Override
    public void widgetSelected(SelectionEvent e) {
    //cojo el número del textBox
    int n=0;

    try
    {
    n = Integer.parseInt(txtNumero.getText()); //cojo el texto y lo trunco a entero
    }
    catch (Exception exc)
    {
    lblArbol.setText(“Introduza un entero”);
    return;
    }
    String arbol = generarArbol(n); //lamo al metodo

    lblArbol.setText(arbol); //dinujo el string
    }
    });
    btnArbol.setBounds(100, 6, 75, 25);
    btnArbol.setText(“Crear”);

    textTlf = new Text(shell, SWT.BORDER);
    textTlf.setText(“cual es su numero tel?”);
    textTlf.setBounds(346, 116, 226, 21);

    btnNewTel = new Button(shell, SWT.NONE);
    btnNewTel.addSelectionListener(new SelectionAdapter() {
    @Override
    public void widgetSelected(SelectionEvent e) {
    //cojo el campo de texto
    String cad_tel = textTlf.getText();

    //pruebas telefono encontrado/no encontrado en el debug
    boolean telefono = false;

    telefono = encontrarTelefono(cad_tel);

    lblNewTel.setText(“Telefono encontrado:” + telefono );
    }
    });
    btnNewTel.setBounds(585, 116, 92, 25);
    btnNewTel.setText(“Hay tel\u00E9fono?”);

    lblNewTel = new Label(shell, SWT.NONE);
    lblNewTel.setBounds(346, 155, 226, 15);
    lblNewTel.setText(“\u00BFHay telefono?:”);

    //Pruebas debug sumas vector de floats
    float[] vector = new float[]{1,0.2f,6,2.5f};
    calcularSumaElementos(vector);

    //Pruebas debug matrizIdentidad
    //matriz de 2X2 2 filas 2 columnas
    int matriz[][] = new int[][]{{2,2},{3,6}};

    //matriz de 2X3 2 filas 3 columnas
    /*
    int matriz [][] = new int[2][3];
    matriz[0][0]= 2;
    matriz[0][1]= 2;
    matriz[0][2]= 3;
    matriz[1][0]= 5;
    matriz[1][1]= 6;
    matriz[1][2]= 8;
    */

    asignarMatrizIdentidad(matriz);
    }

    //genero un arbol introduciendo un numero
    private String generarArbol(int n)
    {
    String result=””;

    //recorremos todas las filas
    for (int fila=1; fila<=n; fila++)
    {
    //recorremos las columnas
    for (int col =1; col 2
    private int contarLetrasMayusculas (String frase)
    {
    int result = 0;

    //con un for recorrer toda la frase
    for (int i=0; i true
    //Ejemplo “Mi teléfono es 654 23 34 44” –> false
    //Ejemplo “Mi teléfono es 65412345678″ –> false
    private boolean encontrarTelefono (String cadena)
    {
    int cont = 0; //contador num encontrados consecutivos
    int i;
    //recorro la cadena
    for(i=0; i<cadena.length(); i++)
    {
    //Busco numeros 6 7 ó 9
    if(cadena.charAt(i)=='6' || cadena.charAt(i)=='7' || cadena.charAt(i)=='9')
    {
    //recorro la subcadena en busca de 8 numeros siguientes
    for(int j=0; j telefono ok
    if(cont==8)
    return true;
    else
    return false;
    }

    //calcula la suma de los elementos de un vector
    // [3 4 5 1] –> 13
    private float calcularSumaElementos(float v[])
    {
    float result = 0.0f;
    for(int i=0; i<v.length;i++)
    result=result+v[i];
    return result;
    }

    //Me genera la matriz identidad de una matriz dada
    //Atencion: La matriz dada se sobreescribe
    private void asignarMatrizIdentidad (int m[][])
    {

    int col = m[0].length; //calculo longitud indice de las columnas
    int fil = m.length; //calculo longitud indice de las filas

    //Si matriz es cuadradra… si no es cuadrada nada
    if(col==fil)
    {
    for(int colum=0; colum<m.length;colum++)
    {
    for(int filas=0; filas es la diagonal de la matriz
    else
    m[colum][filas]=0; //resto elementos
    }
    }
    }
    }

    }

    a un applet? decirte que tengo una clase Cadena en otro paquete:
    el codigo es:

    public class Cadena {

    /*Spublic String Cadena()
    {
    tring result =””;

    result = result.concat( dia + “/”);
    result = result + mes + “/” + anyo;

    return result;
    }*/

    public static Boolean esMayuscula (char c)
    {
    //rango es ascii de las mayusculas
    if(c>=65 && c=’0′ && c<='9')
    return true;
    else
    return false;
    }
    }

    Gracias por la ayyuda que puedas ofrecerme… pensaba que seria más fácil con algun plugin converter o algo asi…

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s