Column Widths


Overview Basic version Model Cell Renderer Editor Column widths Tooltips Controls in cells

The default behaviour of a JTable is to make teh coluns have equal width, and if the user alters the width of the table, or of one column, to equalize the rest. The resize bahaviour is controlled by setAutoResizeMode() which has several options - check the API for details. To use this, you need to start with a clear idea of what you want to do.

We will look at an example where the table adjusts each column to accommodate the data in it. This implies the total table width is fixed. In this case we should use table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); to not allow the user to re-size columns. We want to produce:

We usually construct a scrollpane from the table, and add the scroll pane to the container. But then the header width fills the scrollpane. Instead we add the table, and the header, directly:

 
    private void initComponents() {
        MyModel data = new MyModel();
        table = new JTable(data);
        ..   
        JTableHeader header = table.getTableHeader();
        ..
        setLayout(new BorderLayout());
        add(table.getTableHeader(), BorderLayout.PAGE_START);
        add(table, BorderLayout.CENTER);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); // don't resize columns
        TableColumn column;
        setVisible(true);
        setResizable(false); // disallow container re-sizing
        ..
        pack();
    }
}

We can set column widths by


for (int i = 0; i < table.getModel().getColumnCount(); i++) {
            column = table.getColumnModel().getColumn(i);
            column.setPreferredWidth(...);
        }               

but there is a question of how to organise this. The width of the column will depend on the data in it, which is an aspect of the model. However the actual width, in pixels, will depend on the font in use, which relates to the cell renderer. Ideally the model only concerns the data, while the renderer concerns the display. The solution used here is to get a FontMetric from the cell renderer font, and pass that as an argument to a method in the model. The model class is


class MyModel extends AbstractTableModel {

    private String[] columnNames = {"Short", "Long"};
    private Object[][] data = { {"Aa", "qwert"},
     {"Ba", "qwerthhhjh"},
     {"CCCCC", "A very long piece of text"},
     {"Da", "qwertoooooooo"},
    };
 
    int getColumnWidth(int col, FontMetrics metrics) {
        int result=0;
        for (int row=0; row < getRowCount(); row++)
        { // for each row
        // find length of text, inc. +2 for padding
        int adv = metrics.stringWidth((String) data[row][col])+2;
        if (adv>result) result=adv; // result is the biggest
        }
        return result;
    }

    .. as elsewhere..
}

Then we use that in initComponents():

    private void initComponents() {
        MyModel data = new MyModel();
        table = new JTable(data);
        .. as before
        FontMetrics metrics = table.getGraphics().getFontMetrics(MyRenderer.font);
        for (int i = 0; i < table.getModel().getColumnCount(); i++) {
            column = table.getColumnModel().getColumn(i);
            column.setPreferredWidth(data.getColumnWidth(i, metrics));
        }
        pack();
    }

Comments

0 responses so far

Add a new comment

Your name

Your email (will not be published)

Your comment (no HTML)

Are you a robot? Please type the two words: