This discussion is archived
9 Replies Latest reply: Oct 18, 2012 5:56 PM by robli RSS

JTable row height and JScrollPane

robli Newbie
Currently Being Moderated
Using SE 6.

I have a single column JTable that renders it's rows as JPanel components. The preferred size/height of the panel in each row is based on the content of each row. In current version, the renderer is then calling back to the JTable to set the height of the row as each are rendered. All works fine except when the table contains more rows than it can display, the renderer isn't setting the heights for all the rows until the JScrollPane is used by user to bring all rows into focus. The JTable is fine with this, but the initial state/value of the scroll-bar isn't 100%, and as the user drags it down, the scrollbar 'flickers' as the JTable adjusts the height as new rows are brought into the display.

Typically aren't many rows in these JTable components (~20 odd, but that's often enough to engage the scrollbar) so would like to find a way to prepare the heights of all rows after the data is loaded rather than waiting for user to display them all. Wondered if anyone else had a solution / idea about how this might be achieved ?

Many thanks,
  • 1. Re: JTable row height and JScrollPane
    Kleopatra Journeyer
    Currently Being Moderated
    robli wrote:
    Using SE 6.

    I have a single column JTable that renders it's rows as JPanel components. The preferred size/height of the panel in each row is based on the content of each row. In current version, the renderer is then calling back to the JTable to set the height of the row as each are rendered.
    Wrong - a renderer must never-ever change the state of the caller! Not having the correct size initially is the least of possible problems, at worst you could get nasty loops ...

    Instead, re/calculate and set the rowHeight somewhere else when needed, f.i. initially, when the content changes, when the width changes...

    BTW, SwingX has utility methods - no rocket science, just in case you use it anywhay and did not yet detect TableUtilities :-)

    Cheers
    Jeanette
  • 2. Re: JTable row height and JScrollPane
    robli Newbie
    Currently Being Moderated
    Thanks for the feedback; appreciate the input.

    I guess my issue is that I need to essentially run up the render algorithm to work out how large the row is (preferred size/height of JPanel which the renderer returns). So you would suggest that having loaded the table data, the 'render algorithm' is invoked to determine the row height, set it, and then let the JTable render itself as/when it needs to invoking the same algorithm confident that the row heights are already set appropriately.

    If so, then would you suggest use of an arbitrary Graphics context from a BufferedImage to do this, with appropriate size / constraints established from bounding container etc.

    Thanks again,
  • 3. Re: JTable row height and JScrollPane
    Kleopatra Journeyer
    Currently Being Moderated
    no graphics needed (normally) simply let the table prepare the renderer, ask for its prefSize and use that height as the rowHeight, something like (leaving out looping across columns/rows)
    TableCellRenderer r = table.getCellRenderer(row, col);
    Component comp = table.prepareRenderer(r, row, col);
    int height = comp.getPreferredSize().height;
    table.setRowHeight(height);
    Complete code f.i. http://java.net/projects/swingx/sources/svn/content/trunk/swingx-core/src/main/java/org/jdesktop/swingx/table/TableUtilities.java?rev=4246

    Cheers
    Jeanette

    forgot: how to format a reference correctly? The button above produces .. crap.
  • 4. Re: JTable row height and JScrollPane
    robli Newbie
    Currently Being Moderated
    Thanks again for your feedback here.

    The prepareRenderer approach looks like it may pay off, but because the component contains content painted on a JPanel, we don't actually know what the preferredSize of the JPanel should be until we actually run the paintComponent. Without the graphics context, the fonts etc. aren't known, and all of this drives the height required for the row.

    So calling the prepareRenderer returns me the JPanel OK, but because this doesn't necessitate the painting of the panel, the preferredSize is still unknown. So I'm thinking that what I need to be able to do is having obtained the JPanel, paint it into an abstract buffer sized to the required width, read the height and set the row height. Adding something like ...
    BufferedImage buf = new BufferedImage((int)bean.getSize().getWidth(), 5000, BufferedImage.TYPE_INT_RGB);
    comp.paintAll(buf.createGraphics());
    ... doesn't want to trigger the JPanel paint however. How would you ordinarily prepareRenderer in the case where a graphics / paint is required ?

    Thanks again,
  • 5. Re: JTable row height and JScrollPane
    Kleopatra Journeyer
    Currently Being Moderated
    robli wrote:
    we don't actually know what the preferredSize of the JPanel should be until we actually run the paintComponent.
    sounds fishy ... hard to tell without an SSCCE.

    Cheers
    Jeanette
  • 6. Re: JTable row height and JScrollPane
    robli Newbie
    Currently Being Moderated
    Thanks again.

    I guess it's more of a conceptual issue from where I sit. If I have a graphics JPanel as my cell component on which I'm painting the cell value (amongst other things) and it can wrap the content as many times as it likes, and the row height / cell size needs to be set so as to ensure that the whole content displays for each row, how would we best go about doing this ? Having loaded the table, do we simply cycle through the rows and prepare the render for each row and set the row heights accordingly. And if so, what of the graphics context - will an arbitrary buffer do etc. ? I guess this is what I was thinking someone might have wrestled with already.

    The code is all there to work it out, but it would seem the issue is triggering it. If a preparatory paint request isn't going to fire it (as would seem to be the case), then I'll need to shift the code around and extend the JPanel so I can trigger the necessary rendering code independent of a paint.

    Thanks,
  • 7. Re: JTable row height and JScrollPane
    Kleopatra Journeyer
    Currently Being Moderated
    last order .. :-) If you need a paint request to let the panel decide about its prefSize, you most probably are doing something wrong - as in really wrong.

    Cheers
    Jeanette

    PS: I'm out of this until you show an SSCCE ;-)
  • 8. Re: JTable row height and JScrollPane
    robli Newbie
    Currently Being Moderated
    Thanks again, but as you suggest, think this has run it's course. Seems pretty simple to me; the panel content drives the size required, the paint is the activity that determines how the content lays down on the panel, pre-painting the component somewhere to determine it's height would be simplest. If that isn't something that resonates with anyone, then I'll need to extend the JPanel and locate the render routine so that I can invoke it with or without the paint.

    Thanks,
  • 9. Re: JTable row height and JScrollPane
    robli Newbie
    Currently Being Moderated
    For the record; this resolved by breaking out the JPanel into it's own class which enabled the paintComponent() routines for rendering the content & determining the required height (or # of lines based on applied fonts etc.) to be invoked using an arbitrary bufferedImage for each row after the initial load. Means that when the panel is rendered from a paint request issued by the JTable that the row-height is already set, which ensures that the scroll-bar also knows it's values at initial render. Working great.

    Thanks,

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points