Tutorial de Java

Tablas

Anterior | Siguiente

Al igual que los árboles, las tablas en Swing son importantes y poderosas. En principio, se crearon para constituir un interfaz ligado a bases de datos a través del Java Database Connectivity (JDBC, para los amigos), y así evitar la complejidad inherente al manejo de los datos, proporcionando mucha flexibilidad al programador. Hay suficientes características como para montar desde una hoja de cálculo básica hasta información para escribir un libro completo. Sin embargo, también es posible crear una JTable relativamente simple si entiende correctamente el funcionamiento.

La JTable controla cómo se presentan los datos, siendo el TableModel quien controla los datos en sí mismos. Para crear una JTable habrá pues que crear un TableModel antes, normalmente. Se puede implementar, para ello, el interfaz TableModel, pero es mucho más simple heredar de la clase ayuda AbstractTableModel. El ejemplo java1416.java muestra esta circunstancia.

import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.table.*;
import com.sun.java.swing.event.*;

// El Modelo de la Tabla es el que controla todos los
// datos que se colocan en ella
class ModeloDatos extends AbstractTableModel {
  Object datos[][] = {
    {"uno","dos","tres","cuatro"},
    {"cinco","seis","siete","ocho"},
    {"nueve","diez","once","doce"},
  };
  
  // Esta clase imprime los datos en la consola cada vez
  // que se produce un cambio en cualquiera de las
  // casillas de la tabla
  class TablaListener implements TableModelListener {
    public void tableChanged( TableModelEvent evt ) {
      for( int i=0; i < datos.length; i++ ) {
        for( int j=0; j < datos[0].length; j++ )
          System.out.print( datos[i][j] + " " );
        System.out.println();
      }
    }
  }
  // Constructor
  ModeloDatos() {
    addTableModelListener( new TablaListener() );
  }
  // Devuelve el número de columnas de la tabla
  public int getColumnCount() { 
    return( datos[0].length ); 
  }
  // Devuelve el número de filas de la tabla
  public int getRowCount() { 
    return( datos.length );
  }
  // Devuelve el valor de una determinada casilla de la tabla
  // identificada mediante fila y columna
  public Object getValueAt( int fila,int col ) { 
    return( datos[fila][col] ); 
  }
  // Cambia el valor que contiene una determinada casilla de
  // la tabla
  public void setValueAt( Object valor,int fila,int col ) {
    datos[fila][col] = valor;
    // Indica que se ha cambiado
    fireTableDataChanged();
  }
  // Indica si la casilla identificada por fila y columna es
  // editable
  public boolean isCellEditable( int fila,int col ) { 
    return( true ); 
  }
}       


public class java1416 extends JPanel {
  public java1416() {
    setLayout( new BorderLayout() );
    JTable tabla = new JTable( new ModeloDatos() );
    // La tabla se añade a un ScrollPane para que sea éste el
    // que controle automáticamente en tamaño de la tabla,
    // presentando una barra de desplazamiento cuando sea
    // necesario
    JScrollPane panel = new JScrollPane( tabla );
    add( panel,BorderLayout.CENTER );
  }
  
  public static void main(String args[]) {
    JFrame frame = new JFrame( "Tutorial de Java, Swing" );
    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing( WindowEvent evt ) {
        System.exit( 0 );
      }
    } );
    frame.getContentPane().add( new java1416(),BorderLayout.CENTER );
    frame.setSize( 200,200 );
    frame.setVisible( true );
  }
} 

En el ejemplo, para no complicar la cosa, DataModel es quien contiene el conjunto de datos, pero también se podrían haber cogido de una base de datos. El constructor añade un receptor de eventos de tipo TableModelListener que va a imprimir el contenido de la tabla cada vez que se produzca un cambio. El resto de los métodos utilizan la notación de los Beans y son utilizados por el objeto JTable cuando se quiere presentar la información del DataModel. AbstractTableModel proporciona por defecto los métodos setValueAt() y isCellEditable() que se utilizan para cambiar los datos, por lo que si se quiere realizar esta operación, no queda más remedio que sobrescribir los dos métodos.

La figura siguiente muestra la Tabla obtenida tras la ejecución del programa en donde se ha editado la casilla correspondiente a la segunda fila y columna B.

Una vez que se tiene un TableModel, ya sólo resta colocarlo en el constructor de JTable. Todos los detalles de presentación, edición y actualización están ocultos al programador. En este ejemplo, se coloca la JTable en un JScrollPane, por lo que es necesario un método especial en JTable.

Las tablas pueden soportar un comportamiento más complejo. En el ejemplo java1417.java, se utiliza un método para cargar un array de ocho columnas por un ciento de filas y, posteriormente, la tabla es configurada para que muestre solamente las líneas verticales y permita la selección simultánea de la fila y columna en que se encuentre la celda marcada.

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import com.sun.java.swing.*;
import com.sun.java.swing.table.*;

class java1417 extends JPanel {
  private JTable tabla;
  private JScrollPane panelScroll;
  private String titColumna[];
  private String datoColumna[][];
  
  public java1417() {
    setLayout( new BorderLayout() );
    // Creamos las columnas y las cargamos con los datos que van a
    // aparecer en la pantalla
    CreaColumnas();
    CargaDatos();
    // Creamos una instancia del componente Swing
    tabla = new JTable( datoColumna,titColumna );
    // Aquí se configuran algunos de los parámetros que permite 
    // variar la JTable
    tabla.setShowHorizontalLines( false );
    tabla.setRowSelectionAllowed( true );
    tabla.setColumnSelectionAllowed( true );
    // Cambiamos el color de la zona seleccionada (rojo/blanco)
    tabla.setSelectionForeground( Color.white );
    tabla.setSelectionBackground( Color.red );
    // Incorporamos la tabla a un panel que incorpora ya una barra
    // de desplazamiento, para que la visibilidad de la tabla sea
    // automática
    panelScroll = new JScrollPane( tabla );
    add( panelScroll, BorderLayout.CENTER );
  }
  
  
  // Creamos las etiquetas que sirven de título a cada una de
  // las columnas de la tabla
  public void CreaColumnas() {
    titColumna = new String[8];
    
    for( int i=0; i < 8; i++ ) {
      titColumna[i] = "Col: "+i;
    }
  }
  
  // Creamos los datos para cada uno de los elementos de la tabla
  public void CargaDatos() {
    datoColumna = new String[100][8];
    
    for( int iY=0; iY < 100; iY++ ) {
      for( int iX=0; iX < 8; iX++ ) {
	datoColumna[iY][iX] = "" + iX + "," + iY;
      }
    }
  }
  
  
  public static void main( String args[] ) {
    JFrame ventana = new JFrame( "Tutorial de Java, Swing" );
    
    ventana.addWindowListener( new WindowAdapter() {
      public void windowClosing( WindowEvent evt ){
	System.exit( 0 );
      }
    } );
    ventana.getContentPane().add( new java1417(),BorderLayout.CENTER );
    ventana.setSize( 300,180 );
    
    ventana.setVisible( true );
  }
}

La figura siguiente muestra el resultado de la ejecución del ejemplo. Obsérvese que cuano se selecciona un elemento individual de la tabla, aparece una selección en cruz de fila y columna, centrada en la celda que se ha marcado. En este ejemplo los colores de fondo y texto para la región seleccionada se han alterado, que es otra de las facilidades que soporta el componente JTable, el cambio de color para un área de selección.

Aunque el ejemplo contiene un array relativamente grande de datos, la clase JTable no manipula demasiado bien grandes cantidades de información, resultando un rendimiento bastante pobre cuando se sobrepasan los 2000 elementos.

Navegador

Home | Anterior | Siguiente | Indice | Correo