Ejemplos java y C/linux

Tutoriales

Enlaces

Licencia

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Para reconocer la autoría debes poner el enlace https://old.chuidiang.org

Ejemplo de TableModel en JTable

Vamos a ver cómo utilizar un JTable de java. Pudes ver un applet de ejemplo y el código fuente.

Un JTable es un componente visual de java que nos permite dibujar una tabla, de forma que en cada fila/columna de la tabla podamos poner el dato que queramos; un nombre, un apellido, una edad, un número, etc, etc.

Como muchos componentes de java, se ha seguido una separación modelo-vista . La vista es el componente visual que vemos en pantalla, el modelo es una clase que contiene los datos que luego se verán en pantalla. El modelo de datos únicamente contiene los datos, nosabe nada de quién va a visulizar los datos ni como.

La forma más rápida y sencilla

Aparte de usar otros constructores que hay en JTable, una de lasformas más rápidas y sencillas de utilizar un JTable teniendo toda su funcionalidad, consiste en instanciar como modelo de datos un DefaultTableModel y luego un JTable , pasándole el modelo en el constructor. El código quedaría:

DefaultTableModel modelo = new DefaultTableModel();
JTable tabla = new JTable (modelo);

A partir de ahora todo se maneja con el modelo. En cuanto añadamos, borremos o cambiemos datos del modelo, el JTable se enterará y actualizará automáticamente. El DefaultTableModel tiene todos los métodos necesarios para modificar datos en su interior, añadir filas o columnas y darle a cada columna el nombre que queramos

Vamos a hacer nuestro propio modelo de datos

El DefaultTableModel es un modelo genérico y puede no ser suficiente (o al menos, incómodo de usar) para nuestros propósitos.

Es bastante habitual el querer manejar la tabla como si fuera una lista, de forma que cada filacorresponde a una clase de datos y las columnas son los atributos de esaclase. Por ejemplo, queremos una lista de Persona y cada persona tiene unnombre, un apellido y una edad. Queremos pintar este lista en una tabla,de forma que tiene tres columnas (nombre, apellido y edad) y tantas filascomo Personas haya en la lista. A mi me gustaría tener un modelo alque le diga

modelo.anhadePersona (persona);

 y no un

modelo.setValueAt (fila, columna, persona.nombre);
columna++;
modelo.setValueAt (fila, columna, persona.apellido);
columna++;
modelo.setValueAt (fila, columna, edad);

y algo parecido para obtener o borrar una persona dentro del modelo.

Por ello, a veces esmás cómodo implementar nuestros propios modelos de tabla. Lacosa es fácil, únicamente debemos implementar la interfaceTableModel y luego poner además todos losmétodos que queramos, como el anhadePersona() o el damePersona() mencionados antes.

Una clase que implemente un TableModel debe redefinir los siguientes métodos:

class MiModelo implements TableModel
{
    public void addTableModelListener (TableModelListener l) {...}
    public Class getColumnClass (int columIndex) {...}
    public int getColumnCount() {...}
    public String getColumnName (int columnIndex) {...}
    public int getRowCount() {...}
    public Object getValueAt (int rowIndex, int columnIndex) {...}
    public boolean isCellEditable (int rowIndex, int columnIndex) {...}
    public void removeTableModelListener (TableModelListener l) {...}
    public void setValueAt (Object aValue, int rowIndex, int columnIndex)
}

Hay básicamente tres tipos de métodos:

Métodos para los suscriptores

Para implementar los métodos de los suscriptores necesitamos que nuestro modelo tenga una lista de suscriptores y únicamente hay que añadir o borrar suscriptores de esa lista. El código puede ser tan simple como esto:

class MiModelo implements TableModel
{
    public void addTableModelListener (TableModelListenerl) {
        suscriptores.add (l);
    }

    public void removeTableModelListener (TableModelListener l) {
        suscriptores.remove(l);< BR >     }

    private LinkedList suscriptores = new LinkedList();
}

Si en vez de implementar TableModel, heredamos de AbstractTableModel , ya tenemos esto implementado, además de otra serie de métodos que nos serán útiles más adelante.

Metodos para manejo de los datos

Para el manejode datos, sólo tenemos dos métodos. El que pone un dato enuna fila,columna y el que lo obtiene. Si seguimos con la idea de hacer unalista de personas, el código puede quedar como esto:

class MiModelo implements TableModel
{
    public void setValueAt (Object dato, int fila, int columna) {
         // Obtenemos la persona de la fila indicada
        Persona aux = (Persona)datos.get (fila);       
        switch (columna) {
           // Nos pasan el nombre.
           case 0:                                                     
               aux.nombre = (String)dato;
               break;
           // Nos pasan el apellido.
           case 1:                                                      
               aux.apellido = (String)dato;
               break;
           // Nos pasan la edad.
           case 2:                                                      
               aux.edad = ((Integer)dato).intValue();
               break;
        }

        // Aquí hay que avisar a los sucriptores del cambio.
        // Ver unpoco más abajo cómo.

    }

    public Object getValueAt (int fila, int columna) {
        // Obtenemos la persona de la fila indicada
        Persona aux = (Persona)datos.get (fila);         
        switch (columna) {
            // Nos piden el nombre
            case 0:                                                       
                return aux.nombre;
                break;
            // Nos piden el apellido
            case 1:                                                        
                return aux.apellido;
                break;
            // Nos piden la edad.
            case 2:                                                       
                return new Integer (aux.edad);
                break;
         }
         return null;
    }

    private LinkedList datos = new LinkedList();
}

Simplemente hemos declarado una lista de personas como atributo privado de la clase y hecho los switch necesarios para poner u obtener el campo concreto de Persona para la columna indicada. El Object recibido y devuelto para cada compo puede ser lo que nosotros queramos,pero para una fila,columna dada, debe ser del mismo tipo en ambos métodos. Dicho de otra forma, si devolvemos un Integer,nos pasarán un Integer. Además, debeser un Object (una instancia de una clase), por eso tratamos la edad como Integer y no como int.

El método setValueAt() tiene una pequeña pega. Cualquier modificación que hagamos en los datos, debe ser notificada a los suscriptores. Debemos crear un TableModelEvent , rellenarlo con los datos adecuados y avisar a los suscriptores.

El TableModelEvent se puede rellenar con el constructor. Parael caso de setValueAt() debemos ponerdespués de cambiar el dato (del switch) algo como esto

TableModelEvent evento = new TableModelEvent (this, fila, fila, columna);

Se le pasan como parámetros:

Una vez creado el evento, hay que pasárselo a los suscriptores a través de su método tableChanged()

int i;

for (i=0; i<suscriptores.size(); i++)
    ((TableModelListener)suscriptores.get(i)).tableChanged(evento);

Debemos hacer esto en todos los métodos que hagamos que cambien el modelo de datos, bien sea modificando datos, borrando o añadiendo filas o columnas.

Los demás métodos

Los demás métodos son de información general para la tabla y no tienen demasiado truco.

Otros métodos

Puesto que para eso hemos hecho este modelo, vamos a añadirle un par de métodos que nos son útiles para el ejemplo y nos facilitan el añadir y borrar personas:

public void anhadePersona (Persona nuevaPersona) {
    // Añade la persona al modelo
    datos.add (nuevaPersona);

    // Avisa a los suscriptores creando un TableModelEvent...
    TableModelEvent evento; evento = new TableModelEvent (
        this, this.getRowCount()-1, this.getRowCount()-1,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT);

    // ... y avisando a los suscriptores
    int i;

    for (i=0; i<suscriptores.size(); i++)
        ((TableModelListener)suscriptores.get(i)).tableChanged(evento);
}

En este caso, en el evento, hemos puesto como fila la última, quees la recién añadida. Como columna hemos puesto  TableModelEvent.ALL_COLUMNS que indica que todas las columnas se han visto afectadas. Finalmente, hay un nuevo parámetro que indica que la fila indicada se ha insertado. Si no ponemos nada en este parámetro (como en el caso del setValueAt()), indica queesos datos ya existían antes y que se han modificado.

Y otro método para borrar una fila:

public void borraPersona (int fila) {
    // Se borra la fila datos.remove(fila);

    // Y se avisa a los suscriptores, creando un TableModelEvent... 
    TableModelEvent evento = new TableModelEvent (this, fila, fila,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE);

    // ... y pasándoselo a los suscriptores
    int i;

    for (i=0; i<suscriptores.size(); i++)
        ((TableModelListener)suscriptores.get(i)).tableChanged(evento);
}

Nada especial que comentar. Se borra la fila que se indica, se crea el evento de forma similar al anterior, pero cambiando el último parámetro y se avisa a los suscriptores.

El ejemplo

Si quieres ver un applet con todo esto funcionando y los códigos fuente completos, pulsa aquí.

Estadísticas y comentarios

Numero de visitas desde el 4 Feb 2007:

Aviso Legal