JTable Cómo actualizar el modelo de la tabla después de insertar, eliminar o actualizar los datos.

89

Esta es mi jTable

private JTable getJTable() {
    String[] colName = { "Name", "Email", "Contact No. 1", "Contact No. 2",
            "Group", "" };
    if (jTable == null) {
        jTable = new JTable() {
            public boolean isCellEditable(int nRow, int nCol) {
                return false;
            }
        };
    }
    DefaultTableModel contactTableModel = (DefaultTableModel) jTable
            .getModel();
    contactTableModel.setColumnIdentifiers(colName);
    jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    return jTable;
}

Llamaré a este método para recuperar los datos de la base de datos y ponerlos en el modelo de tabla

public void setUpTableData() {
    DefaultTableModel tableModel = (DefaultTableModel) jTable.getModel();
    ArrayList<Contact> list = new ArrayList<Contact>();
    if (!con.equals(""))
        list = sql.getContactListsByGroup(con);
    else
        list = sql.getContactLists();
    for (int i = 0; i < list.size(); i++) {
        String[] data = new String[7];

            data[0] = list.get(i).getName();
            data[1] = list.get(i).getEmail();
            data[2] = list.get(i).getPhone1();
            data[3] = list.get(i).getPhone2();
            data[4] = list.get(i).getGroup();
            data[5] = list.get(i).getId();

        tableModel.addRow(data);
    }
    jTable.setModel(tableModel);
}

Actualmente estaba usando este método para actualizar la tabla después de actualizar los datos de la tabla. Primero limpiaré la mesa

DefaultTableModel tableModel = (DefaultTableModel) jTable.getModel();
tableModel.setRowCount(0);

y luego reestructurar el modelo de tabla nuevamente para que actualice la tabla jTable. Pero estaba pensando, ¿existen mejores prácticas o una mejor manera de hacerlo?

user236501
fuente

Respuestas:

119

Si desea notificarle JTablesobre cambios en sus datos, utilice
tableModel.fireTableDataChanged()

De la documentación :

Notifica a todos los oyentes que pueden haber cambiado todos los valores de celda en las filas de la tabla. El número de filas también puede haber cambiado y JTable debería volver a dibujar la tabla desde cero. Se supone que la estructura de la tabla (como en el orden de las columnas) es la misma.

Peter Lang
fuente
¿Quieres decir que llamo a este tableModel.fireTableDataChanged () cada vez que hago una actualización?
user236501
3
@ newbie123: si solo inserta nuevas líneas, puede usar fireTableRowsInserted en su lugar. Por otro lado, la implementación de DefaultTableModel.addRowya debería manejar eso ... ¿No es tu tabla actualizada por addRow?
Peter Lang
4
Use setValueAt, DefaultTableModeldispara el evento.
Peter Lang
18
Sin embargo, se debe tener en cuenta que la llamada debe realizarse en formato fundido javax.swing.table.AbstractTableModel, ya que la interfaz TableModelno tiene el método mencionado anteriormente
Milan Aleksić
@PeterLang vea mi pregunta, por favor: stackoverflow.com/questions/18282753/…
Sajad
20

La forma más rápida para su caso es:

    jTable.repaint(); // Repaint all the component (all Cells).

La forma optimizada cuando una o pocas celdas cambian:

    ((AbstractTableModel) jTable.getModel()).fireTableCellUpdated(x, 0); // Repaint one cell.
Daniel De León
fuente
1
De hecho, encontré que jTable.invalidate () fue el método que realmente forzó un redibujo.
Kevin Qiu
Correcto, pero el método de validación es parte del proceso de diseño y también afecta a los padres del contenedor. Entonces, si necesita rehacer el diseño, úselo. docs.oracle.com/javase/7/docs/api/java/awt/…
Daniel De León
7

prueba esto

public void setUpTableData() {
    DefaultTableModel tableModel = (DefaultTableModel) jTable.getModel();

    /**
    * additional code.
    **/
    tableModel.setRowCount(0);
    /**/
    ArrayList<Contact> list = new ArrayList<Contact>();
    if (!con.equals(""))
        list = sql.getContactListsByGroup(con);
    else
        list = sql.getContactLists();
    for (int i = 0; i < list.size(); i++) {
        String[] data = new String[7];

        data[0] = list.get(i).getName();
        data[1] = list.get(i).getEmail();
        data[2] = list.get(i).getPhone1();
        data[3] = list.get(i).getPhone2();
        data[4] = list.get(i).getGroup();
        data[5] = list.get(i).getId();

        tableModel.addRow(data);
    }
    jTable.setModel(tableModel);
    /**
    * additional code.
    **/
    tableModel.fireTableDataChanged();
    /**/
}
Achille
fuente
2
No necesita jTable.setModel (tableModel) al final, ya que ya tiene el modelo de la tabla al principio.
David George
2
DefaultTableModel dm = (DefaultTableModel)table.getModel();
dm.fireTableDataChanged(); // notifies the JTable that the model has changed
Sumit Singh
fuente
3
no, no ... DefaultTableModel ha implementado este evento, y lo implementó correctamente ...
mKorbel
1

¿No sería mejor usarlo java.util.Observabley java.util.Observereso hará que la tabla se actualice?

tom
fuente
6
no, seguro que no, no hagas eso, ¿por qué simuló la opción incorporada de JTable y salió de EDT?
mKorbel
-4

Lo hice así en mi Jtable, se actualiza automáticamente después de 300 ms;

DefaultTableModel tableModel = new DefaultTableModel(){
public boolean isCellEditable(int nRow, int nCol) {
                return false;
            }
};
JTable table = new JTable();

Timer t = new Timer(300, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                addColumns();
                remakeData(set);
                table.setModel(model);
            }
        });
        t.start();

private void addColumns() {
        model.setColumnCount(0);
        model.addColumn("NAME");
            model.addColumn("EMAIL");} 

 private void remakeData(CollectionType< Objects > name) {
    model.setRowCount(0);
    for (CollectionType Objects : name){
    String n = Object.getName();
    String e = Object.getEmail();
    model.insertRow(model.getRowCount(),new Object[] { n,e });
    }}

Dudo que funcione bien con una gran cantidad de objetos como más de 500, la única forma es implementar TableModelListener en su clase, pero no entendí cómo usarlo bien. mira http://download.oracle.com/javase/tutorial/uiswing/components/table.html#modelchange

nkvnkv
fuente