How do I adjust the width of a JScrollPane based on the width of JTable Data?

35 Views Asked by At

My Java program has a JTable in a JScrollPane. For the table I set setAutoResizeMode(JTable.AUTO_RESIZE_OFF) and I adjust the column widths to match the data using resizeColumnWidth (shown in many internet locations). I also set horizontal scroll bar policy to AS_NEEDED. This all works great.

Sometimes some table cells may have extra wide data that makes their columns extra wide. The overall table width of all the columns is then wider than the width of the view area of the JScrollPane. In this case I want the JScrollPane to display a horizontal scroll bar to allow the table to be wider than the pane. I want the table width to be exactly as wide as needed for all the columns. And I want the scroll bars to allow side scrolling as needed to view the entire width of the table.

I think there is a way to enhance my resizeColumnWidth to also make overall adjustments as needed based on all the widths.

How do I do this?

I tried making the JTable's preferred width extra-large. That kinda works, but then I have extra scroll space to the right of the table. I don't like that.

I'm already adjusting the column widths to match the cell data. What I also want, is to adjust the overall table width to match the total of all the column widths.

Below is my code as it stands. Sometimes it works and sometimes it doesn't.

    public static void resizeColumnWidth(JTable table) 
{
    final TableColumnModel columnModel = table.getColumnModel();
    
    int iCumulativeWidth = 0;
            
    // turn off automatic column sizing
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    
    // make sure the bottom of the viewport is filled with color (white)
    table.setFillsViewportHeight(true);
    
    // process each column
    for (int iColumnIndex = 0; iColumnIndex < table.getColumnCount(); iColumnIndex++) 
    {
        // set a default minimum column width
        int iColumnWidth = 15; 

        // get the width of the header
        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);
  
        // process the width of each row
        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);
        }
        
        // check if this is the last column
        if (iColumnIndex >= columnModel.getColumnCount() - 1) 
        { 
            // last column
            
            // calculate the width of the visible scroll area
            int iScrollWidth = table.getPreferredScrollableViewportSize().width;
            
            // calculate how wide the last column needs to be to consume all the remaining table width
            int iRemainingWidth = iScrollWidth - iCumulativeWidth;
            
            // check if the remaining width is larger than what the column normally would be
            if (iRemainingWidth > iColumnWidth)
            {
                // set the column to use the larger remaining width
                iColumnWidth = iRemainingWidth;
            }
        }

        // set the column's width
        columnModel.getColumn(iColumnIndex).setPreferredWidth(iColumnWidth);
        
        // maintain the total cumulative width of all columns
        iCumulativeWidth += iColumnWidth;
     }

     // adjust the width of the table to the width of the columns
     table.setPreferredSize(new Dimension(iCumulativeWidth, table.getPreferredScrollableViewportSize().height));
}
1

There are 1 best solutions below

0
camickr On

I tried making the JTable's preferred width extra-large

Override the getPreferredSize() method of your JTable. Maybe something like:

JTable table = new JTable(...)
{
    @Override
    public Dimension getPreferredSize()
    {
        Dimension d = super.getPreferredSize();

        if (d.width > 500) // pick a reasonable value for your table
            d.width = 500;

        return d;
    }
};

table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );

Now the width of your scroll pane should be a maximum of 500 but it can be smaller if the widths of all columns is smaller.

The scrollbar should then appear if the table width is greater than scroll pane size.