How to refresh data in JTable I am using TableModel

You’ve done it the hard way.

First of all, you’ve implemented directly from TableModel and secondly you’ve failed to implement the listener requirements…

Instead, try extending from the AbstractTableModel instead, which already includes the implementations of the listener registration and notification.

You will need to provide a method that will allow you to add a row to the table model. In this method you need to use the fireTableRowsInserted method which will notify any tables using the model, that a new row has been added…

Update with example

This is VERY, VERY basic example. It’s only intention is to demonstrate the use of fireTableRowsInserted. It uses a Swing Timer to add a new row every 125 milliseconds until you kill it 😉

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;

public class DynamicTable {

    public static void main(String[] args) {
        new DynamicTable();
    }

    public DynamicTable() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
                
                final MyTableModel model = new MyTableModel();
                JTable table = new JTable(model);
                
                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                
                Timer timer = new Timer(125, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        model.addRow();
                    }
                });
                timer.start();
            }
        });
    }
    
    public class MyTableModel extends AbstractTableModel {

        private List<String[]> rows;

        public MyTableModel() {
            rows = new ArrayList<>(25);
        }
        
        @Override
        public int getRowCount() {
            return rows.size();
        }

        @Override
        public int getColumnCount() {
            return 4;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            String[] row = rows.get(rowIndex);
            return row[columnIndex];
        }
        
        public void addRow() {
            int rowCount = getRowCount();
            String[] row = new String[getColumnCount()];
            for (int index = 0; index < getColumnCount(); index++) {
                row[index] = rowCount + "x" + index;
            }
            rows.add(row);
            fireTableRowsInserted(rowCount, rowCount);
        }            
    }                    
}

Updated with another example

Because your table model is backed by its own List, it has no connection to your factory. It doesn’t know when you add or remove objects from it. This means you become responsible for updating the model:

public class MyTableModel extends AbstractTableModel {

    private List<Staff> staffs;

    public MyTableModel(List<Staff> staffs){
        this.staffs = staffs;
    }

    @Override
    public int getRowCount() {
        return staffs.size();
    }

    @Override
    public int getColumnCount() {
        return 5;
    }
    
    public void add(Staff staff) {
        int size = getSize();
        staffs.add(staff);
        fireTableRowsInserted(size, size);
    }

    public void remove(Staff staff) {
        if (staffs.contains(staff) {
            int index = stafff.indexOf(staff);
            staffs.remove(staff);
            fireTableRowsDeleted(index, index);
        }
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Staff staff = staffs.get(rowIndex);
        switch (columnIndex){
            case 0:
                return staff.getName();
            case 1:
                return staff.getSurname();
            case 2:
                return staff.getDate();
            case 3:
                return staff.getPosition();
            case 4:
                return staff.getSalary();
        }
        return "";
    }
}

And your actionPerformed:

@Override
public void actionPerformed(ActionEvent e) {
    Staff staff = new Staff();
    staff.setName(JOptionPane.showInputDialog("Enter First Name"));
    staff.setSurname(JOptionPane.showInputDialog("Enter Second Name"));
    staff.setDate(JOptionPane.showInputDialog("Enter Date"));
    staff.setPosition(JOptionPane.showInputDialog("Enter Position"));
    staff.setSalary(JOptionPane.showInputDialog("Enter Salary"));
    try {
        Factory.getInstance().getStaffDAO().addStaff(staff);
        ((MyTableModel)model).add(staff);
    } catch (SQLException e1) {
        e1.printStackTrace();  
    }
}

Leave a Comment