首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

JTable 列寬自適應內容完整實作方案

     編輯:Java 程式設計入門

JTable 預設平均分配列寬,導致長內容被截斷或短欄位浪費空間。本文提供一個開箱即用的 FitTableColumns 方法,根據表頭與所有行數據的實際渲染寬度動態調整列寬,支援任意 TableModel 與自定義 Renderer。

核心實作代碼


import javax.swing.*;
import javax.swing.table.*;
import java.util.Enumeration;

/**
 * 根據內容自適應調整 JTable 列寬
 * @param myTable 目標 JTable 實例
 */
public void FitTableColumns(JTable myTable) {
    JTableHeader header = myTable.getTableHeader();
    int rowCount = myTable.getRowCount();

    // 遍歷所有列
    Enumeration<TableColumn> columns = myTable.getColumnModel().getColumns();
    while (columns.hasMoreElements()) {
        TableColumn column = columns.nextElement();
        int col = header.getColumnModel().getColumnIndex(column.getIdentifier());

        // 1. 計算表頭渲染寬度
        int width = (int) myTable.getTableHeader().getDefaultRenderer()
                .getTableCellRendererComponent(myTable, column.getIdentifier(), false, false, -1, col)
                .getPreferredSize().getWidth();

        // 2. 遍歷所有行,計算內容渲染寬度,取最大值
        for (int row = 0; row < rowCount; row++) {
            int preferedWidth = (int) myTable.getCellRenderer(row, col)
                    .getTableCellRendererComponent(myTable,
                            myTable.getValueAt(row, col), false, false, row, col)
                    .getPreferredSize().getWidth();
            width = Math.max(width, preferedWidth);
        }

        // 3. 關鍵步驟:通知表頭正在調整該列(避免渲染異常)
        header.setResizingColumn(column);

        // 4. 設定列寬(加上單元格間距避免緊貼邊框)
        column.setWidth(width + myTable.getIntercellSpacing().width);
    }
}

使用方式


// 資料載入完成後呼叫
FitTableColumns(yourTableName);

// 若資料動態更新,需在 model 變更後重新呼叫
tableModel.addTableModelListener(e -> FitTableColumns(table));

關鍵技術點解析

  1. 渲染器委派測量:透過 getTableCellRendererComponent 獲取真實渲染組件,再取 getPreferredSize(),確保自定義 Renderer(如多行文字、圖標、進度條)寬度準確。
  2. 表頭與內容同步測量:先測表頭,再遍歷所有行取最大值,保證表頭不被截斷。
  3. header.setResizingColumn(column) 必不可少:通知 TableHeader 進入調整狀態,防止調整過程中渲染異常或拋出異常。
  4. 單元格間距補償:getIntercellSpacing().width 避免內容貼邊。

效能優化建議

  • 大數據量分頁測量:行數 > 1000 時,僅抽樣測量(如每 10 行)或限制前 200 行。
  • 異步執行:SwingUtilities.invokeLater 包裝,避免阻塞 EDT 導致介面卡頓。
  • 快取列寬:相同數據結構可快取計算結果,避免重複計算。
  • 設定最大/最小寬度:column.setMaxWidth(500); column.setMinWidth(50); 防止極端寬度破壞版面。

常見問題排查

現象原因解決
列寬調整後立即恢復自動調整模式開啟table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF)
自定義 Renderer 寬度不準Renderer 未正確實作 getPreferredSize確保 Renderer 繼承 JLabel/JComponent 並正確佈局
調整時拋出 ArrayIndexOutOfBoundsException欄位索引與模型索引不一致使用 convertColumnIndexToModel/view 轉換
隱藏列仍被測量遍歷包含隱藏列檢查 column.getWidth() > 0 或 isVisible()

進階:支援列隱藏與用戶手動調整記憶


public class SmartColumnFitter {
    private final Map<Integer, Integer> userPreferredWidths = new HashMap<>();

    public void fit(JTable table) {
        TableColumnModel model = table.getColumnModel();
        for (int i = 0; i < model.getColumnCount(); i++) {
            TableColumn col = model.getColumn(i);
            if (col.getWidth() == 0) continue; // 跳過隱藏列

            int width = calculatePreferredWidth(table, i);
            // 尊重用戶手動調整的寬度(若大於計算值)
            width = Math.max(width, userPreferredWidths.getOrDefault(i, width));
            col.setWidth(width);
        }
    }

    // 監聽用戶拖曳調整
    public void installColumnResizeListener(JTable table) {
        table.getTableHeader().addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                TableColumnModel cm = table.getColumnModel();
                for (int i = 0; i < cm.getColumnCount(); i++) {
                    userPreferredWidths.put(i, cm.getColumn(i).getWidth());
                }
            }
        });
    }
}

總結

FitTableColumns 以渲染器為基準測量真實寬度,解決了 JTable 預設均分列寬的痛點。結合效能優化與用戶偏好記憶,可構建專業級的表格展示體驗。記住在資料載入完成、模型變更、視窗大小改變等時機適時呼叫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved