|
Sistemas de Información
|
Java
|
Swing |
|
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:
-
Container
(contenedor o recipiente) en cuyo interior se muestran otros
Component
s. Normalmente el
Container
va a ser un
JFrame
-
Disposiciones, de las cuales las de uso más frecuente son
-
Otras clases derivadas de
Component
, como
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:
Programa
no acaba en .class
- Hay un espacio después de los
:
- 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
-
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.
-
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.
-
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.
- 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.