domingo, 11 de septiembre de 2016

051.- La Clase JTable - Continuación - Java Y NetBeans

Representación de Tablas de una Base de Datos en un JTable:

En la publicación anterior vimos que existe un objeto del tipo JTable que nos permite introducir tablas en nuestras aplicaciones.
Estos objetos son ideales para mostrar el contenido de una tabla de la base de datos o del resultado de una consulta.
Recuerda que para extraer datos de la base de datos realizamos una consulta SQL de tipo SELECT cuyo resultado se almacena en un objeto ResultSet.
Un ResultSet básicamente es una tabla almacenada en memoria (y por tanto no visible) Sin embargo, en este post veremos como trasladar el contenido de un ResultSet a un objeto del tipo JTable para que el usuario pueda visualizar los datos de forma cómoda.

El proceso será básicamente el siguiente:




EJERCICIO GUIADO Nº 1

  1. Crea un proyecto java y prepararlo para que pueda acceder a la base de datos AMANUVA:

    1. Agregar el archivo sqljdbc4.jar a las bibliotecas del proyecto.
 

    1. Declarar los dos objetos globales: conexion y sentencia.

    1. Programar el método conectarBaseDatos de forma que el programa acceda a la base de datos y se construyan los objetos conexion y sentencia.

    1. Programar el evento windowClosing de la ventana principal de forma que se cierre la conexión.


  1. Una vez hecho esto, añade a la ventana principal un objeto del tipo JTable y llámalo tablaTrabajadores.

  1. Añade en la parte inferior un botón llamado btnVerTrabajadores. La ventana principal quedará así:



  1. Agregaremos al proyecto un objeto “modelo de tabla” (DefaultTableModel) llamado detamo que sea global. También añadiremos en el método constructor una llamada a un método configurarTabla y programaremos dicho método de la siguiente forma:




Si observas el código, verás que en el método configurarTabla se crea un vector de cadenas con seis elementos pero que no contiene nada.
Luego se crea el modelo de tabla a partir de este vector vacío.
Y se asigna finalmente a la tablaTrabajadores.
El resultado de esto es que la tabla aparecerá vacía y sin títulos (En realidad, como títulos aparecen letras: A, B, C, etc.).


  1. Ejecuta el programa para ver su aspecto:



  1. Bien, ahora programaremos el botón btnVerTrabajadores de forma que al pulsarlo se muestre el contenido de la tabla Trabajadores. Programe lo siguiente:



Estudiemos el código detenidamente:
Lo primero que se hace es extraer el contenido de la tabla Trabajadores de la base de datos, ejecutando una consulta SQL usando el objeto sentencia. El resultado de dicha consulta se almacenará en un objeto ResultSet llamado rs.

ResultSet rs = sentencia.executeQuery("SELECT * FROM Trabajadores");

Luego se crea el modelo de la tabla definiendo la cabecera. Observa el código:

String titulosTabla[] = {"DNI", "Nombres", "Apellidos", "Sueldo", "Fecha Entrada", "Placa"};
detamo = new DefaultTableModel(null, titulosTabla);
tablaTrabajadores.setModel(detamo);

Como ves, lo que hacemos es definir un vector de cadenas con los títulos correspondientes a los campos de la tabla, y luego usamos este vector para crear el modelo de la tabla.

Finalmente asignamos el modelo creado a la tablaTrabajadores.


  1. Ejecuta el programa y observa como al pulsar el botón Ver Trabajadores la cabecera de la tablaTrabajadores pasa a contener los campos indicados en el vector titulosTabla.



  1. Ahora ya solo nos queda recoger todo el contenido del ResultSet y mostrarlo en la tabla. Para ello, modifique el código del evento actionPerformed del botón btnVerTrabajadores para que quede como sigue:



Si estudiamos el código, veremos que se extrae la tabla Trabajadores entera introduciéndola en un ResultSet llamado rs, a través de una instrucción SELECT de SQL.

Luego construimos un modelo de tabla (DefaultTableModel) llamado detamo usando un vector de títulos, que se corresponde a los campos de la tabla Trabajadores.

Una vez hecho esto, creamos un vector de seis elementos, correspondiente a los seis datos que contiene cada fila, y empezamos a recorrer el ResultSet usando el típico:

while (rs.next()) {

En cada vuelta del bucle tomamos los valores de la fila del ResultSet y los almacenamos en el vector (en la posición correspondiente).

Luego se añade el vector que se ha construido al modelo de la tabla.

Así pues, en cada vuelta se añadirá un registro más al modelo detamo. Estos registros son extraídos del ResultSet.

Cuando el bucle ha terminado, el modelo de la tabla contiene exactamente lo mismo que el ResultSet. Es decir, contiene la tabla Trabajadores, ya que este fue el resultado de la consulta SQL ejecutada.

Ya solo tenemos que asignar el modelo de tabla al JTable correspondiente, es decir, a la tablaTrabajadores, con lo que esta visualizará los datos del modelo.

Todo este proceso se rodea con un try...catch para capturar errores inesperados.

  1. Para entender el código anterior aquí tienes un pequeño gráfico explicativo:



-       De la base de datos extraemos datos a un ResultSet. (Esto se hace ejecutando una consulta SQL de tipo SELECT a través del objeto sentencia).

-       Del ResultSet extraemos los datos a un modelo de tabla. (Esto se hace recorriendo el ResultSet y almacenando cada registro en un vector).

-       Almacenamiento del vector en el modelo de tabla. (Cada vector extraido del ResultSet se inserta como fila en el modelo de tabla).

-       Se asigna el modelo de tabla al objeto JTable. (Al hacer esto el objeto JTable muestra el contenido del modelo).


  1. Ejecuta el programa y observa el resultado al pulsar el botón Ver Trabajadores. Como ves, el objeto tablaTrabajadores muestra entonces el contenido de la tabla Trabajadores:



  1. Si observas la tabla verás que la fecha aparece en el formato estándar de almacenamiento:

año-mes-dia hora:min:seg

Mejora este detalle haciendo los siguientes cambios en el código del botón Ver Trabajadores:



Como se puede observar en el caso de la fecha, se extrae de la cadena el año, mes y día y se concatenan en un formato más habitual: día/mes/año.

  1. Ejecuta el programa y observa como se muestran las fechas:





CONCLUSIONES:

El proceso a seguir para mostrar una tabla de una base de datos en un JTable es el siguiente:

-       Realizar una consulta SELECT para extraer los datos de la tabla de la base de datos. El resultado se almacenará en un ResultSet.

-       Recorrer el ResultSet almacenando cada una de sus filas en un vector y luego traspasando este vector a un modelo de tabla.

-       Una vez que el modelo de tabla está relleno, asignar el modelo a un JTable.

viernes, 9 de septiembre de 2016

050.- La Clase JTable - Java Y NetBeans

Tablas (La Clase JTable):

Como se ha estudiado en las entradas anteriores, se pueden extraer datos de la base de datos a través de consultas SQL de tipo SELECT. Los datos extraídos se almacenan en objetos de tipo ResultSet.

Luego, solo hay que analizar el contenido del objeto ResultSet para extraer los datos que contiene y trabajar con ellos.

En las publicaciones anteriores hemos extraído los datos del ResultSet y los hemos presentado en un JOptionPane o en un JTextPane. Sin embargo, una mejor opción para presentar el contenido de un ResultSet es usar objetos de la clase JTable, ya que estos objetos tienen forma de tabla.

En este post se estudiarán los objetos de la clase JTable (sin tener en cuenta a las bases de datos). Una vez que entendamos el funcionamiento de los objetos del tipo JTable, los usaremos en posteriores publicaciones para presentar dentro de ellos el contenido de consultas SQL.



EJERCICIO GUIADO Nº 1

  1. Crea un nuevo proyecto en NetBeans. En la ventana principal de dicho proyecto agrega un objeto del tipo JTable:



Asigna al objeto JTable el nombre tablaDatos. Debes tener en cuenta que los objetos JTable se añaden siempre dentro de un panel de desplazamiento JScrollPane:



  1. El objeto tablaDatos que se acaba de introducir tiene por defecto cuatro columnas con los nombres “Title 1”, “Title 2”, “Title 3” y “Title 4”, y contiene cuatro filas vacías. Puedes ejecutar el programa para ver el funcionamiento del objeto tablaDatos. Pruebe a introducir algún dato en las celdas de la tabla:



  1. Aprenderemos ahora a configurar determinados aspectos de la tabla que vamos a usar. Para ello añada al método constructor una llamada a un método configurarTablaDatos que programaremos a continuación:



  1. Programa ahora el método configurarTablaDatos de la siguiente forma:



La primera línea del código define un array tipo String con los títulos de la tabla, es decir, con las columnas de la tabla.

A continuación, se construye un objeto del tipo DefaultTableModel, o dicho de otra manera, un modelo de tabla. El objeto detamo está declarado como variable global.


MODELOS (recordatorio):

Hay que recordar que existen objetos en java que contienen un objeto modelo, encargado de contener los datos del objeto. Un ejemplo de ello son las listas y los combos (cuadros desplegables).

Para definir los datos contenidos en el objeto, primero había que definir el modelo y luego asignar el modelo al objeto.

El caso de las tablas es igual. Para introducir datos en la tabla primero hay que configurar su objeto modelo (que será de la clase DefaultTableModel) y luego asignárselo a la tabla.

En el código, se define como global un objeto llamado detamo, de tipo DefaultTablaModel. Luego, al construir el objeto se deben indicar dos parámetros: null y el vector de títulos de columnas:

detamo = new DefaultTableModel(null, titulosTabla);

El valor null hace que la tabla aparezca vacía en un principio, mientras que el vector titulosTabla define las columnas que tendrá la tabla.

Una vez construido de esta forma el objeto modelo detamo, este se asigna al objeto tabla:

tablaDatos.setModel(detamo);

La razón por la que se ha declarado el objeto modelo detamo como global es que será usado en otros métodos del programa.


  1. Ejecuta el programa y observa el resultado:



Como puedes observar, se ha creado una tabla vacía con seis columnas correspondientes al vector titulosTabla.

  1. Vamos a añadir un botón a la ventana con el texto Agregar Fila, al cual llamaremos btnAgregarFila:



7. Dentro del botón btnAgregarFila programa lo siguiente



Este código añadirá una nueva fila en blanco a la tabla. Estudiemos cada línea:

La primera línea recoge el modelo de la tabla a través del método getModel. El modelo es recogido en la variable global detamo que creamos anteriormente. Observa como es necesario realizar un cast (en rojo) a la hora de asignar el modelo a la variable detamo:

detamo = (DefaultTableModel) tablaDatos.getModel();

El resultado de esta instrucción es que volvemos a tener disponible el modelo de la tabla en la variable detamo, y por tanto, podemos manipular los datos contenidos en la tabla a través de esta variable.

Por ejemplo, se usará el modelo detamo para añadir una fila en blanco en la tabla. Para ello, basta con crear un vector de cadenas de 6 elementos (ya que hay seis columnas):

String filaVacia[] = new String[6];

Y luego, a través del método addRow (añadir fila), añadir una fila correspondiente a los valores del vector:

detamo.addRow(filaVacia);

Debido a que el vector está vacío, la fila que se añade está vacía también. Si el vector contuviera algún dato, estos datos aparecerían en la fila que se añade (esto se verá a continuación).


  1. Ejecuta el programa y pulsa varias veces el botón Agregar Fila. Observarás como se van añadiendo filas vacías a la tabla:



  1. Para entender bien el funcionamiento de la inserción de filas en la tabla, añade otro botón llamado btnFilaConDatos con el texto Fila con Datos:



  1. En este botón programe lo siguiente:



Puedes observar que el código es parecido al anterior, solo que en este caso se añade una fila correspondiente a un vector relleno de datos. Esto quiere decir que cuando se añada esta fila al modelo aparecerá con los datos del vector.


  1. Ejecuta el programa y comprueba su funcionamiento, observarás que al pulsar el nuevo botón aparecen filas rellenas:



  1. Sigamos experimentando con la tabla. Ahora añadiremos un botón btnEliminar con el texto “Eliminar Fila”:



  1. Este botón eliminará la fila que esté seleccionada en ese momento. Para ello programe en este botón el siguiente código:



Estudiemos este código. En primer lugar usamos un método que poseen los objetos del tipo JTable llamado getSelectedRow que nos dice el número de la fila que está seleccionada en este momento.

Si no hubiera ninguna fila seleccionada, el método getSelectedRow devuelve el valor –1. Esto lo usamos en el if que viene a continuación para mostrar un mensaje de error diciendo que no hay fila seleccionada que se pueda borrar.

En el caso de que haya alguna fila seleccionada (es decir, que no se haya devuelto el valor  –1) entonces efectuamos el borrado.

Para borrar recogemos el modelo de la tabla y usamos un método llamado removeRow para borrar la fila seleccionada (la cual se pasa como parámetro).


  1. Ejecuta el programa y añade varias filas. Luego prueba a seleccionar alguna y pulsar el botón Eliminar Fila. Observa también lo que sucede cuando intentas eliminar una fila cuando no hay ninguna seleccionada:



  1. Sigamos aprendiendo nuevas cualidades de las tablas. Añada lo siguiente a su ventana:



  1. Lo que se pretende es lo siguiente: El usuario introducirá un valor de fila y de columna, por ejemplo: Fila 2, Columna 5, y al pulsarse el botón Obtener Valor de Celda aparecerá en la etiqueta etiValorCelda el contenido de la casilla situada en la posición 2, 5 (fila 2 columna 5).
Así pues programa lo siguiente en el botón Obtener Valor de Celda:


Analicemos el código:

Primero, se recogen los valores introducidos en los cuadros de texto de la fila y columna y se convierten a enteros:

fil = Integer.parseInt(txtFila.getText());
col = Integer.parseInt(txtColumna.getText());

Luego, se extrae el modelo de la tabla y se usa un método llamado getValueAt. Este método permite extraer el valor de una celda de la tabla, indicando la fila y columna de esa celda. El resultado lo hemos almacenado en una variable valorCelda de tipo cadena. Es necesario realizar un cast (en rojo):

valorCelda = (String) detamo.getValueAt(fil, col);

Finalmente, una vez extraído el valor de la celda de la posición fil, col este se coloca en la etiqueta etiValorCelda.

Este código es susceptible de dar error, por ejemplo si el usuario introduce unos valores de fila y columna incorrectos. Por eso ha sido incluido dentro de un try...catch.


  1.  Ejecuta el programa y añade varias filas. Introduce algunos valores en las filas. Luego prueba a introducir un valor de fila y columna y pulsa el botón Obtener Valor de Celda:



  1. Sigamos experimentando. Añade lo siguiente a la ventana:




  1. Se pretende lo siguiente. El usuario introducirá un valor de fila y de columna en los cuadros de texto correspondientes. Luego, el usuario introducirá un valor en el cuadro de texto txtNuevoValorDeCelda.  Finalmente pulsará el botón btnCambiarValorCelda.

El resultado será que se introduce el valor escrito en la posición de la tabla indicada por la fila y columna introducida.

Para hacer esto, programe lo siguiente dentro del botón btnCambiarValorCelda:



Estudiemos el código detenidamente.

Lo primero que se hace es extraer de los cuadros de texto la fila, columna y el valor a ingresar en la celda. La fila y columna son convertidas a enteros.

fil = Integer.parseInt(txtFila.getText());
col = Integer.parseInt(txtColumna.getText());

nuevoValorCelda = txtNuevoValorDeCelda.getText();

Luego se extrae (como siempre) el modelo de la tabla y se usa un método suyo llamado setValueAt que permite introducir un valor en una celda de la tabla. Concretamente, se introduce el valor escrito por el usuario en la celda con fila y columna indicadas:

detamo = (DefaultTableModel) tablaDatos.getModel();
detamo.setValueAt(nuevoValorCelda, fil, col);

Este código es susceptible de tener errores de ejecución (por ejemplo que el usuario introduzca un valor equivocado en la fila y columna) por eso está rodeado de un try...catch.


  1. Ejecuta el programa. Añade varias filas en blanco. Luego introduce un valor para la fila y la columna y escribe un valor que quieras introducir. Al pulsar el botón Cambiar Valor de Celda dicho valor aparecerá en la celda correspondiente:






CONCLUSIONES:
Existe una clase llamada JTable que permite crear objetos con forma de tabla.
Estos objetos son ideales para mostrar el contenido de las tablas de una base de datos, aunque pueden ser usados de forma independiente también para mostrar cualquier tipo de datos.
Los objetos del tipo JTable contienen un modelo de datos de tipo DefaultTableModel.
Cada vez que se quiera trabajar con una tabla será necesario construir su modelo y asignárselo a la tabla.
Cada vez que se quiera modificar de alguna forma los datos de una tabla, será necesario acceder a su modelo y trabajar con él.
A través del modelo de una tabla podemos añadir nuevas filas a la tabla, eliminar filas, extraer datos de las celdas de la tabla o añadir datos a las celdas de la tabla.