Search code examples
javaswinglayoutjpaneljscrollpane

Nested JScrollPane not fitting


I'm having an issue with nested JScrollPanes. Basically I want to have one outer JScrollPane that scrolls vertically but not horizontally (Think the Netflix web interface). Inside this outer JScrollPane I want to have multiple JScrollPanes that scroll horizontally. My problem is that horizontal scrollbars for the inner JScrollPanes never show up as it looks like they take up the entire preferred size of their JPanels. Here is an image to describe what I am talking about:

enter image description here

EDIT: This code based on camickr's answer is now working:

import java.awt.BorderLayout;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class NestedScrollPane extends JFrame {

    public NestedScrollPane() {
        ScrollablePanel outerPanel = new ScrollablePanel();
        outerPanel.setScrollableWidth(ScrollablePanel.ScrollableSizeHint.FIT);
        outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.Y_AXIS));
        for (int j = 0; j < 20; j++) {
            ScrollablePanel innerPanel = new ScrollablePanel();
            innerPanel.setScrollableHeight(ScrollablePanel.ScrollableSizeHint.NONE);
            innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.X_AXIS));
            JScrollPane innerScrollPane = new JScrollPane(innerPanel);
            innerScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
            for (int i = 0; i < 10; i++) {
                JLabel longLabel = new JLabel("asefaesfesfesfgesgersgrsgdrsgdrsgderg ");
                innerPanel.add(longLabel);
            }
            outerPanel.add(innerScrollPane);
        }
        JScrollPane outerPane = new JScrollPane(outerPanel);
        outerPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        this.setContentPane(outerPane);
        this.setSize(400, 400);
        outerPane.setSize(400, 400);
        this.setVisible(true);
    }

    public static void main (String[] args) {
        NestedScrollPane pane = new NestedScrollPane();
        pane.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

I took a look at How to get JScrollPanes within a JScrollPane to follow parent's resizing but using BoxLayout or BorderLayout on the outer panel doesn't seem to fix anything.


Solution

  • You need to implement the Scrollable interface of the outer panel added to the viewport to force the panel to fill the width of the viewport.

    An easy way to do this is to use the Scrollable Panel. You should be able to use:

    // JPanel outerPanel = new JPanel();
    ScrollablePanel outerPanel = new ScrollablePanel();
    outerPanel.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );