New 2 Java: Construir una Aplicación: 5.- Escribir Objetos a Ficheros, Usar Arrays y más...

En El capítulo Anterior de esta serie, aprendimos como manejar problemas y condiciones, y ya sabemos leer y escribir ficheros. También aprendimos a utilizar la distribución Box, cómo crear ventanas desplegables para mensajes de aviso, y cómo usar la clase JFileChooser para nombrar nuevos ficheros.

La parte 5 refuerza estos conceptos y presenta la segunda parte del panel Log Dives, mostrándonos como:

  • Separar el interface de la implementación
  • Crear un objeto DiveRecord.
  • Serializar objetos y escribirlos en ficheros, y luego leerlos de nuevo y ponerlos en el GUI.
  • Usar objetos Vector para almacenar la entrada.
  • Crear menús desplegables y botones de radio.

. Empezamos

En esta sección del tutorial modificaremos dos clases que creamos anteriormente: Dives.java y CenterPanel.java. Además, definiremos nuevas clases, renombrando la clase contenedora WestPanel.java como DiveHandler, y creando otras dos clases llamadas UIWestPanel.java y DiveRecord.java.

  • Dives.java: Inicializa las dos clases (UIWestPanel y DiveHandler) que componen el panel Log Dives.
  • UIWestPanel.java: Inicializa el GUI, es decir, los campos de texto, los botones de radio, el menú desplegable, y los botones para introducir y ver nuestras sesiones de buceo.
  • CenterPanel.java: Ya no es necesaria. El JTextArea y la imagen del tiburón se ha movido a la clase UIWestPanel.
  • DiveRecord.java: Modela lo que es un objeto DiveRecord.
  • DiveHandler.java: Porporciona funcionalidades, como la recolección de datos desde el objeto UIWestPanel, y graba el objeto DiveRecord en un fichero.

Esta lección nos muestra como construir un interface de usuario que permite grabar en un fichero la información introducida de cada inmersión, y una clase separada que recolecta los datos desde el interface de usuario en un objeto DiveRecord a través de los métodos get públicos. Por último, crearemos el código que escriba el objeto en un fichero, para que posteriormente pueda ser leído de vuelta el GUI.

El panel Log Dives se construye en cuatro pasos básicos:

  1. Modificar las clases que creamos anteriormente.
  2. Crear una clase DiveRecord para el objeto DiveRecord.
  3. Contruir los componentes GUI para la entrada de usuario
  4. Crear una clase que proporcione la funcionalidad para los botones, recoja los datos, grabe la colección de datos como un objeto, y escriba el objeto en un fichero. Posteriormente el objeto se pasa de vuelta al GUI.
Nota:
Se asume que tienes intalada la Java 2 Platform, Standard Edition (J2SE) en tu sistema, y que has completado y compilado los ejemplos de las secciones anteriores de este tutorial.

. Hacer las Modificaciones

En la sección anterior aprendimos como utilizar JFileChooser, y como grabar texto en un fichero. El CenterPanel creó el área de texto para que el usuario introdujera el texto. Debemos mantener el código que crea el área de texto y la imagen del tiburón, pero ya no necesitaremos el resto del código. Como el área de texto es una característica GUI, necesitamos incluir el código junto con las otras caracterísiticas GUI de este de panel.

Sigue estos pasos...
  1. Abre el fichero de la clase CenterPanel.java que creamos en la sección anterior.
  2. Elimina el código del área de texto y la imagen del tiburón, y graba el código en un fichero separado, por ahora.
  3. Abre el fichero Dives.java que creamos en la sección anterior.
  4. Comenta o elimina la línea que inicializa la clase CenterPanel, y la línea que añade el objeto CenterPanel al panel, como se muestra en negrita más abajo.
  5. Cambia NorthPanel por DiveHandler, como se muestra en negrita:
  6. public class Dives extends JPanel
    { // Opens class
        public Dives()
       {// Opens constructor
        // Sets the layout for the page and the
        // background to white.
        setLayout(new BorderLayout());
        setBackground(Color.white);
    
         // Initializes the placeholder classes.
         NorthPanel northPanel = new NorthPanel();
         //CenterPanel centerPanel = new CenterPanel();
         //NorthPanel northPanel = new NorthPanel();
         DiveHandler ui = new DiveHandler();
    
         // Adds class objects to panel regions.
         add("North", northPanel);
         add("West", ui);
         //add("Center", centerPanel);
       } // Closes constructor
    
  7. Graba el fichero.

Nota:
No podrás compilar esta clase hasta que hayamos creado la clase DiveHandler.
Ya no necesitaremos la clase CenterPanel.

. Separar el Interface de la Implementación

Hasta ahora hemos construido cada panel desde una sola clase definida por el usuario. Estas clases incluían el código tanto para los componentes GUI, los datos y las funcionalidades del panel. Una forma mejor del diseño de software implica la arquitectura Modelo, Vista, Controlador (MVC).

La idea que hay detrás de MVC es separar los componentes gráficos (o vista) de los datos (o modelo), y utilizar un controlador para tratar con la interacción del usuario y modificar el modelo o la vista de la forma apropiada.

  • El modelo almacena los datos que define el componente.
  • La vista crea la representación visual del componente.
  • El controlador trata de la interacción del usuario con los componentes y luego actualiza el modelo y/o la vista según las necesidades, dependiendo de la entrada del usuario.

Por supuesto, algunas aplicaciones son demasiado pequeñas o tienen muy poca funcionalidad, por lo que no merece la pena utilizar MVC. Pero para este panel, MVC nos irá muy bien.

  • UIWestPanel.java: creará los componentes GUI para que el usuario introduzca la información. Esta clase actúa como la vista.
  • DiveRecord.java: contiene un constructor para crear un objeto DiveRecord que eventualmente contiene la entrada del usuario, y tiene los métodos públicos get y set necesarios para acceder a datos individuales. Esta clase define un modelo para un objeto DiveRecord.
  • DiveHandler.java es el controlador. Esta clase ejemplariza las clases UIWestPanel y DiveRecord. Además, proporciona las funcionalidades de los botones de la clase UIWestPanel llamando a los métodos públicos set y get de las otras clases.

. Diseñar el objeto

Ahora que ya hemos realizado los cambios necesarios en las dos clases creadas anteriormente, estámos listos para diseñar un nuevo objeto dive. Este es el plano de lo que consiste un objeto dive. También nos dice que tipo de características GUI necesitaremos para recolectar información sobre el buceador, porque cada objeto dive sólo consta de datos de inmersiones.

Para decidir que datos necesitamos pasar al constructor de la clase DiveRecord, determinamos la información más común que los buceadores proporcionan sobre cada sesión de buceo, y anotamos de que tipo de dato se trata, de esta forma:

  • Tipo de inmersión, como desde un bote o desde la playa (String t).
  • Fecha en que tuvo lugar la inmersión (String d).
  • La profundidad alcanzada en esta inmersión (int dth).
  • La presión inicial que tenía el tanque al empezar la inmersón (int s).
  • La presión final que tenía el tanque al finalizar la inmersión (int e).
  • La cantidad total de aire consumido (int u).
  • La duración total de la inmersión (int b).
  • El número de inmersión de ese buceador (int c).
  • Visibilidad del agua (int v).
  • Comentarios sobre la inmersión (String cts).

A cada dato anterior se la asignado un tipo de dato, como un String o un int, y también se le ha asignado un identificador. El objeto dive se construirá en el momento en que el buceador introduzca toda la información.

Entonces esta clase necesita incluir lo siguiente:

  • Un constructor.
  • Métodos get para cada dato.

Esto es todo. Las instrucciones para lo que se debería hacer con esta información van en la clase del controlador que construiremos al final.

Esta clase DiveRecord proporciona un constructor para los datos que está recolectando, y métodos para trabajar con esos datos. Como vamos a escribir este objeto en un fichero usando serialización, esta clase necesita implementar el interface Serializable.

. Serialiación de Objetos

Usualmente los objetos existen mientras el programa que los creó está activo y ejecutándose. La habilidad de un objeto para grabar, o registrar su estado para que pueda ser reproducido en la misma o en otra aplicación es la persistencia. Un objeto puede persistir grabando los valores que describen su estado en un fichero. Por ejemplo, digamos que tenemos una clase Coche con la que los usuarios pueden crear sus propios objetos Coche atendiendo a sus necesidades. La persistencia permitiría que cada ejemplar de Coche pudiera grabar su fabricante, modelo, color, etc y registrar el estado de cada Coche para utilizarlo más tarde.

Podemos grabar el estado de un objeto a través de su serialización, que su representación en una serie ordenada de bytes. Si esa información de estado es otro objeto, también se graban las selecciones actuales para ese objeto, etc., hasta que todos sean tipos de datos primitivos. Los métodos y las variables de estado static no se graban. Los métodos son el comportamiento de un objeto, no el estado, y por eso no se graban. Las variables estáticas, son información sobre la clase, no del ejemplar y tampoco se graban.

La serialiación es ideal para grabar los datos de la inmersión porque sólo necesitamos los datos grabados. Un DiveRecord es simplemente un objeto con esos datos.

Si una clase implementa el interface java.io.Serializable, es serializable. No hay métodos en este interface por eso sólo sirve como un marcador. Sin embargo, simplemente implementar el interface no es suficiente. Las variables de ejemplar de esa clase también debe ser serializables; si no es así, cuando intentemos serializar el estado, se lanzará un excepción.

Más adelante veremos los métodos que escriben y leen el objeto hacia y desde un fichero. Por ahora, sólo debemos asegurarnos de que nuestra clase DiveRecord implemente el interface Serializable.

Sigue estos pasos...
  1. Abre tu editor de texto, y crea una clase DiveRecord importando los siguientes paquetes e implementando el interface Serializable:
    //Represents a record of a dive
    package divelog;
    import java.io.*;
    import java.io.Serializable;
    
    public class DiveRecord implements Serializable
      {
    
  2. Añade las siguientes variables de ejemplar:
        //Instance variables
        private String date, type, cts;
        private int depth, start, end, used, 
           time, count, vis;
    
  3. Crea un constructor por defecto que llame a un método setDive:
        public DiveRecord ()
         {
           setDive();
         }
    
  4. Implementa un método setDive que no tome ningún argumento, pero que contenga las variables listadas arriba:
        public void setDive()
         {
           type = "";
           date = "00/00/00";
           depth = 00;
           start = 0000;
           end = 0000;
           used = 0000;
           time = 00;
           count = 000;
           vis = 00;
           cts = "";
         }
    
  5. Ahora crea un método setDive que tome todas esas variables como argumentos:
        public void setDive (String t,String d, int dth, 
                    int s, int e, int u, int bt, 
                    int c, int v, String cts)
            {
              
              this.type = t;
              this.date = d;
              this.depth = dth;
              this.start = s;
              this.end = e;
              this.used = u;
              this.time = bt;
              this.count = c;
              this.vis = v;
              this.cts = cts;
              
             }
    
  6. Sobreescribe el método toString de la clase String para que devuelva los datos asociados con las variables de ejemplar:
        public String toString()
         {
           return type + date + depth + start + 
              end + used + time + count + vis + cts;
         }
    
  7. Ahora proporciona un método get para cada variable de ejemplar:
        public String getDte()
          {
            return date;
          }     
        public int getDepth ()
          {
            return depth;
          }
         public String getType ()
         {
           return type;
          }
         public int getStart ()
          {
            return start;
           }
        public int getEnd ()
          {
            return end;
           }
           
         public int getUsed ()
           {
             return used;
            }
         public int getTime()
           {
             return time;
           }
         public int getCount ()
           {
             return count;
            }
         public int getVis()
           {
              return vis;
            }
        public String getComments()
          {
             return cts;
           }
       }//closes class     
    
  8. Graba el fichero.
  9. Compila el fichero DiveRecord.java.

Tu nueva clase debería parecerse a esta DiveRecord.java.

Nota:
Observa la palabra clave this usada en el constructor. Los nombres de argumentos ocultan los nombres de las variables miembro. Por eso los identificadores dentro del cuerpo del constructor se refieren a los argumentos no a las variables miembro. Para acceder a las variables miembro, debemos referenciarlas a través de this, el objeto actual. Típicamente, dentro del cuerpo de un método, podemos referenciar directamente las variables miembro del objeto. Sin embargo, algunas veces necesitamos distinguir el indentificador de la variable miembro si uno de los argumentos del método tiene el mismo nombre que la variable miembro. Esto simplemente se hace utilizando la palabra clave this.

Esto completa el modelo de nuestro objeto. Ahora que hemos completado el modelo, necesitamos crear los componentes GUI que el usuario necesita para introducir los datos.

. Construir los componentes GUI

El panel Logs Dives contiene un área de texto para los comentarios de las inmersiones y otros componentes gráficos de entrada como con menú desplegable para elegir el nivel de profundidad, dos botones de radio para elegir entre las inmersiones desde bote o desde la playa, y los campos de texto familiares para registrar la fecha, el tiempo de inmersión, la visibilidad y una etiqueta que se rellena por un métoco que crearemos para que rellene automáticamente el número de inmersión. Si, por ejemplo, estámos construyendo, un diario de ejercicios, podemos cambiar estas características para grabar las calorías quemadas, los ejercicios aeróbicos y anaeróbicos, etc. Puedes cambiar estas características para que se adapten a tu aplicación.

Más delante, crearemos una clase UIWestPanel para definir los componentes GUI para que un buceador introduzca los datos de sus inmersiones.

Lee el API de la clase JComboBox. ¿Qué línea de código es la correcta para hacer que el combobox sea editable?
 A  JComboBox week = new JComboBox(SetEditable);
 B  week.setEditable(true)
 D  week.setEditable == true;

COMPARTE ESTE ARTÍCULO

ENVIAR A UN AMIGO
COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN GOOGLE +
ARTÍCULO ANTERIOR

SIGUIENTE ARTÍCULO

¡SÉ EL PRIMERO EN COMENTAR!
Conéctate o Regístrate para dejar tu comentario.