lunes, 22 de noviembre de 2010

Como incrustar un JDateChooser o un JButton en un JTable

El problema:

Se quiere presentar una tabla (un JTable) que detro tenga un JButton y al lado de el un JDateChooser.

Pasos pra resolver el problema:


1. Crear una implementación de la interfaz TableCellRenderer para mostrar algunas celdas como botones o como Calendarios.

2. Crear una implementación de la interfaz TableCellEditor para que la celda funcione  como boton o como calendario.

3. Crear un modelo que extienda de DefaultTableModel para mostrar los datos de la tabla

La forma de implementar:

Primero implementamos el modelo:


package prueba;
// si no tienes el jar de este componenete quita el import
import com.toedter.calendar.JDateChooser;
import javax.swing.JButton;
import javax.swing.table.DefaultTableModel;

/**
*
* @author gatsu
*/
public class MiModelo extends DefaultTableModel
{

/**
* Este metodo indica que clase esta en que celda. Es importantisimo.
*/
@Override
public Class getColumnClass(int columnIndex)
{
if( columnIndex == 0)
{
return JButton.class;
}
else
{
// si no tienes el jar del JDateChooser solo regresa el JButton.class
return JDateChooser.class;
}
}


@Override
public int getColumnCount()
{
// la tabla solo tiene 2 columnas
return 2;
}

@Override
public int getRowCount()
{
// la tabla solo tiene una fila
return 1;
}




@Override
public Object getValueAt(int row, int column)
{
if( column == 0 )
{
// en la primera columna el elemento es un boton
return new JButton("hola");
}
// en la otra columna el elemento es un calendario (si no esta el jar solo hay que poner el return del boton sin ningun if).
return new JDateChooser();
}


}

Ahora para el render basta con decir que pinte el componente que tiene el modelo.





/*
* @author gatsu
*/
package mx.gob.cnpss.sisenom.view.agenda.table;

import java.awt.Component;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import org.apache.log4j.Logger;


public class MiRender implements TableCellRenderer {



// Este metodo indica como debe de pintarse el elemento en la fila row, en la columna column
// que esta en la tabla table y tiene el color dado por el objeto.
@Override
public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) {

// como el boton y el calendario son componentes esto se vale.
return (JComponent) table.getValueAt(row, column);
}
}

Finalmente se crea el editor, al igual que con el render en el editor indicaremos que debe usarse el editor del propio componente.







package mx.gob.cnpss.sisenom.view.agenda.table;

import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import org.apache.log4j.Logger;

/**
* @author gatsu
*/
public class MiEditor extends AbstractCellEditor implements TableCellEditor {


private Boolean currentValue;

@Override
public Object getCellEditorValue()
{
return currentValue;
}

//El editor usara el propio componente. Para que funcione la celda en el modelo debe ser editable.
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{


return (JComponent) value;// la tabla solo debe tener componentes graficos

}
}



Finalmente, hay que asignar el modelo, el render y el editor al JTable deseado.

JTable tablita = new JTable();
tablita.setModel( new MiModelo());

// solo las celdas con botones se pintaran y usaran como botones.
tablita.setDefaultRender( JButton.class, new MiRender());
tablita.setDefaultEditor( JButton.class, new MiEditor());

Si se desea que las celdas con JDateChosser también trabajen igual se agregaran las siguientes lineas:

tablita.setDefaultRender( JDateChooser.class, new MiRender());
tablita.setDefaultEditor( JDateChooser.class, new MiEditor());










7 comentarios:

  1. Funciona perfecto!, solo tengo una duda... En esa misma tabla, ¿como hago para dejar ciertas columnas para que no se inserte nada en ellas?. Tengo claro como introducir en algunas columnas el DataChooser, Checkboxes,... pero para dejas las celdas sin introducir nada y que sean funcionales...

    ResponderEliminar
    Respuestas
    1. Amigo necesito tu ayuda para introducir un jDateChooser en una celda del jTable, ya que todo lo hago en modo grafico, el me genera el codigo su clase que extiende de FrameView.. y veo este codigo y no consigo como acoplarlo al mio! espero tu respuesta!

      Eliminar
    2. tengo un problema este es mi post:

      http://www.forosdelweb.com/f45/poner-jbutton-jtable-1119960/

      Eliminar
  2. Si no quieres que se inserte nada en ciertas columnas en el TableModel debes sobreescribir el metodo isCellEditable() ese metodo indica si una determinada celda puede ser descrita. Basta con poner una condición en base a la columna de la celda.

    Con eso deberia de bastarte.

    ResponderEliminar
  3. Una mejor forma de hacerlo, especificando la columna en la que se quiere el boton o cualquier componente, solo hay que crear su propio CellEditor
    public IngeniosCellEditor(final JDateChooser datechooser) {
    editorComponent = datechooser;
    Boolean currentValue;
    formatofecha=new SimpleDateFormat("dd/MM/yyyy");

    delegate = new EditorDelegate() {
    public Object getCellEditorValue(){
    return formatofecha.format(datechooser.getDate());
    }

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column){
    return (JComponent) value;// la tabla solo debe tener componentes graficos
    }
    };
    //datechooser.addActionListener(delegate);
    }

    y para que te funcione crea una funcion en tu forma asi:

    public void setUpJDateChooserColumn(JTable table, TableColumn Columna) {
    //Set up the editor for the sport cells.
    jfechachosser = new JDateChooser();
    //comboBox.addItem("ACTIVO");
    //comboBox.addItem("INACTIVO");
    Columna.setCellEditor(new IngeniosCellEditor(jfechachosser));

    //Set up tool tips for the sport cells.
    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
    renderer.setToolTipText("Seleccione un Estado");
    Columna.setCellRenderer(renderer);
    }


    y cuando inicies tus componentes escribe esto:

    setUpJDateChooserColumn(jTable1, jTable1.getColumnModel().getColumn(1));

    el numero 1 es la columna en la que quieres que aparezca el objeto...

    ResponderEliminar
  4. Al seleccionar una fecha con JDateChooser porque se pierde ésta al seleccionar otra celda... Gracias de antemano.

    ResponderEliminar
  5. No te has dado cuenta que los valores desaparecen al salir de la edicion?

    ResponderEliminar