Sesión 12

 

1. Vamos a realizar un par de ejercicios con la librería Swing, para ver qué diferencias existen con AWT, y qué posibilidades nuevas ofrece.

  1. Antes de comenzar con estos ejercicios, lee entero el apartado 3.2 (Swing) del tema 3 de teoría.
  2. Echa un vistazo a la clase JCalculadora.java que se proporciona en la plantilla de la sesión. Verás que es una versión "resuelta" del ejercicio de la Calculadora propuesto en la sesión de AWT anterior. Lo que vamos a hacer ahora es transformar este ejemplo en un programa Swing, para ver qué diferencias hay.
  3. Lo primero que hay que hacer es importar el paquete adecuado (además de los de AWT, que NO hay que quitar, porque el modelo de eventos y los gestores de disposición son los mismos).
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import javax.swing.*;
    
    public class JCalculadora ...
  4. Después vamos cambiando los componentes de AWT por los correspondientes de Swing.
    1. En primer lugar, la clase ya no heredará de Frame, sino de su homólogo JFrame
    public class JCalculadora extends JFrame
    {
    	...
    1. Después sustituimos cada control de AWT por el correspondiente de Swing, es decir, las líneas:
      TextField txtOp1 = new TextField();
      ...
      Choice operadores = new Choice();
      ...
      TextField txtOp2 = new TextField();
      ...
      TextField txtRes = new TextField();
      ...
      Label lblOp1 = new Label("Primer operando:");
      ...
      Label lblOp2 = new Label("Segundo operando:");
      ...
      Label lblOper = new Label("Operador:");
      ...
      Button btnRes = new Button("Primer operando:");
      ...

      Por las correspondientes clases Swing:

      JTextField txtOp1 = new JTextField();
      ...
      JComboBox operadores = new JComboBox();
      ...
      JTextField txtOp2 = new JTextField();
      ...
      JTextField txtRes = new JTextField();
      ...
      JLabel lblOp1 = new JLabel("Primer operando:");
      ...
      JLabel lblOp2 = new JLabel("Segundo operando:");
      ...
      JLabel lblOper = new JLabel("Operador:");
      ...
      JButton btnRes = new JButton("Primer operando:");
      ...
    2. Prueba a compilar y ejecutar la clase... dará error. ¿A qué se debe el error?
    3. Como se explica en la parte de teoría, en Swing algunos métodos de JFrame no pueden ser accedidos directamente, como ocurría con Frame en AWT. Estos métodos son, entre otros, setLayout y add. Así, para solucionar el error anterior, deberás anteponer el método getContentPane() antes de cada método setLayout o add del JFrame:
      getContentPane().setLayout(new GridLayout(4, 2));
      ...
      getContentPane().add(lblOp1);
      getContentPane().add(txtOp1);
      ...
      getContentPane().add(lblOper);
      getContentPane().add(operadores);
      ...
      getContentPane().add(lblOp2);
      getContentPane().add(txtOp2);
      ...
      getContentPane().add(btnRes);
      getContentPane().add(txtRes);
      ...
    4. Compila y comprueba que el funcionamiento del programa es el mismo, aunque su apariencia sea distinta:

      Figura 1. Apariencia de la calculadora en Swing

2. En este segundo ejercicio probaremos algunas cosas nuevas que ofrece Swing, partiendo de una aplicación ya hecha.

  1. Echa un vistazo a la clase JFormatos.java que se proporciona en la plantilla de la sesión. Verás que es una versión en Swing del ejercicio de Formatos que se pedía en la sesión de AWT anterior. 
  2. Compílala y ejecútala para comprobar que funciona correctamente.
  3. Antes de seguir, vamos a echar un vistazo a las cosas que cambian entre la aplicación en AWT y esta versión de Swing:
  4. Sobre esta aplicación vamos a añadir dos cambios: 
    1. Para el temporizador, primero importamos el paquete de entrada salida, para poder utilizar clases de acceso a ficheros:
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      import java.io.*;

      También añadimos una variable global llamada fichero que tenga el nombre del fichero donde guardar el contenido del cuadro de texto:

      public class JFormatos extends JFrame implements ActionListener
      {
      	JTextArea txt;
      	boolean negrita = false, cursiva = false;
      	String fichero = "guardar.txt";
      	...

      Después, en el constructor, añadimos al final el temporizador, que utilizará un PrintWriter para volcar al fichero fichero el contenido del cuadro de texto:

      public JFormatos()
      {
      	...
      	// Timer
      
      	Timer tim = new Timer (10000, new ActionListener() 
      	{
      		public void actionPerformed(ActionEvent e)
      		{
      			try
      			{
      				PrintWriter pw = 
      				   new PrintWriter(new FileWriter(fichero));
      				pw.println(txt.getText());
      				pw.close();
      			} catch (Exception ex) {}
      		}
      	});
      	tim.setRepeats(true);
      	tim.start();
      }

      ¿Qué ocurriría si no pusiéramos el método setRepeats(true)?

    2. Para el botón de guardar, primero declaramos una variable global que haga referencia al JFrame actual (luego veremos para qué sirve):
      public class JFormatos extends JFrame implements ActionListener
      {
      	JTextArea txt;
      	boolean negrita = false, cursiva = false;
      	String fichero = "guardar.txt";
      	JFrame frame = this;
      	...

      Después añadimos el botón al final del constructor, con el icono save.jpg que se tiene en la plantilla, y su evento correspondiente:

      public JFormatos()
      {
      	...
      	// Icono
      		
      	JButton btnSave = new JButton("Guardar", new ImageIcon("save.jpg"));
      	btnSave.addActionListener(new ActionListener()
      	{
      		public void actionPerformed(ActionEvent e)
      		{
      			JFileChooser jfc = new JFileChooser(".");
      			int res = jfc.showSaveDialog(frame);
      			if (res == JFileChooser.APPROVE_OPTION)
      			   fichero = jfc.getSelectedFile().getAbsolutePath();
      		}
      	});
      	getContentPane().add(btnSave, BorderLayout.SOUTH);
      
      }

      Observa que para añadir el icono al botón, utilizamos un constructor de JButton con los parametros JButton(String nombre, Icon icono), y creamos el icono con la clase ImageIcon de Swing.

      En cuanto al evento del botón, creamos un diálogo de tipo JFileChooser, que se abrirá en el directorio actual (indicado por "."). Observa que al llamar a showSaveDialog se abre un diálogo como los de Guardar como... de Windows, y este diálogo devuelve un entero, que es el resultado tras cerrarlo. Si dicho resultado es igual a la constante JFileChooser.APPROVE_OPTION indica que el usuario ha elegido un fichero, con lo que sólo nos queda tomar el fichero seleccionado (getSelectedFile) y su ruta absoluta (getAbsolutePath). A partir de entonces, el fichero donde guarde el temporizador será el nuevo que hemos asignado.

      Observa también que la variable frame que hemos creado antes, la utilizamos para crear el diálogo, indicando de qué ventana principal depende. En realidad, podríamos haber utilizado cualquier componente de nuestra ventana principal.

      Si hubiésemos querido abrir un fichero para leerlo, en lugar de para guardarlo... ¿qué método de JFileChooser habría sido más adecuado, en lugar de showSaveDialog? (consulta la API de esta clase para averiguarlo).

 

3. Para terminar esta sesión, vamos a dar un rápido vistazo a los Applets. Lee primero el apartado 3.3 (Applets) del tema 3 de teoría.

  1. Echa un vistazo a la clase CalcApplet.java que se proporciona en la plantilla de la sesión. Verás que es otra copia del ejercicio de la Calculadora en AWT. Ahora vamos a convertirla en Applet.
  2. Lo primero que haremos será importar el paquete para trabajar con applets, manteniendo los que ya hay de AWT, que los necesitaremos para los eventos, controles, y demás:
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import java.applet.*;
    
    public class CalcApplet ...
  3. Después hacemos que la clase herede de Applet, no de Frame:
    public class CalcApplet extends Applet
    {
    	...
  1. A continuación, sustituimos el constructor por el método init, simplemente cambiando el nombre:
    public CalcApplet()
    {
    	...

    por:

    public void init()
    {
    	...
  1. Por último, eliminamos el método main entero (al ser un applet, no lo necesita), y compilamos el programa para depurar posibles erratas.
  2. Lo que nos queda por hacer es una página HTML desde donde cargar el applet. En la plantilla se proporciona la página CalcApplet.html, con un body vacío, sólo hace falta añadirle una etiqueta APPLET con el applet que queramos ejecutar:
    <html>
    <body>
    
    <APPLET CODE=CalcApplet.class WIDTH=400 HEIGHT=200>
    </APPLET>
    
    </body>
    </html>
  3. Abre la página desde cualquier navegador, y comprueba que el applet funciona correctamente. También puedes abrirla desde la herramienta appletviewer que viene con JDK, pasándole la página a abrir, desde la ventana de MS-DOS:
    appletviewer CalcApplet.html

PARA ENTREGAR