Problema al establecer un editor propio en una JTable

Mabrev
05 de Febrero del 2004
Hola:

Estoy empezando a utilizar JTable, uso una para mostrar unos datos almacenados en una BD, y una de las columnas contiene fechas. A la hora de modificar una fecha, quiero que aparezca un calendario que permita seleccionar el nuevo valor, para ello he creado un editor específico. Al seleccionar la fecha y modificarla parece que va todo bien, pero al seleccionar otra celda, la que había sido modificada vuelve a su valor actual. Adjunto el código del render y del editor de la celda a ver si alguien puede echarme una mano.

Editor:
[CODE]
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import calendario.*;


public class EditorFecha extends JButton implements TableCellEditor
{
private Fecha fechaActual = null;
private boolean editable;
private boolean edicionFinalizada;

public EditorFecha(boolean editable)
{
super("");
this.editable = editable;
this.setBorderPainted(false);
this.setMargin(new Insets(0,0,0,0));
ActionListener okListener = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
mostrarVentana();
}
};
this.addActionListener(okListener);
}

public Component getTableCellEditorComponent(JTable tabla, Object valor, boolean isSelected, int fila, int columna)
{
this.setBackground(tabla.getBackground());
fechaActual = (Fecha) valor;
this.setText(fechaActual.getFecha());

return this;
}

public Object getCellEditorValue()
{
return fechaActual;
}

public boolean isCellEditable(EventObject e)
{
return editable;
}

public boolean shouldSelectCell(EventObject e)
{
return true; //La celda que está siendo editada debe estar seleccionada
}

public boolean stopCellEditing()
{
return edicionFinalizada;
}

public void cancelCellEditing()
{}

public void addCellEditorListener(CellEditorListener cel)
{}

public void removeCellEditorListener(CellEditorListener cel)
{}

public void setCellEditable(boolean editable)
{
this.editable = editable;
}

private void setEdicionFinalizada()
{
edicionFinalizada = true;
}

private void establecerFecha(String fecha)
{
fechaActual = new Fecha(fecha);
this.setText(fecha);
}

private void mostrarVentana()
{
edicionFinalizada = false;
final Calendario calendario = new Calendario();
final JFrame ventana = new JFrame("Seleccione una fecha");
JPanel botonera = new JPanel();
JButton aceptarB = new JButton("Aceptar");
JButton cancelarB = new JButton("Cancelar");
JLabel espacio = new JLabel("");

ActionListener aceptarListener = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
establecerFecha(calendario.getFecha());
setEdicionFinalizada();
ventana.dispose();
}
};
aceptarB.addActionListener(aceptarListener);

ActionListener cancelarListener = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
setEdicionFinalizada();
ventana.dispose();
}
};
cancelarB.addActionListener(cancelarListener);

espacio.setPreferredSize(new Dimension(80, 0));

botonera.add(cancelarB, null);
botonera.add(espacio, null);
botonera.add(aceptarB, null);

ventana.getContentPane().setLayout(new BorderLayout());
ventana.getContentPane().add(calendario, BorderLayout.CENTER);
ventana.getContentPane().add(botonera, BorderLayout.SOUTH);
ventana.setSize(400, 200);
ventana.setVisible(true);
}
} [/CODE]

Render:
[CODE]
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class RenderFecha extends DefaultTableCellRenderer implements TableCellRenderer
{
public RenderFecha()
{
super();
}

public Component getTableCellRendererComponent(JTable tabla, Object valor, boolean isSelected, boolean hasFocus, int fila, int columna)
{
Color amarillo = new Color(255, 255, 185);
if (valor != null)
this.setText(((Fecha)valor).getFecha());
else
this.setText("");
setHorizontalAlignment(CENTER);
setOpaque(true);
if (isSelected || hasFocus)
this.setBackground(amarillo);
else
this.setBackground(SystemColor.control);

return this;
}
}
[/CODE]

Muchas gracias por adelantado.

Saludos

chuidiang
05 de Febrero del 2004
Cuando en un JTable se edita algo, el funcionamiento interno es más o menos este:

- El JTable detecta que se quiere editar una celda
- El JTable pasa al editor el valor de la celda y lo muestra en pantalla en su sitio.
- El JTable se suscribe al editor para enterarse cuando se ha finalizado la edicion (bien poque se termina de editar, bien porque se cancela la edicion)
- El JTable le pide al Editor el nuevo valor y lo pone en el modelo

Para que tu editor funcione, debes implementar los metodos de añadir CellEditorListener y avisar a los sucriptores cuando se termine la edicion.

En www.geocities.com/chuidiang dentro de java tienes un ejemplo de implementación de un editor de estos, por si te sirve de algo.

Se bueno.