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));
}
Override the
getPreferredSize()method of your JTable. Maybe something like: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.