views:

71

answers:

1

Hey,

I have a containing panel JPanel with a Flow Layout, the containing panel is in a JScrollPane, the containing panel holds a bunch of other JPanels, inner panels, in it. All the inner panels have the same dimensions. If there are more panels then the containing panel can hold in its width then they are gridded downwards, and if there are more panels then the containing panel can hold in its height, then the inner panels are aligned in the same grid with the exception of the last row which is centered with the row before last.

While I resize the dialog the containing panel extends and the layout flow layout perform its duty, but the scroll bars do not appear although the size of the panel exceeds the bounds of the JScrollPane.

How do I control the appearance of the scroll bars when I resize the containing panel dynamically?

as for the images, they should sum it up:

alt text

After extending the dialog width:

alt text

Adam

+1  A: 

You need to make the containing panel implement Scrollable, and set the preferred scrollable viewport size according to the width.

import java.awt.*;
import javax.swing.*;

public class Test
{
    public static void main(String args[])
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                JPanel container = new ScrollablePanel();
                container.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
                for( int i = 0; i < 20; ++i )
                {
                    JPanel p = new JPanel();
                    p.setBorder(BorderFactory.createLineBorder(Color.RED));
                    p.setPreferredSize(new Dimension(50, 50));
                    p.add(new JLabel("" + i));
                    container.add(p);
                }

                JScrollPane scroll = new JScrollPane(container);
                scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
                scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

                JFrame f = new JFrame("Test");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                    
                f.getContentPane().add(scroll);                    
                f.pack();
                f.setSize(250, 300);
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}

class ScrollablePanel extends JPanel implements Scrollable
{
    public Dimension getPreferredSize()
    {
        return getPreferredScrollableViewportSize();
    }

    public Dimension getPreferredScrollableViewportSize()
    {
        if( getParent() == null )
            return getSize();
        Dimension d = getParent().getSize();
        int c = (int)Math.floor((d.width - getInsets().left - getInsets().right) / 50.0);
        if( c == 0 )
            return d;
        int r = 20 / c;
        if( r * c < 20 )
            ++r;
        return new Dimension(c * 50, r * 50);
    }

    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
    {
        return 50;
    }

    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
    {
        return 10;
    }

    public boolean getScrollableTracksViewportHeight()
    {
        return false;
    }

    public boolean getScrollableTracksViewportWidth()
    {
        return getParent() != null ? getParent().getSize().width > getPreferredSize().width : true;
    }
}

All numbers are hardcoded for simplicity, but you should get the idea.

Geoffrey Zheng
WOW, took me forever, the getPreferredScrollableViewportSize() was not called no matter what I did, only the getPreferredSize() was called, so I started from scratch, and then it worked, frustrated I compared the two codes, and apparently the NetBeans generates a setPreferredSize(w,h) in some cases, and once this is set the viewport layout skips the method. Good ridden, this was a bugger. Thanks for your help, I think I got everything I need.
TacB0sS
What's why I don't use a GUI builder :)
Geoffrey Zheng