�La siguiente sentencia es verdadera o falsa?
Las clase an�nimas internas se declaran y ejemplarizan al mismo tiempo, usando la palabra clave new con el nombre de la clase o el interface existentes.
Verdadero. Las clase an�nimas internas se declaran y ejemplarizan al mismo tiempo, usando la palabra clave new con el nombre de la clase o el interface existentes.
�Crear Clases An�nimas
Las clases an�nimas internas nos permiten trabajar con clases locales sin tener que ponerles nombre. Se utilizan muy frecuentemente para el manejo de eventos de los componentes gr�ficos. Un beneficio de utilizar clases an�nimas internas es que mantienen la acci�n del c�digo que manejan en el mismo lugar donde se ejemplariza el controlador GUI. En la clase controladora DiveHandler, se ejemplariza el UIWestPanel, proporcionando las referencias necesarias para el manejo de eventos.
Creamos una clase an�nima interna de la siguiente manera:
ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent ae) { System.out.println("Anonymous class example"); } };
Luego registramos el componente con el oyente:
button.addActionListener(listener);
Podemos combinar la definici�n de una clase interna con su utilizaci�n y registro de un oyente en un bloque de c�digo. Usando la siguiente sintaxis para crear la clase an�nima interna y registrar un componente, no necesitamos referenciar una variable local:
button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("Button clicked."); } });
Observa el }); de la �ltima l�nea del ejemplo. El } termina la definici�n de la clase interna. El ) finaliza la lista de argumentos de addActionListener, y el �nico argumento dentro de los corchetes es un argumento del tipo ActionListener, referenciando un ejemplar creado desde nuestra clase an�nima.
Aunque parezca que este objeto ActionListener no tiene un nombre de clase, el compiladorr le asigna nombres a las clases an�nimas internas. Despu�s de compilar las clases con clases an�nimas internas, veremos que se han creado nuevos ficheros .class que tienen un signo $ y un n�mero, como DiveHandler$1.class.
Las clase an�nimas suelen ser m�s concisas que las clases miembro, y hacen posible que para nuestra conveniencia definamos objetos oyentes donde los est�mos utilizando.Pero se pueden hacer d�ficiles de leer si el c�digo del m�todo del interface es largo y complejo. Una buena forma de mantener el c�digo limpio es encerrar los grandes trozos de c�digo en sus propios m�todos, y luego llamar al m�todo desde dentro del m�todo del interface.
Ahora podemos registrar el enterButton con un objeto ActionListener, y llamar a otros m�todos dentro de la clase an�nima interna:
Sigue estos pasos... |
---|
|
Observa estos tres m�todos llamados dentro del m�todo actionPerformed:
- ui.getAirIntake; Esta llamada obtiene la informaci�n necesaria sobre el aire que hay en el tanque desde la clase UIWestPanel.
- ui.getCount; Esta llamada obtiene el n�mero de inmersiones desde el GUI.
- addDive; Crearemos una definici�n para addDive m�s adelante, donde se recolectar� la informaci�n del GUI y se grabar� en un fichero.
Ahora escribiremos una clase interna para el bot�n viewButton como hicimos para enterButton:
Sigue estos pasos... |
---|
|
El constructor ahora abre los streams de entrada y salida, crea dos botones, y registra cada bot�n con su oyente, usando clases an�nimas.
�Crear la Funcionalidad del Bot�n
El GUI que hemos creado tiene campos de texto, men�s y botones de radio para que el usuario introduzca la informaci�n de la inmersi�n. Una vez que el usuario introduce los datos y pulsa el bot�n Enter, o mejor dicho el bot�n enterButton, se dispara un evento. Debemos proporcionar las instrucciones para lo que tenga que suceder. En este caso necesitamos escribir los datos a un fichero.
�Escribir Objetos a un Fichero
Para escribir los datos a un fichero, seguimos estos pasos:
- Llamamos al m�todo que colecta los datos desde el GUI y los devuelve como un objeto Vector, y lo asignamos a un identificador del tipo Vector.
- Sacamos todos los �tems del Vector y los forzamos para que corresponda su tipo a los del modelo DiveRecord.
- Creamos un nuevo objeto DiveRecord.
- Llamamos al m�todo setDive y le pasamos los �tems Vector.
- Escribimos el objeto DiveRecord en un fichero.
Ya hemos preparado nuestro c�digo para hacer el primer paso. En UIWestPanel, creamos un m�todo llamado getUIFields que obten�a los datos introducidos y los devolv�a como un objeto Vector:
public Vector getUIFields() { Vector fieldValues = new Vector(); fieldValues.add(rb.getText()); fieldValues.add(date.getText()); fieldValues.add(s); fieldValues.add(psiStart.getText()); fieldValues.add(psiEnd.getText()); fieldValues.add(psiUsed.getText()); fieldValues.add(bottomTime.getText()); fieldValues.add(diveNumberL.getText()); fieldValues.add(vis.getText()); fieldValues.add(comments.getText()); return fieldValues; }// closes getUIFields
Observa que los datos se devuelven como objetos String dentro del Vector. El m�todo setDive de DiveRecord necesita que le pasemos objetos de distintos tipos:
public void setDive (String t, String d, int dth, int s, int e, int u, int bt, int c, int v, String cts){ . . . }
Por eso despu�s de obtener los datos del Vector, necesitaremos forzarlos a los tipos adecuados. Esto se hace dentro de un m�todo addDive que vamos a crear en la clase DiveHandler.
Sigue estos pasos... |
---|
|
En el m�todo de arriba, primero se llama al m�todo getUIFields para recuperar la entrada del usuario y asignarla a un objeto Vector. Los valores que el usuario a introducido se fuerzan al tipo apropiado para poder pasarlos al m�todo setDive del objeto DiveRecord:
String t = (String)values.get(0);
En esta l�nea, el valor 0, en este caso el tipo de inmersi�n, se recupera desde el objeto Vector y se fuerza al tipo String. Se llama al m�todo System.out.prinln para que podamos chequearlo en la salida est�ndard. Puedes borrar las l�neas de las llamadas a System.out.prinln si prefieres que no se imprima nada en la consola mientras se ejecuta la aplicaci�n.
Despu�s de sacar los datos del Vector y de forzarlos a los tipos apropiados, se pasan dentro del m�todo setDive para crear un objeto DiveRecord:
Dr = new DiveRecord(); Dr.setDive(t, d, dth, s, e, u, bt, c, v, cts);
Entonces se escribe el objeto en un fichero y se incrementa la variable objectCount con cada objeto escrito:
output.flush(); objectCount ++;
Como explicamos anteriormente en la secci�n sobre las clases ObjectOutputStream y ObjectInputStream, debemos incluir el c�digo para manejar excepciones y condiciones. Para la mayor�a de estas ocurrencias, no necesitaremos parar el programa. S�lo deberemos informar al usuario de que algo ha sucedido, como que se ha alcanzado el final del fichero, que no se ha encontrado un fichero o que ha habido un problema al escribir el fichero. Podemos conseguir esto muy f�cilmente utilizando la clase JOptionPane:
catch (NumberFormatException nef) { JOptionPane.showMessageDialog(this, "You need to fill out all fields", "Invalid fields", JOptionPane.ERROR_MESSAGE); }//close catch catch (FileNotFoundException fnf) { JOptionPane.showMessageDialog(this, "File not found", null, JOptionPane.ERROR_MESSAGE); }//close catch catch (IOException io) { JOptionPane.showMessageDialog(this, "Error closing file", null, JOptionPane.ERROR_MESSAGE); closeFile(); }//close catch
Por �ltimo, despu�s de haber escrito el fichero, es importante cerrarlo y limpiar los campos del GUI para que el usuario pueda introducir otra inmersi�n:
closeFile(); }//close catch ui.clearFields();
�Ver en el GUI Objetos de un Fichero
Los pasos para ver un objeto son similares a los de escribir un objeto, con algunas peque�as diferencias:
- Asignar un identificador a un objeto DiveRecord.
- Si un objeto no es null, abrir el fichero de texto con un ObjectInputStream.
- En el caso de que haya alg�n problema al abrir el fichero, manejar la excepci�n.
- Leer los objetos.
- Forzar los tipos a String.
- Configurar los strings del GUI.
En el m�todo viewDive, utilizamos una sentencia if para comprobar si el stream ya estaba abierto:
public void viewDive() { try { DiveRecord Dr; if(input == null) try{ input = new ObjectInputStream(new FileInputStream( "diveLogs.dat")); }catch (IOException ioex){ JOptionPane.showMessageDialog(null, "Error during reading file", null, JOptionPane.ERROR_MESSAGE); } }
La variable input es null si el fichero no se hab�a abierto apropiadamente para su lectura. Si no es as�, se abre un nuevo objeto ObjectInputStream y se proporciona el manejo de excepciones.
Para leer el objeto, debemos forzarlo como un objeto DiveRecord, y luego lo leemos:
Dr = (DiveRecord) input.readObject();
Como el m�todo setFields de la clase UIWestPanel acepta un array de strings como argumento, obtenemos todos los �tems del objeto DiveRecord, los forzamos al tipo String, y los almacenamos en un array. Por �ltimo, pasamos el array al m�todo setFields:
String svalues[] = { Dr.getType(), Dr.getDte(), String.valueOf(Dr.getDepth()), String.valueOf(Dr.getStart()), String.valueOf(Dr.getEnd()), String.valueOf(Dr.getUsed()), String.valueOf(Dr.getTime()), String.valueOf(Dr.getCount()), String.valueOf(Dr.getVis()), Dr.getComments()}; ui.setFields(svalues); return;
De nuevo, necesitamos manejar las excepciones que se podr�an lanzar:
catch (EOFException eofex){ JOptionPane.showMessageDialog (null, "No more records in file",null, JOptionPane.ERROR_MESSAGE); }//close catch catch (ClassNotFoundException cnfex){ JOptionPane.showMessageDialog(null, "Unable to open object", null, JOptionPane.ERROR_MESSAGE); }//close catch catch (IOException ioex) { JOptionPane.showMessageDialog(null, "Error during reading file", null, JOptionPane.ERROR_MESSAGE); }//close catch
Sigue estos pasos... |
---|
Tu clase DiveHandler se deber�a parecer a esta |
�Sumario
En este quinta parte del tutorial New 2 Java: Crear una Aplicaci�n hemos aprendido a:
�Separar el Interface de la Implementaci�n
Hemos aprendido c�mo utilizar la arquitectura MVC, manteniendo los componentes gr�ficos separados de los datos o modelo.
�Dise�ar un Objeto
Hemos decidido qu� atributos deber�a tener un objeto, y hemos proporcionado los m�todos get necesarios para trabajar con los datos.
�Serializar Objetos
Hemos descubierto lo f�cil que es serializar un objeto, y hemos conocido el interface Serializable.
�Escribir Objetos en Ficheros
Por �ltimo, hemos aprendido c�mo escribir objetos en un fichero y c�mo leerlos luego y poner sus datos en el interface gr�fico de usuario.