jueves, 3 de mayo de 2012

JTable con imágenes y texto

9 comentarios
Hola a todos y especialmente a Marmoleria Cañones que es la persona que me pidió esta nueva entrada sobre JTable.

En la sección CONSULTAS ¿NECESITAS AYUDA CON TU CÓDIGO? me pedía si podía hacer un nuevo ejemplo con un TableCellRenderer para poder mostrar una imagen y una descripción en un JTable...

Nada más fácil, el TableCellRenderer por defecto que tiene instalado la clase JTable nos renderiza las imágenes sin necesidad de introducir código nuevo. Por lo tanto solo tenemos que pasar un objeto de la clase ImageIcon como contenido de una fila y se pintará automáticamente, siempre que la clase TableCellRenderer sepa que tipo de objeto debe pintar.
Por lo tanto la clave de esto pasa por decir que tipo de objeto se debe pintar, el modelo de datos por defecto de un JTable es el DefaultTableModel, este modelo hace creer al renderer que todos los objetos que debe pintar son Object, por lo que lo único necesario para poder mostrar una imagen es crear una clase que extienda DefaultTableModel y sobreescribir el método que indica que tipo de objeto contiene cada columna.
En el modelo por defecto tenemos:
public Class<?> getColumnClass(int columnIndex) {
 return Object.class;
    }
Y la modificación que debemos hacer:
 private class MyTableModel extends DefaultTableModel {

     public MyTableModel(Object[][] data, Object[] columnNames) {
         super(data, columnNames);
     }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
                Class<?> clazz = Object.class;
  Object aux = getValueAt(0, columnIndex);
   if (aux != null) {
    clazz = aux.getClass();
   }
   
   return clazz;
  }
  
 }


Es decir, nuestra tabla queda así:
package tableIconoDescripcion;

import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class Table extends JTable {

 public Table() {
  super();
  String [] columnNames = new String[]{ "Nombre", "Icono", "Descripción"};
        Object [][] data      = new Object[][]{
          {"Angel", createImage("icono1.jpg"), "angelarcosheredia@gmail.com"},
          {"Juan", createImage("icono2.jpg"), "juan@gmail.com", false},
          {"Ana", createImage("icono3.jpg"), "ana@hotmail.com", false}
          };
        MyTableModel model = new MyTableModel(data, columnNames);
        this.setRowHeight(100);
        this.setModel(model);
 }

 /**
  * Para recuperar una imagen de un archivo...
  * @param path Ruta de la imagen relativa al proyecto
  * @return una imagen
  */
 public ImageIcon createImage(String path) {
  URL imgURL = getClass().getResource(path);
     if (imgURL != null) {
         return new ImageIcon(imgURL);
     } else {
         System.err.println("Couldn't find file: " + path);
         return null;
     }
 }

 private class MyTableModel extends DefaultTableModel {

     public MyTableModel(Object[][] data, Object[] columnNames) {
         super(data, columnNames);
     }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
   Class<?> clazz = Object.class;
   Object aux = getValueAt(0, columnIndex);
   if (aux != null) {
    clazz = aux.getClass();
   }

   return clazz;
  }

 }

}


Este sería el resultado obtenido:



Y para lanzar la aplicación simplemente ejecutamos este código.
package tableIconoDescripcion;

import javax.swing.JFrame;
import javax.swing.JScrollPane;


public class Main {

 private static void createAndShowGUI() {
  JFrame frame = new JFrame("Componentes Swing en JTable");

  final Table table = new Table();

  // La añadimos a un scroll para mostrar la cabecera
  JScrollPane scroll = new JScrollPane(table);

  frame.add(scroll);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     frame.setSize(800, 200);
     frame.setVisible(true);
 }

 public static void main(String[] args) {

  javax.swing.SwingUtilities.invokeLater(new Runnable() {
   public void run() {
    createAndShowGUI();
   }
  });
 }

}

Eso es todo, para cualquier otra aclaración, no dudéis en contactar conmigo.

Un saludo