3

The output from my program is in a JTextArea inside a JScrollPane. It looks nasty:

Created BinaryTree.java      in     I:\Netbeans OLDIES but KEEPIES\BinaryTree\src\binarytree\BinaryTree.java
Created DisplayStuff.java        in     I:\Netbeans OLDIES but KEEPIES\BinaryTree\src\binarytree\DisplayStuff.java
Created LinkedList.java      in     I:\Netbeans OLDIES but KEEPIES\BinaryTree\src\binarytree\LinkedList.java
Created Node.java        in     I:\Netbeans OLDIES but KEEPIES\BinaryTree\src\binarytree\Node.java
Created notes        in     I:\Netbeans OLDIES but KEEPIES\BinaryTree\src\binarytree\notes
Created TryBinaryTree.java       in     I:\Netbeans OLDIES but KEEPIES\BinaryTree\src\binarytree\TryBinaryTree.java

So I thought about putting the output into a JTable, assuming it would be a simple matter to adjust column size at the end of execution and get results that look more like a spreadsheet and thus be more readable:

enter image description here

I'd never used JTable before, so I tried a simple program to see if I could make a JTable at all. I did. Here it is:

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

public class TestJTable 
{
  static void init()
  {
    fraFrame = new JFrame();
    fraFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        dftTableModel = new DefaultTableModel(0 , 4);
        tblOutput     = new JTable(dftTableModel);
        scrOutput     = new JScrollPane(tblOutput);
        colMdl        =     tblOutput.getColumnModel();

    fraFrame.add(scrOutput); // NOTE: add the SCROLL PANE, not table
    fraFrame.setVisible(true);
    fraFrame.pack();
  }

  public static void main(String[] args) 
  {
    init();
    tblOutput.doLayout();
    dftTableModel.addRow(new Object[]{"Action", "Filename", "", "Path"});
    for (int i = 0; i < 100; i++) 
    {
        String c0 = Utilities.Utilities.repeat("x", (int) (Math.random()*50));
        dftTableModel.addRow(new Object[]{((Math.sin(i)) > 0 ? "Updated" : "Created"), 
                                          c0, "in", c0});
        k = Math.max(k, c0.length());
    }
  }
  static int                  k;
  static JFrame               fraFrame ;
  static JTable               tblOutput; 
  static DefaultTableModel    dftTableModel; 
  static JScrollPane          scrOutput;
  static TableColumnModel     colMdl;
}

And here's the output:

enter image description here

I want to be able to set the columns' sizes exactly as I want.

An hour of spinning my wheels with sizes, preferred sizes, table sizes, autoresizing (and not) led me to try the following in varying combinations at varying parts of the program, none producing satisfactory results, although taking out pack helped somewhat:

    fraFrame.setSize(1400, 600);
    tblOutput.setSize(1500,400);
    colMdl.getColumn(0).setPreferredWidth(15);
    colMdl.getColumn(1).setPreferredWidth(10*k);
    colMdl.getColumn(2).setPreferredWidth(5);
    colMdl.getColumn(3).setPreferredWidth(10*k);

So it is that I have to ask:

(a) Specifically, given that I know that k is the number of characters in the Filename and 'Pathcolumns, how can I make the contents of those columns be exactly fit their columns? (I assumefont` size will enter the picture.)

(b) Generally, how do I change the column size in a JTable? E.g., one column will always say "in". How to make the column be no wider than that?

EDIT

Thanks to @camickr, it was EASY to get the desired output, both in the test program above and in the real thing, output below:

enter image description here

DSlomer64
  • 4,234
  • 4
  • 53
  • 88
  • 4
    For [example](http://stackoverflow.com/questions/13013989/how-to-adjust-jtable-columns-to-fit-the-longest-content-in-column-cells/13037771#13037771). Also, you need to turn of auto column sizing, see `JTable#setAutoResizeMode` for more details – MadProgrammer Aug 13 '15 at 00:50

1 Answers1

8

Check out the Table Column Adjuster.

You can set the column width based on:

  1. the heading of the column
  2. the data in each row of the column
  3. the larger of the heading or data

The class also supports other features to allow for dynamic resizing if the data is changed.

Or you can use the basic code provided which just uses the prepareRenderer(...) method of the JTable to determine the maximum width.

JTable table = new JTable( ... );
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );

for (int column = 0; column < table.getColumnCount(); column++)
{
    TableColumn tableColumn = table.getColumnModel().getColumn(column);
    int preferredWidth = tableColumn.getMinWidth();
    int maxWidth = tableColumn.getMaxWidth();

    for (int row = 0; row < table.getRowCount(); row++)
    {
        TableCellRenderer cellRenderer = table.getCellRenderer(row, column);
        Component c = table.prepareRenderer(cellRenderer, row, column);
        int width = c.getPreferredSize().width + table.getIntercellSpacing().width;
        preferredWidth = Math.max(preferredWidth, width);

        //  We've exceeded the maximum width, no need to check other rows

        if (preferredWidth >= maxWidth)
        {
            preferredWidth = maxWidth;
            break;
        }
    }

    tableColumn.setPreferredWidth( preferredWidth );
}

Edit:

I was hoping that knowing the font size and number of characters

FontMetrics fm = table.getFontMetrics( table.getFont() );
int charWidth = fm.stringWidth("a");
System.out.println( charWidth );
camickr
  • 321,443
  • 19
  • 166
  • 288
  • @camickr--Thanks for the prompt reply. Looks good. I've about had it for today, but a quick readthrough of the code is encouraging. I was hoping that knowing the font size and number of characters (fixed width using Courier New, not shown in my code) would make it just a few lines, but it seems nothing is ever as easy as hoped. – DSlomer64 Aug 13 '15 at 00:56
  • 1
    @DSlomer64, well you can get the size of a fixed width character using code like demonstrated in the edit. But of course you still need to loop through all the rows in the table for every column in order to determine the maximum number of characters in each column. The solution given here will work for any renderer that might be used by the table so it is a more general solution. – camickr Aug 13 '15 at 01:13
  • @camickr--THANK YOU for sharing `TableColumnAdjuster`! After seeing 423 lines of code last night, I thought NO WAY am I gonna be able to use this any time soon. FIrst thing this morning I had at it. `static TableColumnAdjuster tca` declared it; `tca = new tablecolumnadjuster.TableColumnAdjuster(tblOutput)` linked my `JTable` to it; and `tca.setDynamicAdjustment(true)` made the magic happen. It took awhile to fit the pieces together, but my last edit in the OQ shows the result. – DSlomer64 Aug 13 '15 at 17:22