Reputation: 119
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
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