You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据JTable数据宽度调整JScrollPane的显示宽度?

JTable列宽适配与滚动条优化方案

问题背景

将JTable嵌入JScrollPane后,已设置setAutoResizeMode(JTable.AUTO_RESIZE_OFF),通过resizeColumnWidth方法适配列宽,水平滚动条策略设为AS_NEEDED。但当单元格包含超宽数据时,希望表格总宽度恰好等于所有列宽总和,JScrollPane自动显示水平滚动条,且无多余空白区域。原代码存在偶尔失效的问题,需优化。

原代码(问题版本)

public static void resizeColumnWidth(JTable table) 
{
    final TableColumnModel columnModel = table.getColumnModel();
    
    int iCumulativeWidth = 0;
            
    // 关闭自动列宽调整
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    
    // 填充视口空白高度
    table.setFillsViewportHeight(true);
    
    // 遍历处理每一列
    for (int iColumnIndex = 0; iColumnIndex < table.getColumnCount(); iColumnIndex++) 
    {
        // 设置默认最小列宽
        int iColumnWidth = 15; 

        // 获取表头所需宽度
        TableColumn tableColumn = table.getTableHeader().getColumnModel().getColumn(iColumnIndex);
        TableCellRenderer renderer1 = tableColumn.getHeaderRenderer();
        if (renderer1 == null) 
        {
            renderer1 = table.getTableHeader().getDefaultRenderer();
        }
        Component component = renderer1.getTableCellRendererComponent(table, tableColumn.getHeaderValue(), false, false, -1, iColumnIndex);
        iColumnWidth = Math.max(component.getPreferredSize().width, iColumnWidth);
  
        // 计算单元格内容所需宽度
        for (int iRowIndex = 0; iRowIndex < table.getRowCount(); iRowIndex++) 
        {                
            TableCellRenderer renderer2 = table.getCellRenderer(iRowIndex, iColumnIndex);
            Component comp = table.prepareRenderer(renderer2, iRowIndex, iColumnIndex);
            iColumnWidth = Math.max(comp.getPreferredSize().width + 1, iColumnWidth);
        }
        
        // 处理最后一列,强制填充视口剩余宽度
        if (iColumnIndex >= columnModel.getColumnCount() - 1) 
        { 
            int iScrollWidth = table.getPreferredScrollableViewportSize().width;
            int iRemainingWidth = iScrollWidth - iCumulativeWidth;
            
            if (iRemainingWidth > iColumnWidth)
            {
                iColumnWidth = iRemainingWidth;
            }
        }

        // 设置列的首选宽度
        columnModel.getColumn(iColumnIndex).setPreferredWidth(iColumnWidth);
        
        // 累加总列宽
        iCumulativeWidth += iColumnWidth;
     }

     // 设置表格首选宽度为累加的总列宽
     table.setPreferredSize(new Dimension(iCumulativeWidth, table.getPreferredScrollableViewportSize().height));
}

优化后的代码

public static void resizeColumnWidth(JTable table) {
    final TableColumnModel columnModel = table.getColumnModel();
    int totalWidth = 0;

    // 关闭自动列宽调整
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    // 填充视口空白高度
    table.setFillsViewportHeight(true);

    // 遍历每一列计算适配宽度
    for (int colIdx = 0; colIdx < table.getColumnCount(); colIdx++) {
        int colWidth = 15; // 设置默认最小列宽

        // 计算表头所需宽度
        TableColumn tableColumn = columnModel.getColumn(colIdx);
        TableCellRenderer headerRenderer = tableColumn.getHeaderRenderer();
        if (headerRenderer == null) {
            headerRenderer = table.getTableHeader().getDefaultRenderer();
        }
        Component headerComp = headerRenderer.getTableCellRendererComponent(
                table, tableColumn.getHeaderValue(), false, false, -1, colIdx);
        colWidth = Math.max(headerComp.getPreferredSize().width, colWidth);

        // 计算单元格内容所需宽度
        for (int rowIdx = 0; rowIdx < table.getRowCount(); rowIdx++) {
            TableCellRenderer cellRenderer = table.getCellRenderer(rowIdx, colIdx);
            Component cellComp = table.prepareRenderer(cellRenderer, rowIdx, colIdx);
            colWidth = Math.max(cellComp.getPreferredSize().width + 1, colWidth);
        }

        // 设置列的首选宽度
        tableColumn.setPreferredWidth(colWidth);
        totalWidth += colWidth;
    }

    // 设置表格首选宽度为所有列宽总和,高度保留视口首选高度
    table.setPreferredSize(new Dimension(totalWidth, table.getPreferredScrollableViewportSize().height));
    // 允许表格宽度不受限,确保超过视口时触发滚动条
    table.setMaximumSize(new Dimension(Integer.MAX_VALUE, table.getMaximumSize().height));
}

关键优化点

  • 移除最后一列强制填充逻辑:原代码中最后一列会强制填充视口剩余宽度,导致表格总宽度被锁死在视口宽度内,无法触发水平滚动。优化后每列严格按内容适配,总宽度由所有列宽累加得出。
  • 放开表格宽度限制:通过设置表格最大宽度为Integer.MAX_VALUE,确保表格可以根据实际列宽自由扩展,不会被视口宽度约束。
  • 简化变量命名:调整变量名提升代码可读性,不影响功能逻辑。

内容的提问来源于stack exchange,提问作者Rob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 12:52:46