Beginning Sistemas de Información Java Swing Listado siguiente
PresentaciónEntrada/SalidaBibliotecasSwingMarcosBotonesCuadros de texto
ListasImágenesMenúsDiálogosArchivosGráficos 2D 


Fundamentos de Swing
El funcionamiento de Swing se basa en una colección de elementos fundamentales, que se caracterizan por tener una representación visible en pantalla. Las IGU basadas en Swing se construyen tomando como punto de partida clases derivadas de Component. Concretamente, se utilizan tres grandes grupos de derivaciones: La arquitectura más frecuente de una aplicación Swing es un JFrame dotado de un menú (construido con JMenuBar, varios JMenu y varios JMenuItem), que muestra uno o más JPanel en su interior, y dotado posiblemente de uno o más JButton con ActionListener asociados (posiblemente los mismos que los asociados a los JMenuItem). Este tipo de arquitectura se adapta bien al conocido esquema de Modelo-Vista-Controlador, que se utilizará también de forma habitual.

Ventanas
El componente fundamental de todas las aplicaciones basadas en Swing es JFrame, un componente de tipo Container que sirve como ventana principal. Los JFrame pueden recibir un nombre a través del constructor. Para añadir un componente es preciso utilizar el método getContentPane(), como se verá.
¿Cómo se crea una ventana? Facilón... véanse algunos ejemplos sencillos. Es muy conveniente realizar experimentos con estos componentes, "jugar", porque tarde o temprano se va a necesitar precisamente el efecto que se consiguió anteriormente casi por casualidad. Consúltese el término "Investigación operativa".

Ejercicio
Construir un programa que muestre una ventana en pantalla. El nombre de la ventana se indicará a través de la línea de órdenes.
import javax.swing.*;
import java.awt.Dimension;

public class JFrameSencillo {
   static public void main(String[] args) {
       String nombre = null;
       if (args.length == 1)
           nombre = args[0];
       else
           nombre = "Sin título";
       JFrame jf = new JFrame(nombre);

       jf.setSize(new Dimension(250,250));
       jf.setVisible(true);
           
   }
}

Este sencillísimo programa ya muestra una ventana de nombre parametrizado. Lamentablemente, no se cierra cuando se pulsa el marcador de cierre; para que esto suceda es preciso indicar al programa que lo haga:

Ejercicio
Construir una ventana con cierre real, de tal modo que concluya el program al cerrar la ventana.
import javax.swing.JFrame;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class JFrameConCierre{
	static public void main(String[] args) {
		String nombre = null;
		if (args.length == 1)
			nombre = args[0];
		else
			nombre = "Sin título";
		JFrame jf = new JFrame(nombre);
		jf.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
					System.exit(0);
				}
			});

	   jf.setSize(new Dimension(250,250));
	   jf.setVisible(true);
		   
   }
}
Comentarios.- El mecanismo de creación de la ventana no ha cambiado, pero aparece un fragmento de código relativamente extraño. La llamada a addWindowListener() tiene como argumento una clase anónima derivada de WindowAdapter. La única modificación que se efectúa es la redefinición del método windowClosing(), que pasa a forzar la salida de la aplicación (por omisión, los métodos de WindowAdapter no hacen nada).

Otra posible versión de este programa es la siguiente:

import javax.swing.*;
import java.awt.Dimension;

public class JFrameSencillo2 {
   static public void main(String[] args) {
       String nombre = null;
       if (args.length == 1)
           nombre = args[0];
       else
           nombre = "Sin título";
       /* nombre = args.length == 1 ? args[0] : "Sin título"; */
       JFrame jf = new JFrame(nombre);
       jf. setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
       jf.setSize(new Dimension(250,250));
       jf.setVisible(true);
           
   }
}

Comentarios.- Esta versión es más sencilla y se basa en características relativamente nuevas de Java (desde Java 1.3). La constante EXIT_ON_CLOSE no es la única que se puede emplear; véase la documentación de JFrame.

Nota.- Fieles a nuestra costumbre de rizar el rizo, este programa se ha escrito en un ordenador y transferido a otro vía ftp. A continuación, se efectuó la compilación en el ordenador remoto, y se creó un archivo jar, empleando instrucciones similares a las siguentes:
[maxus:JFrameSencillo] coti% javac JFrameSencillo.java 
[maxus:JFrameSencillo] coti% pico manifest
[maxus:JFrameSencillo] coti% jar cmfv manifest sencillo.jar *.class
manifest agregado
agregando: JFrameSencillo.class(entrada = 549) (salida= 383)(desinflado 30%)


A continuación se empleó la herramienta curl para trasladar el .jar desde el ordenador remoto hasta el ordenador local:

[cauldron:tests]> curl -G [.....]sencillo.jar > sencillo.jar

Y finalmente se ejecutó el programa localmente:
java -jar sencillo.jar Pruebas

El resultado fue perfectamente correcto. ¿Cómo se repetiría el proceso de forma sencilla para crear y compilar (remotamente) y ejecutar (localmente) la segunda versión del programa? El aspecto que ofrece el directorio remoto al finalizar la creación de todos los archivos es el siguiente:
-rw-r--r--   1 coti  staff  549  2 Jun 20:28 JFrameSencillo.class
-rw-r--r--   1 coti  staff  393  2 Jun 20:24 JFrameSencillo.java
-rw-r--r--   1 coti  staff  604  2 Jun 20:50 JFrameSencillo2.class
-rw-r--r--   1 coti  staff  458  2 Jun 20:50 JFrameSencillo2.java
-rw-r--r--   1 coti  staff   28  2 Jun 20:28 manifest
-rw-r--r--   1 coti  staff   29  2 Jun 20:50 manifest2
-rw-r--r--   1 coti  staff  887  2 Jun 20:28 sencillo.jar
-rw-r--r--   1 coti  staff  935  2 Jun 20:51 sencillo2.jar

make y Java


Considérese el siguiente makefile:
programa.jar: Programa.class
	jar cmfv manifest programa.jar *.class

Programa.class: Programa.java
	javac Programa.java

clean:
	rm *.class
	rm programa.jar

Como puede verse, es perfectamente posible crear un makefile adecuado para generar directamente el archivo .jar correspondiente a una aplicación, después de compilar las distintas clases necesarias. El archivo manifest, que será preciso escribir además del makefile, contiene una sola línea de texto:

Main-class: Programa

Obsérvese que:
  1. Programa no acaba en .class
  2. Hay un espacio después de los :
  3. ay un retorno de carro al final de la línea.
Una vez creado el manifiesto, como en los barcos de carga, se teclea make y el resto es automático, generándose programa.jar. Para ejecutar programa.jar, se le puede hacer doble clic (Mac OS X) o bien se escribe:

java -jar programa.jar

y el programa se ejecutará inmediatamente.

Nota sobre métodos de compilación
Se recomienda crear el makefile correspondiente a cada uno de los ejercicios anteriores, con objeto de facilitar su compilación y posibles mejores o modificaciones posteriores. Téngase en cuenta que resulta muy cómodo compilar sin más que teclear make, mucho más que ir compilando archivo por archivo.
Otra posibilidad interesante es escribir en un archivo las rutas de todos los archivos que se quieran compilar. Si llamamos listado a este archivo, se puede escribir:

javac @listado

y el compilador creará los .class correspondientes a todos los archivos indicados en listado

Nota sobre los entornos gráficos
El uso de entornos gráficos (JCreator, JEdit, Eclipse y un largo etcétera) puede suponer una cierta comodidad, pero sólo en el caso de que seamos capaces de hacer lo mismo manualmente. De otro modo, si algo no va bien (y algo acabará por no ir bien) será imposible seguir adelante. Basta con llegar a un lugar en que se use otro sistema de trabajo para que no funcione nada. Sin embargo, un makefile (o un listado) funcionará siempre, haciendo como mucho pequeños cambios debidos a la estructura de directorios.

Ejercicios propuestos
  1. Construir un programa que recubra de ventanas toda la pantalla. El programa mostrará una retícula 2x2 si no se le indica otra cosa a través de la línea de órdenes, o bien tomará dos argumentos (número de filas y número de columnas),que empleará para recubrir la pantalla. Se sugiere colorear el fondo de las ventanas.
  2. Crear una derivación del programa anterior con una ventana tal que si se pulsa el botón de cierre de la misma se cierren todas las ventanas del recubrimiento. Sugerencia: dar a esa ventana otro color y título diferente.
  3. Estudiar sucintamente la clase Timer. Construir una ventana que "resucite" (esto es, vuelva a aparecer) al cabo de cinco segundos de haber desaparecido cuando el usuario hace clic en el botón de cierre. Obsérvese que la clase Timer es un valioso auxiliar para todo tipo de tareas, y muy especialmente para el control de la interfaz gráfica de usuario.
  4. Construir un programa adecuado para visualizar imágenes de los tipos .jpg, .gif y .png. El programa, de operación totalmente automática, se situará en una carpeta y mostrará una imagen distinta cada N segundos. El número de segundos será de 5 por defecto, pero se podrá indicar a través de la línea de órdenes.