Como Hacer un JTable personalizado

Publicado el 08 septiembre 2018 por Cristian David Henao Hoyos @chenaooo
En esta entrada les mostraré un ejemplo de un JTable personalizado, les compartiré el código y explicaré la lógica necesaria para que lo puedan vincular en sus proyectos, adicionalmente podrán consultar el paso a paso en mi canal de youtube.
Hola que tal, llevo mucho tiempo sin escribir entradas en el blog ya que me he dedicado principalmente a mi canal de youtube (si no lo conoces puedes encontrarlo aquí) pero tengo toda la intención de retomarlo nuevamente y así ir compartiendo diferentes entradas que como siempre, se que les puede servir.
En esta oportunidad y despúes de que hace mucho me preguntaran por esto, quise hacer este ejemplo sobre como personalizar un JTable, ya en otra ocasión mostré como crear un JTable y llenarlo desde la BD (lo puedes ver aquí) pero ahora les mostraré básicamente todo lo necesario para poder controlar el estilo visual de este componente, agregarle colores, vincular otros elementos como botones o iconos entre otras cosas... 
El resultado final será este

Para este caso les comparto las clases, trataré de explicarlo lo más simple posible pero al final compartiré el proyecto en GitHub para que lo puedan revisar mejor... listo, veamos!!!

Estructura del proyecto.

Esta es la estructura del proyecto, es un ejemplo muy simple pero por organización quise agrupar las clases necesarias en paquetes las cuales iré explicando paso a paso. 

Aplicacion.java

Esta es la clase principal, será la encargada de iniciar al sistema llamando a la ventanaTabla. 
import gui.VentanaTabla;
public class Aplicacion {
public static void main(String[] args) {
// TODO Auto-generated method stub
VentanaTabla miVentana=new VentanaTabla();
miVentana.setVisible(true);
}
}

Utilidades.java

Esta clase simplemente cumplirá la función de almacenar variables estáticas o constantes que usaremos en todo el sistema, especificamente para las referencias a las columnas de nuestra tabla.
package utilidades;
public class Utilidades {
public static final int DOCUMENTO=0;
public static final int NOMBRE=1;
public static final int DIRECCION=2;
public static final int TELEFONO=3;
public static final int PROFESION=4;
public static final int EDAD=5;
public static final int NOTA1=6;
public static final int NOTA2=7;
public static final int NOTA3=8;
public static final int PROMEDIO=9;
public static final int PERFIL=10;
public static final int EVENTO=11;
public static int filaSeleccionada;
}

PersonaVo.java

Esta clase básicamente es un pojo qué nos permitirá gestionar la información que se presente en nuestra tabla, para este caso como no vamos a trabajar con bases de datos entonces simplemente usaremos el constructor con parámetros para ir asignando la información de las personas.
package vo;
public class PersonaVo {
private String documento;
private String nombre;
private String direccion;
private String telefono;
private String profesion;
private int edad;
private double nota1;
private double nota2;
private double nota3;
private double promedio;
public PersonaVo(){

}
public PersonaVo(String documento, String nombre, String direccion, String telefono, String profesion, int edad,
double nota1, double nota2, double nota3, double promedio) {
super();
this.documento = documento;
this.nombre = nombre;
this.direccion = direccion;
this.telefono = telefono;
this.profesion = profesion;
this.edad = edad;
this.nota1 = nota1;
this.nota2 = nota2;
this.nota3 = nota3;
this.promedio = promedio;
}
public String getDocumento() {
return documento;
}
public void setDocumento(String documento) {
this.documento = documento;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDireccion() {
return direccion;
}
public void setDireccion(String direccion) {
this.direccion = direccion;
}
public String getTelefono() {
return telefono;
}
public void setTelefono(String telefono) {
this.telefono = telefono;
}
public String getProfesion() {
return profesion;
}
public void setProfesion(String profesion) {
this.profesion = profesion;
}
public int getEdad() {
return edad;
}
public void setEdad(int edad) {
this.edad = edad;
}
public double getNota1() {
return nota1;
}
public void setNota1(double nota1) {
this.nota1 = nota1;
}
public double getNota2() {
return nota2;
}
public void setNota2(double nota2) {
this.nota2 = nota2;
}
public double getNota3() {
return nota3;
}
public void setNota3(double nota3) {
this.nota3 = nota3;
}
public double getPromedio() {
return promedio;
}
public void setPromedio(double promedio) {
this.promedio = promedio;
}
}

GestionEncabezadoTabla.java

Esta clase como ya se imaginarán es la encargada de definir el estilo visual del encabezado, aquí podremos establecer cual es el color del texto, tipo de fuente y color de las columnas a presentar, para eso debemos implementar la interfaz lo que permitirá sobreescribir el método getTableCellRendererComponent() encargado de la personalización.
package utilidades;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.TableCellRenderer;
//
// Permite personalizar el encabezado de la tabla para definir el color que tendrá en las
// columnas
// @author CHENAO
//
//
public class GestionEncabezadoTabla implements TableCellRenderer {

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

JComponent jcomponent = null;

if( value instanceof String ) {
jcomponent = new JLabel((String) value);
((JLabel)jcomponent).setHorizontalAlignment( SwingConstants.CENTER );
((JLabel)jcomponent).setSize( 30, jcomponent.getWidth() );
((JLabel)jcomponent).setPreferredSize( new Dimension(6, jcomponent.getWidth()) );
}

//jcomponent.setBorder(javax.swing.BorderFactory.createMatteBorder(0, 0, 1, 1, new java.awt.Color(221, 211, 211)));
jcomponent.setBorder(javax.swing.BorderFactory.createMatteBorder(0, 0, 1, 1, new java.awt.Color(255, 255, 255)));
jcomponent.setOpaque(true);
//jcomponent.setBackground( new Color(236,234,219) );
jcomponent.setBackground( new Color(65,65,65) );
jcomponent.setToolTipText("Tabla Seguimiento");
jcomponent.setForeground(Color.white);

return jcomponent;
}
}

ModeloTabla.java

Esta clase hereda de la clase DefaultTableModel y nos permitirá definir el modelo que alimentará a la tabla con los titulos de las columnas y los datos a presentar.
package utilidades;
import javax.swing.table.DefaultTableModel;
public class ModeloTabla extends DefaultTableModel{
String[] titulos;
Object[][] datos;
//
// Determina el modelo con el que se va a construir la tabla
// @param datos
// @param titulos
//
public ModeloTabla(Object[][] datos, String[] titulos) {
super();
this.titulos=titulos;
this.datos=datos;
setDataVector(datos, titulos);
}
public ModeloTabla() {
// TODO Auto-generated constructor stub
}
public boolean isCellEditable (int row, int column)
{
//Definimos si una celda puede ser o no editable
if (column!=Utilidades.PERFIL & column!=Utilidades.EVENTO & column!=Utilidades.NOTA1 & column!=Utilidades.NOTA2 & column!=Utilidades.NOTA3){
return false;
}else{
return true;
}
}
}

adicionalmente se usa el método isCellEditable(int row, int column) que nos permitirá definir cuales campos de que columnas podrán ser editables o no, esto para el caso de que queramos introducir datos directamente o simplemente bloquear esta posiblidad.

GestionCeldas.java

Esta es una de las clases principales ya que determina el aspecto visual de la tabla específicamente hablando de las celdas, fuentes, componentes gráficos que queramos vincular entre otros aspectos, para este proceso heredamos de la clase DefaultTableCellRenderer y sobreescribimos el método getTableCellRendererComponent() que será llamado cada que se escuche algún evento sobre la tabla y así definir las acciones sobre las celdas.
package utilidades;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
//
// Esta clase permite gestionar la tabla y los eventos realizados sobre ella
// cada celda seria un objeto personalizable
// @author CHENAO
//
//
public class GestionCeldas extends DefaultTableCellRenderer{
private String tipo="text";
//se definen por defecto los tipos de datos a usar
private Font normal = new Font( "Verdana",Font.PLAIN ,12 );
private Font bold = new Font( "Verdana",Font.BOLD ,12 );
//etiqueta que almacenará el icono a mostrar
private JLabel label = new JLabel();
//iconos disponibles para ser mostrados en la etiqueta dependiendo de la columna que lo contenga
private ImageIcon iconoGuardar = new ImageIcon(getClass().getResource("/recursos/iconos/ico_guardar.png"));
private ImageIcon iconoBuscar = new ImageIcon(getClass().getResource("/recursos/iconos/ico_buscar.png"));

public GestionCeldas(){

}
//
//constructor explicito con el tipo de dato que tendrá la celda
// @param tipo
//
public GestionCeldas(String tipo){
this.tipo=tipo;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean focused, int row, int column) {

//
//Este metodo controla toda la tabla, podemos obtener el valor que contiene
// definir que celda está seleccionada, la fila y columna al tener el foco en ella.
//
// cada evento sobre la tabla invocará a este metodo
//

//definimos colores por defecto
Color colorFondo = null;
Color colorFondoPorDefecto=new Color( 192, 192, 192);
Color colorFondoSeleccion=new Color( 140, 140 , 140);

/*
* Si la celda del evento es la seleccionada se asigna el fondo por defecto para la selección
*/
if (selected) {
this.setBackground(colorFondoPorDefecto );
}
else
{
//Para las que no están seleccionadas se pinta el fondo de las celdas de blanco
this.setBackground(Color.white);
}

/*
* Se definen los tipos de datos que contendrán las celdas basado en la instancia que
* se hace en la ventana de la tabla al momento de construirla
*/
if( tipo.equals("texto"))
{
//si es tipo texto define el color de fondo del texto y de la celda así como la alineación
if (focused) {
colorFondo=colorFondoSeleccion;
}else{
colorFondo= colorFondoPorDefecto;
}
this.setHorizontalAlignment( JLabel.LEFT );
this.setText( (String) value );
//this.setForeground( (selected)? new Color(255,255,255) :new Color(0,0,0) );
//this.setForeground( (selected)? new Color(255,255,255) :new Color(32,117,32) );
this.setBackground( (selected)? colorFondo :Color.WHITE);
this.setFont(normal);
//this.setFont(bold);
return this;
}

//si el tipo es icono entonces valida cual icono asignar a la etiqueta.
if( tipo.equals("icono"))
{
if( String.valueOf(value).equals("PERFIL") )
{
label.setIcon(iconoBuscar);
}
else if( String.valueOf(value).equals("EVENTO") )
{
label.setIcon(iconoGuardar);
}
label.setHorizontalAlignment( JLabel.LEFT );
label.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
// return boton;
return label;
}

//definie si el tipo de dato el numerico para personalizarlo
if( tipo.equals("numerico"))
{
if (focused) {
colorFondo=colorFondoSeleccion;
}else{
colorFondo=colorFondoPorDefecto;
}
// System.out.println(value);
this.setHorizontalAlignment( JLabel.CENTER );
this.setText( (String) value );
this.setForeground( (selected)? new Color(255,255,255) :new Color(32,117,32) );
this.setBackground( (selected)? colorFondo :Color.WHITE);
// this.setBackground( (selected)? colorFondo :Color.MAGENTA);
this.setFont(bold);
return this;
}

return this;
}
}
para definir los eventos sobre las celdas, cosas como cambiar de color si la celda contendrá datos numéricos o si se van a mostrar componentes graficos dentro de la celdas se usa la variable tipo y dependiendo de este se realiza la lógica necesaria de personalización.

VentanaTablas.java

Por último tenemos la ventana de nuestro sistema donde se presentará la tabla personalizada, aquí usamos las constantes de la clase Utilidades.java para definir las columnas que se presentarán, así mismo el método construirTabla() se encargará de definir el modelo y generar las instancias de la clase GestionCeldas.java 
package gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.table.JTableHeader;
import utilidades.GestionCeldas;
import utilidades.GestionEncabezadoTabla;
import utilidades.ModeloTabla;
import utilidades.Utilidades;
import vo.PersonaVo;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.awt.Font;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class VentanaTabla extends JFrame implements MouseListener{
private JPanel contentPane;
private JScrollPane scrollPaneTabla;
private JTable tablaPersonas;
ArrayList listaPersonas;//lista que simula la información de la BD
ModeloTabla modelo;//modelo definido en la clase ModeloTabla
private int filasTabla;
private int columnasTabla;
public VentanaTabla() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1121, 453);

iniciarComponentes();
setLocationRelativeTo(null);
construirTabla();
}
private void iniciarComponentes() {
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));

JLabel lblTablaPersonas = new JLabel("Tabla Personas");
lblTablaPersonas.setFont(new Font("Rockwell", Font.BOLD, 25));
contentPane.add(lblTablaPersonas, BorderLayout.NORTH);

scrollPaneTabla = new JScrollPane();
contentPane.add(scrollPaneTabla);

tablaPersonas = new JTable();
tablaPersonas.setBackground(Color.WHITE);
tablaPersonas.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
tablaPersonas.addMouseListener(this);
//tablaSeguimiento.addKeyListener(this);
tablaPersonas.setOpaque(false);
scrollPaneTabla.setViewportView(tablaPersonas);

}
//
//Metodo que permite construir la tabla de personas
//se crean primero las columnas y luego se asigna la información
//
private void construirTabla() {

listaPersonas=consultarListaPersonas();

ArrayList titulosList=new ArrayList<>();

titulosList.add("Documento");
titulosList.add("Nombre");
titulosList.add("Direccion");
titulosList.add("Telefono");
titulosList.add("Profesion");
titulosList.add("Edad");
titulosList.add("Nota1");
titulosList.add("Nota2");
titulosList.add("Nota3");
titulosList.add("Promedio");
titulosList.add(" ");
titulosList.add(" ");

//se asignan las columnas al arreglo para enviarse al momento de construir la tabla
String titulos[] = new String[titulosList.size()];
for (int i = 0; i < titulos.length; i++) {
titulos[i]=titulosList.get(i);
}
//obtenemos los datos de la lista y los guardamos en la matriz
//que luego se manda a construir la tabla
Object[][] data =obtenerMatrizDatos(titulosList);
construirTabla(titulos,data);

}
//
//Permite simular el llenado de personas en una lista
//que posteriormente alimentará la tabla
//@return
//
private ArrayList consultarListaPersonas() {
ArrayList lista=new ArrayList<>();

lista.add(new PersonaVo("1234", "Cristian David Henao", "Calle 2# 23-09 Armenia", "7564323", "Ingeniero",23, 2.5, 4.3, 3.0, (2.5+4.3+3)/33));
lista.add(new PersonaVo("3455", "Juan Camilo Perez", "Calle 2# 23-09 Armenia", "7564323", "Ingeniero",0, 0, 0,0,0));
lista.add(new PersonaVo("3214", "Marlon Guapacha", "Calle 2# 23-09 Armenia", "7564323", "Ingeniero",0, 0, 0,0,0));
lista.add(new PersonaVo("7886", "Marina Marin", "Calle 2# 23-09 Armenia", "7564323", "Ingeniero",0, 0, 0,0,0));
lista.add(new PersonaVo("4331", "Juliana Henao", "Calle 2# 23-09 Armenia", "7564323", "Ingeniero",0, 0, 0,0,0));
lista.add(new PersonaVo("98675", "David Henao", "Calle 2# 23-09 Armenia", "7564323", "Ingeniero",0, 0, 0,0,0));
lista.add(new PersonaVo("1221", "Cristian mendez Henao", "Calle 2# 23-09 Armenia", "7564323", "Ingeniero",0, 0, 0,0,0));

return lista;
}
//
// Llena la información de la tabla usando la lista de personas trabajada
// anteriormente, guardandola en una matriz que se retorna con toda
// la información para luego ser asignada al modelo
// @param titulosList
// @return
//
private Object[][] obtenerMatrizDatos(ArrayList titulosList) {

//se crea la matriz donde las filas son dinamicas pues corresponde
//a todos los usuarios, mientras que las columnas son estaticas
// correspondiendo a las columnas definidas por defecto
//
String informacion[][] = new String[listaPersonas.size()][titulosList.size()];

for (int x = 0; x < informacion.length; x++) {

informacion[x][Utilidades.DOCUMENTO] = listaPersonas.get(x).getDocumento()+ "";
informacion[x][Utilidades.NOMBRE] = listaPersonas.get(x).getNombre()+ "";
informacion[x][Utilidades.DIRECCION] = listaPersonas.get(x).getDireccion()+ "";
informacion[x][Utilidades.TELEFONO] = listaPersonas.get(x).getTelefono()+ "";
informacion[x][Utilidades.PROFESION] = listaPersonas.get(x).getProfesion()+ "";
informacion[x][Utilidades.EDAD] = listaPersonas.get(x).getEdad()+ "";
informacion[x][Utilidades.NOTA1] = listaPersonas.get(x).getNota1()+ "";
informacion[x][Utilidades.NOTA2] = listaPersonas.get(x).getNota2()+ "";
informacion[x][Utilidades.NOTA3] = listaPersonas.get(x).getNota3()+ "";
informacion[x][Utilidades.PROMEDIO] = listaPersonas.get(x).getPromedio()+ "";
//se asignan las plabras clave para que en la clase GestionCeldas se use para asignar el icono correspondiente
informacion[x][Utilidades.PERFIL] = "PERFIL";
informacion[x][Utilidades.EVENTO] = "EVENTO";
}

return informacion;
}
//
// Con los titulos y la información a mostrar se crea el modelo para
// poder personalizar la tabla, asignando tamaño de celdas tanto en ancho como en alto
// así como los tipos de datos que va a poder soportar.
// @param titulos
// @param data
//
private void construirTabla(String[] titulos, Object[][] data) {
modelo=new ModeloTabla(data, titulos);
//se asigna el modelo a la tabla
tablaPersonas.setModel(modelo);

filasTabla=tablaPersonas.getRowCount();
columnasTabla=tablaPersonas.getColumnCount();

//se asigna el tipo de dato que tendrán las celdas de cada columna definida respectivamente para validar su personalización
tablaPersonas.getColumnModel().getColumn(Utilidades.EDAD).setCellRenderer(new GestionCeldas("numerico"));
tablaPersonas.getColumnModel().getColumn(Utilidades.NOTA1).setCellRenderer(new GestionCeldas("numerico"));
tablaPersonas.getColumnModel().getColumn(Utilidades.NOTA2).setCellRenderer(new GestionCeldas("numerico"));
tablaPersonas.getColumnModel().getColumn(Utilidades.NOTA3).setCellRenderer(new GestionCeldas("numerico"));
tablaPersonas.getColumnModel().getColumn(Utilidades.PROMEDIO).setCellRenderer(new GestionCeldas("numerico"));
tablaPersonas.getColumnModel().getColumn(Utilidades.PERFIL).setCellRenderer(new GestionCeldas("icono"));
tablaPersonas.getColumnModel().getColumn(Utilidades.EVENTO).setCellRenderer(new GestionCeldas("icono"));

//se recorre y asigna el resto de celdas que serian las que almacenen datos de tipo texto
for (int i = 0; i < titulos.length-7; i++) {//se resta 7 porque las ultimas 7 columnas se definen arriba
System.out.println(i);
tablaPersonas.getColumnModel().getColumn(i).setCellRenderer(new GestionCeldas("texto"));
}

tablaPersonas.getTableHeader().setReorderingAllowed(false);
tablaPersonas.setRowHeight(25);//tamaño de las celdas
tablaPersonas.setGridColor(new java.awt.Color(0, 0, 0));
//Se define el tamaño de largo para cada columna y su contenido
tablaPersonas.getColumnModel().getColumn(Utilidades.DOCUMENTO).setPreferredWidth(130);//documento
tablaPersonas.getColumnModel().getColumn(Utilidades.NOMBRE).setPreferredWidth(380);//nombre
tablaPersonas.getColumnModel().getColumn(Utilidades.DIRECCION).setPreferredWidth(350);//direccion
tablaPersonas.getColumnModel().getColumn(Utilidades.TELEFONO).setPreferredWidth(130);//telefono
tablaPersonas.getColumnModel().getColumn(Utilidades.PROFESION).setPreferredWidth(280);//profesion
tablaPersonas.getColumnModel().getColumn(Utilidades.EDAD).setPreferredWidth(80);//edad
tablaPersonas.getColumnModel().getColumn(Utilidades.NOTA1).setPreferredWidth(100);//nota1
tablaPersonas.getColumnModel().getColumn(Utilidades.NOTA2).setPreferredWidth(100);//nota2
tablaPersonas.getColumnModel().getColumn(Utilidades.NOTA3).setPreferredWidth(100);//nota3
tablaPersonas.getColumnModel().getColumn(Utilidades.PROMEDIO).setPreferredWidth(130);//promedio
tablaPersonas.getColumnModel().getColumn(Utilidades.PERFIL).setPreferredWidth(30);//accion perfil
tablaPersonas.getColumnModel().getColumn(Utilidades.EVENTO).setPreferredWidth(30);//accion evento

//personaliza el encabezado
JTableHeader jtableHeader = tablaPersonas.getTableHeader();
jtableHeader.setDefaultRenderer(new GestionEncabezadoTabla());
tablaPersonas.setTableHeader(jtableHeader);

//se asigna la tabla al scrollPane
scrollPaneTabla.setViewportView(tablaPersonas);
}
@Override
public void mouseClicked(MouseEvent e) {
//capturo fila o columna dependiendo de mi necesidad
int fila = tablaPersonas.rowAtPoint(e.getPoint());
int columna = tablaPersonas.columnAtPoint(e.getPoint());

//uso la columna para valiar si corresponde a la columna de perfil garantizando
// que solo se produzca algo si selecciono una fila de esa columna
//
if (columna==Utilidades.PERFIL) {
//sabiendo que corresponde a la columna de perfil, envio la posicion de la fila seleccionada
validarSeleccionMouse(fila);
}else if (columna==Utilidades.EVENTO){//se valida que sea la columna del otro evento
JOptionPane.showMessageDialog(null, "Evento del otro icono");
}

}
//
// Este metodo simularia el proceso o la acción que se quiere realizar si
// se presiona alguno de los botones o iconos de la tabla
// @param fila
//
private void validarSeleccionMouse(int fila) {
Utilidades.filaSeleccionada=fila;


//teniendo la fila entonces se obtiene el objeto correspondiente para enviarse como parammetro o imprimir la información
PersonaVo miPersona=new PersonaVo();
miPersona.setDocumento(tablaPersonas.getValueAt(fila, Utilidades.DOCUMENTO).toString());
miPersona.setNombre(tablaPersonas.getValueAt(fila, Utilidades.NOMBRE).toString());

String info="INFO PERSONA\n";
info+="Documento: "+miPersona.getDocumento()+"\n";
info+="Nombre: "+miPersona.getNombre()+"\n";

JOptionPane.showMessageDialog(null, info);
}
//estos metododos pueden ser usados dependiendo de nuestra necesidad, por ejemplo para cambiar el tamaño del icono al ser presionado
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub

}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub

}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub

}
@Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub

}
}
Como pueder ver implementamos la interfaz MouseListener para definir los eventos del mouse en los iconos vinculados a la tabla, este proceso lo veremos en el onClick();
Y listo, todo el código se encuenta documentado pero adicionalmente lo pueden encontrar en mi GITHUB desde este enlace, aquí termina nuestro ejemplo, espero que les pueda servir y sea de fácil entendimiento...
También te podría Interesar.
  • Imagenes en Java
  • Componentes de Texto.
  • Componentes Atomicos Java Swing
  • Componentes Java Swing
  • Que es Java Swing?
  • Clases Abstractas.
  • Herencia en Java.
  • ¿ String Vrs StringBuffer Vrs StringBuilder ?
  • Comparando Fechas En Java
  • Tutorial Aplicaciones Web con Jboss Seam

¿Hay algo que quieras anexar o comentar sobre esta entrada?  no dudes en hacerlo.....y si te gustó...... te invito a compartir
 y Suscribirte ingresando al botón "Participar en este sitio" para darte cuenta de mas entradas como esta ;)