95

This is my 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;
}

I will call this method to retrieve the data from database and put it into table model

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);
}

Currently I was using this method to refresh the table after updating the table data. I will first clear the table

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

and then restructure the table model again so it will refresh the jTable. But I was thinking is there any best practices or better way to do that?

J. Pinto
  • 19
  • 9
user236501
  • 8,538
  • 24
  • 85
  • 119
  • very old question without enough details to pin-point the exact reason of the problem (DefaultTableModel fires the notifications as needed, so the error is its usage, most probably) - still confusing current readers ;) – kleopatra May 24 '23 at 09:01

6 Answers6

132

If you want to notify your JTable about changes of your data, use
tableModel.fireTableDataChanged()

From the documentation:

Notifies all listeners that all cell values in the table's rows may have changed. The number of rows may also have changed and the JTable should redraw the table from scratch. The structure of the table (as in the order of the columns) is assumed to be the same.

RustyTheBoyRobot
  • 5,891
  • 4
  • 36
  • 55
Peter Lang
  • 54,264
  • 27
  • 148
  • 161
  • do you mean i call this tableModel.fireTableDataChanged() everytime when i doing updating ? – user236501 Jul 05 '10 at 11:57
  • 3
    @newbie123: If you only insert new lines, you can use [fireTableRowsInserted](http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/table/AbstractTableModel.html#fireTableRowsInserted%28int,%20int%29) instead. On the other hand, the implementation of `DefaultTableModel.addRow` should already handle that... Isn't your table refreshed by `addRow`? – Peter Lang Jul 05 '10 at 11:59
  • 4
    Use [`setValueAt`](http://java.sun.com/javase/6/docs/api/javax/swing/table/AbstractTableModel.html#setValueAt%28java.lang.Object,%20int,%20int%29), `DefaultTableModel` fires the event. – Peter Lang Jul 05 '10 at 12:40
  • 23
    One should notice though that the call must be made on casted `javax.swing.table.AbstractTableModel`, since interface `TableModel` does not have the method mentioned above – Milan Aleksić Feb 17 '12 at 10:47
  • technically correct - but a) not needed with DefaultTableModel (its modification methods will fire the appropriate notifications), b) conceptionally wrong to let client code fire the notifications - that's the inherent responsibility of the model. So there's someting wrong with the usage of the model, unfortunately not shown in the question – kleopatra May 24 '23 at 08:57
22

The faster way for your case is:

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

The optimized way when one or few cell change:

    ((AbstractTableModel) jTable.getModel()).fireTableCellUpdated(x, 0); // Repaint one cell.
Daniel De León
  • 13,196
  • 5
  • 87
  • 72
  • 1
    I actually found that jTable.invalidate() was the method that actually forced a redraw. – Kevin Qiu Jun 06 '13 at 18:36
  • Right, but the validate method is part of the layout process, and impacts the parents of the container too. So if you need the redo the layout, use it. http://docs.oracle.com/javase/7/docs/api/java/awt/Container.html#invalidate() – Daniel De León Jun 07 '13 at 01:23
8

try this

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();
    /**/
}
Alexey
  • 714
  • 8
  • 21
Achille
  • 97
  • 1
  • 1
1

Would it not be better to use java.util.Observable and java.util.Observer that will cause the table to update?

tom
  • 11
  • 1
0
To inform the Jtable about data change do this - 

DefaultTableModel tableModel = new DefaultTableModel(yourData, yourColumns);
//Set data and columns in tableModel to JTable
JTable yourTable= new JTable(model);

//After data Changed fire change detector
tableModel.fireTableDataChanged();
-4

I did it like this in my Jtable its autorefreshing after 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 });
    }}

I doubt it will do good with large number of objects like over 500, only other way is to implement TableModelListener in your class, but i did not understand how to use it well. look at http://download.oracle.com/javase/tutorial/uiswing/components/table.html#modelchange

nkvnkv
  • 914
  • 2
  • 12
  • 25