Al igual que los árboles, las tablas es uno de los elementos más complejos de manejar dentro de swing por la cantidad de posibilidades que ofrece. Su comentado es el de representan datos de manera estructurada con posibilidades de representación personalizada. Para poder crear una tabla, hay que tener en cuenta que esta tendrá que estar dentro de un JScrollPane para que pueda ser visible en su totalidad. El constructor de la tabla es:

JTable tabla = new JTable(datosFilas, nombreColumnas);

Como constructor se puede pasar por parámetros multitud de opciones: array multidimensional de objetos y array de string, número de filas número de columnas, modelo de datos, etc… siempre dependiendo de las necesidades. Los tipos de creación son los siguientes.

Mediante datos simples

Esta creación se basa en la existencia de dos array donde se pasan directamente los datos a la tabla. Esta forma de trabajar no es muy recomendable ya que se trataría de una tabla con datos estáticos. Siempre que se quiera realizar cualquier acción se debe hacer directamente sobre la tabla

nombreColumnas = new String[]{"Nombre", "Apellido", "Telefono", "Trabajando"};
datosFilas = new Object[][]{{"Nombre1", "Apellido", 123, true},
                {"Nombre2", "Apellido", 123, true},
                {"Nombre3", "Apellido", 123, true}};
tabla = new JTable(datosFilas, nombreColumnas);
scrollPane = new JScrollPane(tabla);
this.add(scrollPane);

Además de tratarse de datos estáticos, cada una de las casillas actúa de forma independiente por lo que no se guarda el tipo correspondiente al mismo tiempo que pueden ser editadas.

Mediante un modelo simple

Se parece mucho a la forma anterior pero en este caso se separa la parte gráfica de la parte de datos, pudiendo añadir / borrar / modificar directamente sobre los datos y no sobre la parte gráfica, convirtiendo al componente en algo dinámico. Cuando se quiera realizar cualquier acción se debe hacer sobre el modelo.

nombreColumnas = new String[]{"Nombre", "Apellido", "Telefono", "Trabajando"};
datosFilas = new Object[][]{{"Nombre1", "Apellido", 123, true},
                {"Nombre2", "Apellido", 123, true},
                {"Nombre3", "Apellido", 123, true}};
modeloTabla = new DefaultTableModel(datosFilas, nombreColumnas);
tabla = new JTable(modeloTabla);
scrollPane = new JScrollPane(tabla);

Las características negativas del no guardado de los tipos, edición por defecto siguen estando presentes es esta modalidad pero se pueden modificar mediante métodos que se verán más adelante.

Mediante un modelo personalizado

Se trata de la opción más completa ya que permite indicar a la tabla como debe de rellenarse de forma dinámica al mismo tiempo que se pueden marcar tipos, ediciones, incluso forma de representar de cada una de las celdas. Para poder hacer esto se debe extender de DefaultTableModel o de AbstractTableModel y rellenar cada uno de los métodos que se necesiten. El primero utiliza parte del modelo simple pero personalizando ciertas partes gracias a la sobrescrita de métodos siendo un ejemplo

public class ModeloDefault extends DefaultTableModel {

    Class[] tipos = new Class[]{String.class,String.class,Integer.class,Boolean.class};
    Boolean[] editables = new Boolean[]{false,false,false,true};

    //Utiliza la definición del modelo simple para obtener las columnas y datos pasados
    public ModeloDefault(Object[][] data, Object[] columnNames) {
        super(data, columnNames);
    }
    //Configura una clase para cada una de las columnas. De esta forma cada columna mantiene el tipo determinado 
    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return tipos[columnIndex];
    }
    //Indica si cada celda (o cada columna) es evitable
    @Override
    public boolean isCellEditable(int row, int column) {
        return editables
; } }

Por último tan solo falta llamar al modelo en la clase donde esté presente la tabla

nombreColumnas = new Object[]{"Nombre", "Apellido", "Telefono", "Trabajando"};
datosFilas = new Object[][]{{"Nombre1", "Apellido", 123, true},
        {"Nombre2", "Apellido", 123, true},
        {"Nombre3", "Apellido", 123, true}};
ModeloDefault modeloDefault = new ModeloDefault(datosFilas,nombreColumnas);

Este tipo de modelo tiene más métodos que se pueden sobre escribir, pero se explicarán en el modelo Abstracto.

Tratamiento de datos dento de una tabla

Los métodos que se pueden utilizar dentro de una tabla se diferencian si se utiliza un modelo o se accede directamente a la tabla. El método más recomendable es el acceso a los datos sobre el modelo.

Información de la tabla

Son muchas las informaciones que se pueden obtener de una tabla ya que a la hora de conectar con base de datos esto puede se muy útil. Algunas de las informaciones que se pueden obtener son:

//Obtiene el número de columnas
modeloDefault.getColumnCount()
//Obtiene el número de filas
modeloDefault.getRowCount()
//Obtiene el nombre de la columna cuya posición es 0
modeloDefault.getColumnName(0)
//Obtiene la posición de la columna cuyo nombre es "Nombre"
modeloDefault.findColumn("Nombre")
//Obtiene la fila seleccionada
modeloDefault.getSelectedRow()
//Notifica un cambio dentro de los datos de la tabla
modeloDefault.fireTableDataChanged();

Agregar filas

Las posibilidades son o bien ejecutar el método addRow que coloca el elemento al final de la tabla o el método inserRow que coloca el elemento en la posición especificada

Object[] datoAgregar = {"Nombre","Apellido",123,false};
modeloDefault.addRow(datoAgregar);
modeloDefault.insertRow(0,datoAgregar);

Eliminar filas

Para eliminar una fila o conjunto de filas se puede hacer directamente accediendo a la posición de la tabla o bien a la selección a través del modelo de selección

modeloDefault.removeRow(tabla.getSelectedRow());
modeloDefault.removeRow(tabla.getSelectionModel().getLeadSelectionIndex());

Obtener información celda / fila

Para obtener información de una celda se ejecuta el método getValueAt, pasándole la fila y columnas seleccionadas

System.out.println(modeloDefault.getValueAt(tabla.getSelectedRow(),tabla.getSelectedColumn()));
for (int i = 0; i< modeloDefault.getColumnCount();i++){
     System.out.println(modeloDefault.getValueAt(tabla.getSelectedRow(),i));

Manejo de eventos

Para poder manejar los eventos de una tabla se puede hacer cuando se produce un cambio en la estructura de los datos (datos añadidos, modificados, eliminados) , o cuando se cambia la selección dentro de la tabla.

Para evaluar los cambios en la estructura de la tabla se implementa la interfaz TableModelListener y se aplica al modelo de la tabla

modeloDefault.addTableModelListener(this);
@Override
public void tableChanged(TableModelEvent e) {
        int row = e.getFirstRow();
        int column = e.getColumn();
        Object data = modeloDefault.getValueAt(row, column);
        System.out.println(data);
}

Si se quiere evaluar el cambio en la selección se hace sobre el modelo de selección ListSelectionModel mediante la interfaz ListSelectioListener

modeloSeleccion = tabla.getSelectionModel();
modeloSeleccion.addListSelectionListener(this);
@Override
public void valueChanged(ListSelectionEvent e) {
    System.out.println(modeloDefault.getValueAt(tabla.getSelectedRow(),tabla.getSelectedColumn()));

}