34

I need my JTable to automatically re-size its column widths to fit the content. I found the TableColumnAdjuster class very useful. But there's a small problem. Say i have 5 columns, and their content is very short. In that case, if i use the auto adjuster, it sets the first four columns widths according to their content and gives all the rest of space to the last column. Please see the example.

enter image description here

Here the last column, Balance is given all the excess space. But what if i need to give that space to one of the middle columns. In the above case, i need to assign that space to the third column, name. I tried modifying the TableColumnAdjuster class's adjustColumns() method. But I couldn't get it working.

I tried both column.setPreferredWidth() and column.setWidth() for changing column sizes. But seems it doesn't change anything. How can I effectively change the column sizes of a JTable. If there's some other alternative or a direct answer to my main problem, that's better. Thanks!

Anubis
  • 6,995
  • 14
  • 56
  • 87

6 Answers6

72

You can try the next:

public void resizeColumnWidth(JTable table) {
    final TableColumnModel columnModel = table.getColumnModel();
    for (int column = 0; column < table.getColumnCount(); column++) {
        int width = 15; // Min width
        for (int row = 0; row < table.getRowCount(); row++) {
            TableCellRenderer renderer = table.getCellRenderer(row, column);
            Component comp = table.prepareRenderer(renderer, row, column);
            width = Math.max(comp.getPreferredSize().width +1 , width);
        }
        if(width > 300)
            width=300;
        columnModel.getColumn(column).setPreferredWidth(width);
    }
}

JTable

This needs to be executed before the resize method.
If you have:

table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

JTable

Bill K
  • 62,186
  • 18
  • 105
  • 157
Paul Vargas
  • 41,222
  • 15
  • 102
  • 148
  • This is fantastic, ended up using it. I added a check before the setPreferredColumnModel call that looks like "if(width > 300)width=300;" which fixes some cases where I'm displaying really long data fields. I'd suggest adding that to the answer--and you might also extract out min/max width (Would make fantastic optional parameters--in fact I'm going to go do that in my codebase now.) (I wish I knew when it was cool to edit something like that into someone else's answer... Since it's not CW I hate to change content without permission.) – Bill K Sep 07 '16 at 00:22
  • Hi, @BillK Feel free to edit/add the code... and if you have, a screenshot. ;) – Paul Vargas Sep 07 '16 at 00:46
  • 1
    can I also somehow evaluate the header too so that its text won't get cut off? – xeruf Jul 13 '17 at 12:33
  • 2
    @Xerus Add `width = Math.max(width, table.getColumnModel().getColumn(column).getPreferredWidth());` after line 9 in the above code to evaluate the headers. – SomeDude Dec 30 '19 at 16:59
  • Worked perfectly, as expected! – RafiAlhamd Nov 13 '20 at 05:28
4

There is no option to automatically resize one column larger than the other.

Maybe you can to something like:

tca = new TableColumnAdjuster( table, 0 );
tca.adjustColumns();
TableColumnModel tcm = table.getColumnModel();  
TableColumn tc = tcm.getColumn(1);
tc.setWidth(tc.getWidth() + 25);

This would allow you to add extra space to column 1. This extra space would only be added the first time the table is displayed.

Another option is to use:

table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);

This would allocate extra space proportionally to each column.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • 1
    This is the opposite of what was asked. "table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);" resizes all columns evenly without considering the content length. – Shai Alon Dec 30 '21 at 15:26
4

setAutoResizeMode() will tell your table how to resize you should give it a try will all different options available to see the differences, in My case I wanted to specifically resize two columns and let it decide how to adjust all the other ones.

jTable1.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
TableColumnModel colModel=jTable1.getColumnModel();
colModel.getColumn(1).setPreferredWidth(25);    
colModel.getColumn(2).setPreferredWidth(400);
Edwin Barahona
  • 189
  • 1
  • 3
  • 13
0

You can do this:

JPanel jp = new JPanel();
jp.add(table);

jp.setLayout(new GridLayout(1,1)); /* little trick ;) and believe me that this step is important to the automatic all columns resize! A import is also needed for using GridLayout*/
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); // this is obvius part
augus1990
  • 27
  • 1
0

With a slight modification to Paul Vargas's answer, you can also take into account the column header size:

public static void resizeColumnWidth(JTable table) {
    final TableColumnModel columnModel = table.getColumnModel();
    for (int column = 0; column < table.getColumnCount(); column++) {
        // Account for header size
        double width = table.getTableHeader().getHeaderRect(column).getWidth();
        for (int row = 0; row < table.getRowCount(); row++) {
            TableCellRenderer renderer = table.getCellRenderer(row, column);
            Component comp = table.prepareRenderer(renderer, row, column);
            width = Math.max(comp.getPreferredSize().width + 1, width);
        }
        if (width > 300)
            width = 300;
        columnModel.getColumn(column).setPreferredWidth((int) width);
    }
}
Cardinal System
  • 2,749
  • 3
  • 21
  • 42
0

With a slight modification to Paul Vargas's answer, you can also take into account the column header's content:

public static void resizeColumnWidth(JTable table)
{
      TableCellRenderer renderer;
      TableColumn column;
      Component component;
      Object header;
      int rowIndex, minWidth, width;

      column = table.
         getColumnModel().
         getColumn(colIndex);

      renderer = table.
         getTableHeader().
         getDefaultRenderer();

      header    = column.getHeaderValue();
      component = renderer.getTableCellRendererComponent(table, header, false, false, -1, colIndex);
      width     = component.getPreferredSize().width;
      minWidth  = Math.max(width, 0);

      for (rowIndex = table.getRowCount(); --rowIndex >= 0; )
      {
         renderer  = table.getCellRenderer(rowIndex, colIndex);
         component = table.prepareRenderer(renderer, rowIndex, colIndex);
         width     = component.getPreferredSize().width;
         minWidth  = Math.max(minWidth, width);
      }

      column.setPreferredWidth(minWidth);
    }

Note: This is different from Cardinal System's answer in that this code takes into account the header's content and Cardinal System's answer just takes into account the header's size.

Nathan
  • 8,093
  • 8
  • 50
  • 76