Search code examples
javaswingjpaneljscrollpanejscrollbar

JScrollPane doesn't work while inside a JPanel


JScrollPane works perfectly when I give it a JPanel and then add the JScrollPane directly on to a JFrame with frame.getContentPane.add(). However, it doesn't work when I add the JScrollPane to a JPanel and then add the JPanel to the JFrame. I need to use the second method because I'm going to add multiple things inside the JPanel and JFrame and I need to keep it organized. Here is my code.

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

public class Main {
    
    /**
     * @param inpanel asks if the JScrollPane should
     * be inside of a JPanel (so other things can also be added)
     */
    public static void testScroll(boolean inpanel) {
        JFrame f = new JFrame();
        f.setLayout(new BorderLayout());
        f.setResizable(true);
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createLineBorder(Color.red));
        //panel.setLayout(new BoxLayout(panel, 1));
        panel.setLayout(new GridLayout(0,1));
        for (int i = 0; i < 100; i++) {
            JLabel l = new JLabel("hey"+i,SwingConstants.CENTER);
            l.setBorder(BorderFactory.createLineBorder(Color.green));
            l.setPreferredSize(new Dimension(200,200));
            panel.add(l);
        }
        JScrollPane scrollPane = new JScrollPane(panel);
        scrollPane.setBorder(BorderFactory.createLineBorder(Color.blue));

        //**********THIS DOES NOT WORK HOW I WANT IT TO************
        if(inpanel){ 
            JPanel holder = new JPanel();
            holder.add(scrollPane);
            f.getContentPane().add(holder);
        }
        //************THIS DOES WORK HOW I WANT IT TO****************
        else{ 
            f.getContentPane().add(scrollPane);
        }
        f.pack();
        f.setSize(500, 500);
        f.setExtendedState(JFrame.MAXIMIZED_BOTH);
        
        f.setVisible(true);
        
        JScrollBar bar = scrollPane.getVerticalScrollBar();
        bar.setValue(bar.getMaximum());
        bar.setUnitIncrement(50);
    }

    public static void main(String[] args) {
        
        Runnable r = new Runnable() {
            @Override
            public void run() {
                testScroll(false); //OR TRUE
            }
        };
        SwingUtilities.invokeLater(r);
        
    }

}

In the main method, if I pass false, it works like I mentioned before, but when I pass true it shows up without a scroll bar.

Picture when passing false

enter image description here

Picture when passing true

enter image description here

I need a way to add the JScrollPane to a JPanel and still have it work. Thanks in advance!


Solution

  • Your problem is the holder JPanel's layout. By default it is FlowLayout which will not re-size its child components when need be. Make it a BorderLayout instead, and your scrollpane will resize when needed. If you need something more complex, check out the layout manager tutorials.