Ventanas splash.
Fecha de creación: 01.09.2002
Revisión 1.0.1 (30.01.2003)
Pedro Del Gallego Vida
akipelli AT hotmail DOT com
| Traducción: Copyright (c) 2002, Pedro Del Gallego Vida. Este documento puede ser distribuido solo bajo los términos y condiciones de la licencia de Documentación de javaHispano v1.0 o posterior (la última versión se encuentra en /licencias/). El copyright del original pertence a Tony Colston. |
|
La mayoría de las aplicaciones actuales tienen una ventana splash. Usar una ventana splash es una forma de avisar al usuario de que algo esta ocurriendo en nuestra aplicación, durante el largo periodo de arranque. Algunas ventanas splash pueden ser cerradas pinchando en cualquier lugar de ellas, otras son visibles solo durante el proceso de carga, en cambio otras son siempre visibles después de que la aplicación haya comenzado.
No te gustaría que fuese posible hacer todas estas cosas con Java? Usando Swing con hilos (threads), podemos hacerlo.
Aquí tienes la primera clase para una ventana splash creada para ser usada en una aplicación.
class SplashWindow1 extends JWindow
{
public SplashWindow1(String filename, Frame f)
{
super(f);
//-------- Creo una etiqueta para mostrar la imagen
JLabel l = new JLabel(new ImageIcon(filename));
//-------- Añado la etiqueta al contenedor
getContentPane().add(l, BorderLayout.CENTER);
pack();
//-------- calculo el tamaño de la pantalla
Dimension screenSize =
Toolkit.getDefaultToolkit().getScreenSize();
Dimension labelSize = l.getPreferredSize();
//--------- Situo la ventana en el centro de la pantalla
setLocation(screenSize.width/2 - (labelSize.width/2),
screenSize.height/2 - (labelSize.height/2));
//--------- Hago visible la pantalla
setVisible(true);
screenSize = null;
labelSize = null;
}
}
La clase SplashWindow1 hereda de la clase Swing JWindow. JWindow es un contenedor pesado. Este no tiene los elementos normales que aparecen en otras ventanas, como botones de control de ventanas (cerrar, minimizar, maximizar), barra para el nombre de la ventana o los bordes del frame. Por esto JWindow es perfecto para crear ventanas splahs. El código anterior asume que la imagen esta localizada en el directorio de trabajo. Esta imagen es cargada mediante de una clase ImageIcon, la imagen es situada en el centro del JWindow. El JWindow esta diseñado para dejar a Swing que calcule el tamaño apropiado, y después la desplace hasta el centro de la pantalla y entonces la hace visible.
Si ejecutamos el codigo anterior, desafortunadamente tendremos una ventana splash centrada, que no puede se cerrada!. Para hacer que se cierre tendremos que añadir:
class SplashWindow2 extends JWindow
{
public SplashWindow2(String filename, Frame f)
{
// ---- Este código es igual al anterior
super(f);
JLabel l = new JLabel(new ImageIcon(filename));
getContentPane().add(l, BorderLayout.CENTER);
pack();
Dimension screenSize =
Toolkit.getDefaultToolkit().getScreenSize();
Dimension labelSize = l.getPreferredSize();
setLocation(screenSize.width/2 - (labelSize.width/2),
screenSize.height/2 - (labelSize.height/2));
//------ Añado el MouseListener para que cuando haga click
//------ desaparezca la ventana
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
setVisible(false);
dispose();
}
});
setVisible(true);
}
}
La única diferencia en esta versión de la clase SplashWindow, es que ahora tenemos un MouseListener anónimo instalado en nuestra JWindow. Ahora cuando el usuario haga un click sobre la ventana splash esta desaparecerá.
En este punto, tendremos nuestra bonita ventana splash, que puede ser eliminada pero que no desaparece sola.Tendremos que añadir mas código para que pasado cierto tiempo la ventana desaparezca. Esta vez tendremos que introducir hilos en nuestra ventana.
class SplashWindow3 extends JWindow
{
public SplashWindow3(String filename, Frame f, int waitTime)
{
//---- Código igual al anterior
super(f);
JLabel l = new JLabel(new ImageIcon(filename));
getContentPane().add(l, BorderLayout.CENTER);
pack();
Dimension screenSize =
Toolkit.getDefaultToolkit().getScreenSize();
Dimension labelSize = l.getPreferredSize();
setLocation(screenSize.width/2 - (labelSize.width/2),
screenSize.height/2 - (labelSize.height/2));
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
setVisible(false);
dispose();
}
});
//----- tiempo que estara visible la ventana, en milisegundos
final int pause = waitTime;
//----- Este es el objeto que cierra la ventana
final Runnable closerRunner = new Runnable()
{
public void run()
{
setVisible(false);
dispose();
}
};
//----- Este es el objeto que pone a dormir a closerRunner
//----- y captura las excepciones;
Runnable waitRunner = new Runnable()
{
public void run()
{
try
{
Thread.sleep(pause);
SwingUtilities.invokeAndWait(closerRunner);
}
catch(Exception e)
{
e.printStackTrace();
// can catch InvocationTargetException
// can catch InterruptedException
}
}
};
setVisible(true);
//----- aqui creamos y lanzamos el hilo
Thread splashThread = new Thread(waitRunner, "SplashThread");
splashThread.start();
}
}
La idea general es crear un objeto Thread, que representa un hilo, que será detenido un tiempo determinado. En el código anterior el hilo se duerme durante 4 segundos, cuando el hilo despierta cierra la ventana splash. No usaremos el hilo principal de la ventana splash ya que este es el que pinta los componentes y el que maneja los eventos de Swing.
Para rodear esta limitación Swing da la posibilidad a los programadores de crear objetos runnable. En este caso usaremos una clase closeRunner para que haga el trabajo sucio. Pasaremos un objeto Runnable al metodo estático SwingUtilities.invokeAndWait(). Este ejecutará el metodo run del objeto Runnable closeRunner, que es pasado al método. Mediante el uso de hilos separados para capturar el cierre de la ventana, la aplicación principal sera mostrada y estará activa detrás de la ventana splash.
Si queremos hacer una ventana splash que siempre sea visible y que el usuario no pueda eliminar, quitaremos el código que oculta la ventana splash. Si queremos una ventana splash que pueda ser cerrada manualmente por el usuario, podemos llamar a los metodos setVisible(false) y dispose() como en cualquier otra JWindow.
Conclusión
Mediante el uso del método SWingUtilities.invokeAndWait(), podemos crear una ventana splash multihilo segura. El usuario puede hacer click en la ventana y eliminarla, o la ventana splash puede desaparecer por si misma pasado el tiempo que le digamos.
Para usar esta clase no hace falta comprender el código, nos basta con crear un objeto de ella pasándole los parámetros correspondientes, donde filename es el nombre de la imagen que se mostrará en la ventana splash, Frame el frame de la aplicación principal y wairTime el tiempo que se mostrará la ventana.
....
SplashWindow miSplash = new SplaashWindow("miImagen.jpg",this,4000);
....
Ya solo queda crear una aplicación a la que añadir nuestra pantalla splash. :-).
Recursos
[1] Artículo original,
http://www.javaworld.com/javaworld/javatips/jw-javatip104.html
Acerca del autor
Pedro Del Gallego Vida
Pedro del Gallego Vida, Akuma, estudiante de Ingeniería Superior en Informática en Madrid, centra su interés profesional en la POO, la programación declarativa/lógica, la inteligencia articfial y la teoría del conocimiento.
Actualmente se deja el tiempo intentando desarrollar un framework para la simulación de redes neuronales y memorias Hopfield.
Acerca del artículo original
Tony Colston