[Java] Specifying the column widths of a JTable as percentages

The widths of the columns of a JTable are specified through TableColumn.setWidth. To set the widths of the columns as percentage, set the widths of column in proportion to each other. For example:

private static JTable createTable() {
    JTable table = new JTable(1, 3);
    TableColumnModel model = table.getColumnModel();

    model.getColumn(0).setHeaderValue("20 %");
    model.getColumn(1).setHeaderValue("30 %");
    model.getColumn(2).setHeaderValue("50 %");

    setWidthAsPercentages(table, 0.20, 0.30, 0.50);
    TableModel tableModel = table.getModel();

    tableModel.setValueAt("First Column", 0, 0);
    tableModel.setValueAt("Second Column", 0, 1);
    tableModel.setValueAt("Third Column", 0, 2);
}

/**
 * Set the width of the columns as percentages.
 * 
 * @param table
 *            the {@link JTable} whose columns will be set
 * @param percentages
 *            the widths of the columns as percentages; note: this method
 *            does NOT verify that all percentages add up to 100% and for
 *            the columns to appear properly, it is recommended that the
 *            widths for ALL columns be specified
 */
private static void setWidthAsPercentages(JTable table,
        double... percentages) {
    final double factor = 10000;

    TableColumnModel model = table.getColumnModel();
    for (int columnIndex = 0; columnIndex < percentages.length; columnIndex++) {
        TableColumn column = model.getColumn(columnIndex);
        column.setPreferredWidth((int) (percentages[columnIndex] * factor));
    }
}

The percentage can be specified in the range from 0 to 1 (with 0 being 0% and 1 being 100%) or the range from 0 to 100. Note that the above implementation of setWidthAsPercentages relies that the widths for ALL columns are specified. It also relies a value of factor that is sufficiently large to guarantee that the total of the widths is greater than the width of the table. If the sum of the column widths is less than the table’s initial width, some of the columns will be expanded. Yet, when the total is greater than the table’s widths, the columns widths are reduced in the required fashion.

This means you would need to ensure that the initial width of the table is less than 10000 and if changes are made later, this value may need to be revised. If the table is being placed in a JScrollPane, you could use getPreferredScrollableViewportSize instead:

    ...
    final double factor = table.getPreferredScrollableViewportSize().getWidth();
    ...

Interesting, a factor that is too large can cause the table headings to be rendererd incorrectly. When factor is changed to Double.MAX_VALUE, the table is rendered like this when it is first loaded:

Admittedly, I have do yet fully understand why this happens when (however, I think there could be an overflow when Java is performing the calculations for laying out the table). When this happens, you can get the headings to appear by moving the mouse over them. When using the view port size, beware that the default viewport size happens to be 450 x 400 and is coded into the JTable‘s initializeLocalVars method (at least for Oracle Java) – so it is possible for the value to differ between different Java implementations.

Leave a comment