JTable 採用「視圖-模型分離」架構:JTable 負責渲染與互動,TableModel 負責資料存取與變更通知。本文以 Table.java 範例完整解析核心 API 與擴充技巧。
JTable (View) ◄──► TableModel (Data)
▲ ▲
│ │
TableColumnModel AbstractTableModel
(欄位寬度/排序) (資料儲存/事件發送)
class DataModel extends AbstractTableModel {
// 1. 資料儲存 (二維陣列、List、資料庫 ResultSet 皆可)
Object[][] data = {
{"one", "two", "three", "four"},
{"five", "six", "seven", "eight"},
{"nine", "ten", "eleven", "twelve"}
};
// 2. 監聽器:資料變更時列印完整表格 (示範用)
class TableModelListenerImpl implements TableModelListener {
public void tableChanged(TableModelEvent e) {
for (Object[] row : data) {
for (Object cell : row) System.out.print(cell + " ");
System.out.println();
}
}
}
{ addTableModelListener(new TableModelListenerImpl()); } // 實例初始化區塊
// 3. 必須實作的三個核心方法
public int getRowCount() { return data.length; }
public int getColumnCount() { return data[0].length; }
public Object getValueAt(int r, int c) { return data[r][c]; }
// 4. 可編輯支援:覆寫預設唯讀行為
public boolean isCellEditable(int r, int c) { return true; }
public void setValueAt(Object val, int r, int c) {
data[r][c] = val;
fireTableDataChanged(); // 關鍵:通知 JTable 重繪
}
}
public class Table extends JPanel {
public Table() {
setLayout(new BorderLayout());
JTable table = new JTable(new DataModel());
// 必須用 JTable.createScrollPaneForTable() 或 new JScrollPane(table)
// 以正確顯示表頭 (TableHeader)
JScrollPane scroll = new JScrollPane(table);
add(scroll, BorderLayout.CENTER);
}
}
| 需求 | 解決方案 | 關鍵方法/類別 |
|---|---|---|
| 欄位標題自訂 | 覆寫 getColumnName(int) | TableModel |
| 欄位類型控制渲染/編輯器 | 覆寫 getColumnClass(int) | TableModel → JTable 自動選擇渲染器 |
| 大量資料分頁/延遲載入 | 實作 getValueAt 內部查詢 DB | 配合 Pagination 或 VirtualTableModel |
| 儲存格級別驗證 | 自訂 TableCellEditor + InputVerifier | DefaultCellEditor 子類 |
| 排序/篩選 | RowSorter / TableRowSorter | table.setRowSorter(new TableRowSorter<>(model)) |
| 拖放重排欄列 | table.setDragEnabled(true) + TransferHandler | JTable 內建支援 |
| 匯出 Excel/CSV | 遍歷 Model 寫入 Apache POI / OpenCSV | 獨立工具類,不汙染 Model |
fireTableCellUpdated(r,c)、fireTableRowsInserted(first,last)、fireTableStructureChanged(),避免全表重繪。DefaultTableCellRenderer 為單例,getTableCellRendererComponent 每儲存格調用一次,切勿在內部建立新物件。getValueAt 即時計算/查詢,不在記憶體保留完整陣列。掌握 TableModel 介面契約,即可將任意資料來源 (資料庫、REST API、記憶體集合) 無縫接入 JTable,享受排序、篩選、編輯、列印等企業級功能。