刷新包含JPanel的JTable

时间:2015-04-12 15:35:41

标签: java swing jtable

我有一个JTable,其中包含渲染JPanel的单元格。问题是每次我更新模型时,JTable都不会触发。我目前的代码如下。我尝试了不同的东西,如table.validate()和table.repaint(),但仍然不刷新表。

我尝试通过执行table.setModel(newModel)来更改表的模型,但这完全消除了表(包括取消选择)。我希望该表在后台静默更新。

刷新代码在我的其他默认呈现的JTable上运行良好,但这不适用于这个特定的。

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

已编辑:上述问题的解决方案

正如@JB Nizet所建议的

1。)将setFeed()添加到DefaultTableModel

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

2.)刷新模型的Feed并解除事件

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

1 个答案:

答案 0 :(得分:2)

首先使用此模型创建模型和表格:

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

但是当你想刷新表时,不是更新这个模型并让模型触发一个事件,以便表重新读取模型并更新其视图,你创建另一个不同的模型,然后你创建这个新模型开火活动:

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

                newModel --contains--> newData

但该表仍然使用以前的型号,因此没有收到任何事件。即使它确实如此,它仍然会重新读取它使用的模型的数据,而不是你创建的新模型。

您必须创建单个模型,更新它(即更改其Feed),然后从此模型中激发相应的事件。