11

I have a JTable that will have the last column data field change to different string values. I want to resize the column to the string length. What is the formula for string length to width?

I'm going to be using JTable.getColumnModel().getColumn().setPreferredWidth() so I want to know how to translate string length to width value.

kleopatra
  • 51,061
  • 28
  • 99
  • 211
Hank
  • 3,367
  • 10
  • 48
  • 86

3 Answers3

15

you are not really interested in the string length (nor its mapping to a particular font/metrics). You're interested in the preferredSize of the renderingComponent which renderers the cell content. To get that, loop through all rows and query the size, something like

 int width = 0;
 for (row = 0; row < table.getRowCount(); row++) {
     TableCellRenderer renderer = table.getCellRenderer(row, myColumn);
     Component comp = table.prepareRenderer(renderer, row, myColumn);
     width = Math.max (comp.getPreferredSize().width, width);
 }

Or use JXTable (in the SwingX project): it has a method pack() which does the work for you :-)

Edit: the reason to prefer the table's prepareRenderer over manually calling getXXRendererComponent on the renderer is that the table might do decorate visual properties of the renderingComponent. If those decorations effect the prefSize of the component, a manual config is off.

Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • the tableColumn.getWidth() != tableColumn.getPreferredWidth() - the former property is the actual width while the latter is what the columns wants to get. Depending on JTable's autoResizeMode the columns are squeezed/spread to fit the viewport. Try table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF). Most probably this will show a scrollBar (the table is in a JScrollPane, right?) and the column width is the same as its prefWidth – kleopatra Apr 28 '11 at 15:06
  • Great answer, I was just implementing this logic with the string length when I found this question. But do you have an idea how to consider the column name length, too? – das Keks May 13 '13 at 14:25
  • Okay, just found out that there is a method `getHeaderRenderer()` – das Keks May 13 '13 at 14:37
5

This method will pack a given column in a JTable -

/**
 * Sets the preferred width of the visible column specified by vColIndex. The column
 * will be just wide enough to show the column head and the widest cell in the column.
 * margin pixels are added to the left and right
 * (resulting in an additional width of 2*margin pixels).
 */ 
public static void packColumn(JTable table, int vColIndex, int margin) {
    DefaultTableColumnModel colModel = (DefaultTableColumnModel)table.getColumnModel();
    TableColumn col = colModel.getColumn(vColIndex);
    int width = 0;

    // Get width of column header
    TableCellRenderer renderer = col.getHeaderRenderer();
    if (renderer == null) {
        renderer = table.getTableHeader().getDefaultRenderer();
    }
    java.awt.Component comp = renderer.getTableCellRendererComponent(
        table, col.getHeaderValue(), false, false, 0, 0);
    width = comp.getPreferredSize().width;

    // Get maximum width of column data
    for (int r=0; r<table.getRowCount(); r++) {
        renderer = table.getCellRenderer(r, vColIndex);
        comp = renderer.getTableCellRendererComponent(
            table, table.getValueAt(r, vColIndex), false, false, r, vColIndex);
        width = Math.max(width, comp.getPreferredSize().width);
    }

    // Add margin
    width += 2*margin;

    // Set the width
    col.setPreferredWidth(width);
}
spot35
  • 888
  • 4
  • 9
4

Table Column Adjuster works both statically and dynamically and the user can control this.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • just for emphasis, repeating my comment from above: be lazy: JTable has a method prepareRenderer - let that do it's work instead of preparing manually – kleopatra Apr 28 '11 at 14:56
  • @kleopatra, Thanks for pointing that out Jeanette. Usually I am lazy. Other postings in my blog do use this method. Not sure why I didn't use the prepareRender() method this time :) – camickr Apr 28 '11 at 15:28