mfrancisp
mfrancisp

Reputation: 119

Refreshing a JTable that contains JPanel

I have a JTable with cells that render a JPanel. The problem is that everytime I update the model, the JTable doesn't fire. My current code is below. I tried different things such as table.validate() and table.repaint() but still doesn't refresh the table.

I tried to change the table's model by doing table.setModel(newModel) but this completely wipes off the table (including the deselecting). I would prefer the table to update silently in the background.

The refresh code works very well on my other default rendered JTable but this doesn't work on this particular one.

public class RoomViewTable2 {
    JScrollPane hostPane;
    public static JTable table;
    public static DefaultTableModel model;
    private static Timer refreshTimer;

public RoomViewTable2() {

}

public static JTable getRoomViewTable() {
    model = new RoomRowTableModel(getFeeds());
    table = new JTable(model);
    table.setDefaultRenderer(TablePanelUI.class, new RoomRowCellRenderer());
    table.setRowHeight(75);

    runRefreshTimer();

    return table;
}

public static ArrayList<TablePanelUI> getFeeds() {
    ArrayList<TablePanelUI> feeds = new ArrayList<TablePanelUI>();
    try {
        DB.dbConnect();
        String sql = "SELECT id, folio_id from room_view WHERE validity = '1'";
        ResultSet rs = DB.con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE
                , ResultSet.CONCUR_READ_ONLY)
                .executeQuery(sql);

        while (rs.next()) {
            feeds.add(new TablePanelUI(new RoomInfo(rs.getInt(1))
                , new FolioInfo(rs.getInt(2))));
        }
        rs.close();
        DB.con.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return feeds;
}

public static class RoomRowCellRenderer implements TableCellRenderer{
      public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {

        TablePanelUI room = (TablePanelUI) value;

        JPanel panel = room.getPanel();

        if (isSelected) {
          panel.setBackground(table.getSelectionBackground());
        }else{
          panel.setBackground(table.getBackground());
        }

        return panel;
      }
}

public static void refreshRoomView() {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            model = new RoomRowTableModel(getFeeds());
            model.fireTableDataChanged();
            table.updateUI();   
        }
    });

}

public static void runRefreshTimer() {
    refreshTimer = new Timer(10000, new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            refreshRoomView();
            System.out.println("UPDATING");
        }
    });
    refreshTimer.start();
}

public static class RoomRowTableModel extends DefaultTableModel {
    ArrayList<TablePanelUI> feeds;

    public RoomRowTableModel(ArrayList<TablePanelUI> feeds) {
        this.feeds = feeds;
    }

    public Class getColumnClass(int columnIndex) { 
        return TablePanelUI.class; 
    }

    public int getColumnCount() { 
        return 1; 
    }

    public String getColumnName(int columnIndex) { 
        return "Feed"; 
    }

    public int getRowCount() { 
        return (feeds == null) ? 0 : feeds.size(); 
    }

    public Object getValueAt(int rowIndex, int columnIndex) { 
        return (feeds == null) ? null : feeds.get(rowIndex); 
    }

    public boolean isCellEditable(int columnIndex, int rowIndex) { 
        return true; 
    }
}

EDITED: Solution to the problem above

As suggested by @JB Nizet

1.) Added setFeed() to the DefaultTableModel

    public void setFeed(ArrayList<TablePanelUI> feeds) {
        this.feeds = feeds;
    }

2.) Refreshed the model's feed and fired the event

int selectedRow = table.getSelectedRow();
model.setFeed(getFeeds());
model.fireTableDataChanged();
table.updateUI();
if (selectedRow >= 0) {
    table.setRowSelectionInterval(0, selectedRow);  
}

Upvotes: 0

Views: 288

Answers (1)

JB Nizet
JB Nizet

Reputation: 691715

You start by creating a model, and a table using this model:

table --uses--> model --contains--> data 

But when you want to refresh the table, instead of updating this model and make the model fire an event so that the table re-reads the model and updates its view, you create another different model, and you make this new model fire an event:

table --uses--> model --contains--> data 

                newModel --contains--> newData

But the table still uses the previous model, and thus doesn't receive any event. And even if it did, it would still re-read the data frm the model it uses, not from the new model you created.

You must create a single model, update it (i.e. change its feeds), and fire the appropriate events from this model.

Upvotes: 2

Related Questions