108

I have a JTable in which I set the column size as follows:

table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getColumnModel().getColumn(0).setPreferredWidth(27);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(90);
table.getColumnModel().getColumn(4).setPreferredWidth(90);
table.getColumnModel().getColumn(6).setPreferredWidth(120);
table.getColumnModel().getColumn(7).setPreferredWidth(100);
table.getColumnModel().getColumn(8).setPreferredWidth(95);
table.getColumnModel().getColumn(9).setPreferredWidth(40);
table.getColumnModel().getColumn(10).setPreferredWidth(400);

This works fine, but when the table is maximized, I get empty space to the right of the last column. Is it possible to make the last column resize to the end of the window when resized?

I found AUTO_RESIZE_LAST_COLUMN property in docs but it does not work.

Edit: JTable is in a JScrollPane its prefered size is set.

Jason Plank
  • 2,336
  • 5
  • 31
  • 40
Hamza Yerlikaya
  • 49,047
  • 44
  • 147
  • 241

9 Answers9

48

What happens if you call setMinWidth(400) on the last column instead of setPreferredWidth(400)?

In the JavaDoc for JTable, read the docs for doLayout() very carefully. Here are some choice bits:

When the method is called as a result of the resizing of an enclosing window, the resizingColumn is null. This means that resizing has taken place "outside" the JTable and the change - or "delta" - should be distributed to all of the columns regardless of this JTable's automatic resize mode.

This might be why AUTO_RESIZE_LAST_COLUMN didn't help you.

Note: When a JTable makes adjustments to the widths of the columns it respects their minimum and maximum values absolutely.

This says that you might want to set Min == Max for all but the last columns, then set Min = Preferred on the last column and either not set Max or set a very large value for Max.

Eddie
  • 53,828
  • 22
  • 125
  • 145
24

With JTable.AUTO_RESIZE_OFF, the table will not change the size of any of the columns for you, so it will take your preferred setting. If it is your goal to have the columns default to your preferred size, except to have the last column fill the rest of the pane, You have the option of using the JTable.AUTO_RESIZE_LAST_COLUMN autoResizeMode, but it might be most effective when used with TableColumn.setMaxWidth() instead of TableColumn.setPreferredWidth() for all but the last column.

Once you are satisfied that AUTO_RESIZE_LAST_COLUMN does in fact work, you can experiment with a combination of TableColumn.setMaxWidth() and TableColumn.setMinWidth()

akf
  • 38,619
  • 8
  • 86
  • 96
  • 1
    When AUTO_RESIZE_LAST_COLUMN is used table is resized to fit the scroll pane my goal is to have the table at certain min size but make it grow if it is bigger than my mininum size. – Hamza Yerlikaya Jun 05 '09 at 04:11
  • You can have this behavior if you use TableColumn.setMinWidth() instead of TableColumn.setMaxWidth(). – akf Jun 05 '09 at 04:35
  • to add to my last comment: use TableColumn.setMinWidth() for each column in your table, including the last column. – akf Jun 05 '09 at 04:36
  • setting both min and max width solved the problem but now scroll bars are missin. – Hamza Yerlikaya Jun 05 '09 at 06:50
16

JTable.AUTO_RESIZE_LAST_COLUMN is defined as "During all resize operations, apply adjustments to the last column only" which means you have to set the autoresizemode at the end of your code, otherwise setPreferredWidth() won't affect anything!

So in your case this would be the correct way:

table.getColumnModel().getColumn(0).setPreferredWidth(27);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(90);
table.getColumnModel().getColumn(4).setPreferredWidth(90);
table.getColumnModel().getColumn(6).setPreferredWidth(120);
table.getColumnModel().getColumn(7).setPreferredWidth(100);
table.getColumnModel().getColumn(8).setPreferredWidth(95);
table.getColumnModel().getColumn(9).setPreferredWidth(40);
table.getColumnModel().getColumn(10).setPreferredWidth(400);
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
Rico Ocepek
  • 767
  • 6
  • 20
6

Use this method

public static void setColumnWidths(JTable table, int... widths) {
    TableColumnModel columnModel = table.getColumnModel();
    for (int i = 0; i < widths.length; i++) {
        if (i < columnModel.getColumnCount()) {
            columnModel.getColumn(i).setMaxWidth(widths[i]);
        }
        else break;
    }
}

Or extend the JTable class:

public class Table extends JTable {
    public void setColumnWidths(int... widths) {
        for (int i = 0; i < widths.length; i++) {
            if (i < columnModel.getColumnCount()) {
                columnModel.getColumn(i).setMaxWidth(widths[i]);
            }
            else break;
        }
    }
}

And then

table.setColumnWidths(30, 150, 100, 100);
Miss Chanandler Bong
  • 4,081
  • 10
  • 26
  • 36
Oleg Mikhailov
  • 5,751
  • 4
  • 46
  • 54
4

This code is worked for me without setAutoResizeModes.

        TableColumnModel columnModel = jTable1.getColumnModel();
        columnModel.getColumn(1).setPreferredWidth(170);
        columnModel.getColumn(1).setMaxWidth(170);
        columnModel.getColumn(2).setPreferredWidth(150);
        columnModel.getColumn(2).setMaxWidth(150);
        columnModel.getColumn(3).setPreferredWidth(40);
        columnModel.getColumn(3).setMaxWidth(40);
Harsha Basnayake
  • 4,565
  • 3
  • 17
  • 23
4

Reading the remark of Kleopatra (her 2nd time she suggested to have a look at javax.swing.JXTable, and now I Am sorry I didn't have a look the first time :) ) I suggest you follow the link

I had this solution for the same problem: (but I suggest you follow the link above) On resize the table, scale the table column widths to the current table total width. to do this I use a global array of ints for the (relative) column widths):

private int[] columnWidths=null;

I use this function to set the table column widths:

public void setColumnWidths(int[] widths){
    int nrCols=table.getModel().getColumnCount();
    if(nrCols==0||widths==null){
        return;
    }
    this.columnWidths=widths.clone();

    //current width of the table:
    int totalWidth=table.getWidth();
    
    int totalWidthRequested=0;
    int nrRequestedWidths=columnWidths.length;
    int defaultWidth=(int)Math.floor((double)totalWidth/(double)nrCols);

    for(int col=0;col<nrCols;col++){
        int width = 0;
        if(columnWidths.length>col){
            width=columnWidths[col];
        }
        totalWidthRequested+=width;
    }
    //Note: for the not defined columns: use the defaultWidth
    if(nrRequestedWidths<nrCols){
        log.fine("Setting column widths: nr of columns do not match column widths requested");
        totalWidthRequested+=((nrCols-nrRequestedWidths)*defaultWidth);
    }
    //calculate the scale for the column width
    double factor=(double)totalWidth/(double)totalWidthRequested;

    for(int col=0;col<nrCols;col++){
        int width = defaultWidth;
        if(columnWidths.length>col){
            //scale the requested width to the current table width
            width=(int)Math.floor(factor*(double)columnWidths[col]);
        }
        table.getColumnModel().getColumn(col).setPreferredWidth(width);
        table.getColumnModel().getColumn(col).setWidth(width);
    }
    
}

When setting the data I call:

    setColumnWidths(this.columnWidths);

and on changing I call the ComponentListener set to the parent of the table (in my case the JScrollPane that is the container of my table):

public void componentResized(ComponentEvent componentEvent) {
    this.setColumnWidths(this.columnWidths);
}

note that the JTable table is also global:

private JTable table;

And here I set the listener:

    scrollPane=new JScrollPane(table);
    scrollPane.addComponentListener(this);
Peter Alsen
  • 320
  • 2
  • 5
  • 15
michel.iamit
  • 5,788
  • 9
  • 55
  • 74
  • 1
    as far as I can see, this is a (very brittle) hack: it doesn't update on user changing a column width. Again, I would suggest you look into the source code of JXTable - it has an additional property horizontalScroll which triggers filling the available width if the sum of column prefs is less than the current width and shows a horizontal scrollbar otherwise – kleopatra Dec 12 '11 at 19:51
  • I Know it does not react to the user changing the table widths manually, in that way it's a hack... but again: it's better than suggested above. But you made me curious to JXTable.... I will have a look there! (and nice to walk in to you again on a table subject :) ) – michel.iamit Dec 12 '11 at 19:55
  • You were right, see my remark on top of my answer, I upvoted your remark! – michel.iamit Dec 12 '11 at 20:05
  • At least this was useful for me, I used this approach for my case with a column weight principle. – Solostaran14 Nov 08 '13 at 17:10
2
fireTableStructureChanged();

will default the resize behavior ! If this method is called somewhere in your code AFTER you did set the column resize properties all your settings will be reset. This side effect can happen indirectly. F.e. as a consequence of the linked data model being changed in a way this method is called, after properties are set.

count0
  • 2,537
  • 2
  • 22
  • 30
1

No need for the option, just make the preferred width of the last column the maximum and it will take all the extra space.

table.getColumnModel().getColumn(0).setPreferredWidth(27);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(90);
table.getColumnModel().getColumn(4).setPreferredWidth(90);
table.getColumnModel().getColumn(6).setPreferredWidth(120);
table.getColumnModel().getColumn(7).setPreferredWidth(100);
table.getColumnModel().getColumn(8).setPreferredWidth(95);
table.getColumnModel().getColumn(9).setPreferredWidth(40);
table.getColumnModel().getColumn(10).setPreferredWidth(Integer.MAX_INT);
David Newcomb
  • 10,639
  • 3
  • 49
  • 62
-3

Use this code. It worked for me. I considered for 3 columns. Change the loop value for your code.

TableColumn column = null;
for (int i = 0; i < 3; i++) {
    column = table.getColumnModel().getColumn(i);
    if (i == 0) 
        column.setMaxWidth(10);
    if (i == 2)
        column.setMaxWidth(50);
}
Miss Chanandler Bong
  • 4,081
  • 10
  • 26
  • 36
Arijit
  • 1,633
  • 2
  • 21
  • 35