Auto adjust the height of rows in a JTable
Asked Answered
Q

3

21

In a JTable, how can I make some rows automatically increase height to show the complete multiline text inside? This is how it is displayed at the moment:

I do not want to set the height for all rows, but only for the ones which have multiline text.

Qintar answered 23/11, 2009 at 14:53 Comment(0)
E
40

The only way to know the row height for sure is to render each cell to determine the rendered height. After your table is populated with data you can do:

private void updateRowHeights()
{
    for (int row = 0; row < table.getRowCount(); row++)
    {
        int rowHeight = table.getRowHeight();

        for (int column = 0; column < table.getColumnCount(); column++)
        {
            Component comp = table.prepareRenderer(table.getCellRenderer(row, column), row, column);
            rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
        }

        table.setRowHeight(row, rowHeight);
    }
}

If only the first column can contain multiple line you can optimize the above code for that column only.

Entrant answered 23/11, 2009 at 17:14 Comment(3)
Do i need a table model for this?Atomizer
I would like to add here, that while this solves variable row heights in jtable, it also solves the selection of the desired row, which would correctly scroll the viewport, if called after this method. Many examples out there, that use row height adjustment in cell renderer, can never correctly scroll to the desired row after populating the tableProulx
IF THIS DOES NOT WORK, do not call updateRowHeights() directly. Instead, wrap it in an EventQueue.invokeLater() block.Hadlee
C
3

Camickr's solution did not work for me at all. My data model was dynamic though - it changed all the time. I guess the mentioned solution works for static data, like coming from an array.

I had JPanel for cell renderer component and it's preferred size wasn't set correctly after using prepareRenderer(...). The size was set correctly after the containing window was already visible and did repaint (2 times in fact after some unspecified, though short time). How could I call updateRowHeights() method shown above then and where would I do this? If I called it in (overriden) Table.paint() it obviously caused infinite repaints. It took me 2 days. Literally. The solution that works for me is this one (this is the cell renderer I used for my column):

public class GlasscubesMessagesTableCellRenderer extends MyJPanelComponent implements TableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
            int row, int column) {
        //this method updates GUI components of my JPanel based on the model data
        updateData(value);
        //this sets the component's width to the column width (therwise my JPanel would not properly fill the width - I am not sure if you want this)
        setSize(table.getColumnModel().getColumn(column).getWidth(), (int) getPreferredSize().getHeight());

        //I used to have revalidate() call here, but it has proven redundant

        int height = getHeight();
        // the only thing that prevents infinite cell repaints is this
        // condition
        if (table.getRowHeight(row) != height){
            table.setRowHeight(row, height);
        }
        return this;
    }
}
Chrystal answered 11/5, 2016 at 9:20 Comment(6)
You can set RowHeight dynamically like this.Schramke
Thank you GAVD. Oh did I try that ;) Unfortunately TableModelListener's events are events of the table model not the table GUI. They are raised /long/ before the GUI repaints itself and GUI components have their sizes calculated properly. You can force-calculate the sizes at this point (I couldn't figure this out for 2 days), but why would you? The repaint will do the job anyway. I know this solution is dirty, but after 2 days your perfectionism subsides, you know ;)Chrystal
You will never be able to correctly scroll to the desired row using this approachProulx
@Proulx would be great if you could propose alternative solution, then. I can't see a problem but would love if you could elaborate so that I could understand your point of view.Chrystal
Correct solution is the accepted answer, which will be able to scroll correctly after populating the table. See my comment there. Your solution doesn't work with variable row heights, you can't control the renderer, when it decides it needs to redraw.Proulx
The accepted answer did not work for me either. However, it was solved by wrapping the update row height code in an EventQueue.invokeLater().Hadlee
R
2

You must iterate over each row, get the bounding box for each element and adjust the height accordingly. There is no code support for this in the standard JTable (see this article for a solution for Java ... 1.3.1 =8*O).

Roar answered 23/11, 2009 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.