I came across a common problem the other day that I am sure many of you have. As it had been ages since I last solved it I turned to Google hoping it would come to my rescue. Well either I wasn’t guessing the right search terms or the answer is not out there. So I thought I would help the situation by writing a blog with the answer.

So the problem is you have some component in a scroll pane and when its preferred height is less than the scollpane area then you want it to stretch to fill the scollpane. But when it grows bigger than the scollpane area you would like it show the scrollbars. This is very useful when you want to be able to click in the spare space to clear selection or in the case of drag and drop where you want to be able to drop into the empty area. There was a bug fixed in JDK 6 that made this possible for JTable with setFillsViewportHeight(true). So here is how you do it for your own components: You need to make the component that is in the JScrollPane implement javax.swing.Scrollable and below is a skeleton implementation for you.

    public Dimension getPreferredScrollableViewportSize() {
        return getPreferredSize();
    }

    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
        return (orientation == SwingConstants.HORIZONTAL)? visibleRect.width : visibleRect.height;
    }

    public boolean getScrollableTracksViewportHeight() {
        boolean tracks = false;
        if (getParent() instanceof JViewport) {
            tracks = getPreferredSize().getHeight() <
                    ((JViewport) getParent()).getExtentSize().getHeight();
        }
        return tracks;
    }

    public boolean getScrollableTracksViewportWidth() {
        return true;
    }

    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
        return getScrollableBlockIncrement(visibleRect, orientation, direction)/5;
    }

The key part of this is the getScrollableTracksViewportHeight() method that adjusts its returned value based on the relationship between preferred height and visible height. You could use something similar for getScrollableTracksViewportWidth() if you want a similar effect in that direction. Now I just have to remember to look at my blog next time I need to do this 😉