-1

I tried to add a JPanel (with FlowLayout) to a JScrollPane but the ScrollBar is not working. I want to place buttons as grid but it places horizontally.

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

public class Test {
    public static void main(String[] args){
        JFrame frame = new JFrame("Test");
        frame.setVisible(true);
        frame.setSize(1000,500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout(FlowLayout.LEFT));

        JScrollPane pane = new JScrollPane(panel);
        pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        frame.add(pane);

        for (int i=0;i<100;i++){
            panel.add(new JButton("Label"));
        }
    }
}

enter image description here enter image description here

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Why not use [GridLayout](https://docs.oracle.com/javase/tutorial/uiswing/layout/grid.html) or [GridBagLayout](https://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html) instead of `FlowLayout`? – Abra Feb 05 '21 at 10:24
  • 1) Add all components. 2) Call `pack()`, ***then*** 3) `frame.setVisible(true);`. As to the problem at hand, it sounds like a `JList` appropriately configured, would be the better approach. – Andrew Thompson Feb 05 '21 at 11:58
  • 1
    You could also use the [Wrap Layout](https://tips4java.wordpress.com/2008/11/06/wrap-layout/) which is an extension of FlowLayout that allows components to dynamically wrap to the next row. The issue with this approach is that each component is displayed at its preferred size so it may not be a true grid if components have different sizes. Using a JList will provide dynamic wrapping and all cells will be the same size. – camickr Feb 05 '21 at 15:24
  • Don't remove relevant tags added by others. The [tag:layout-manager] tag is a 'parent' tag of all Java layouts (they all implement the layout manager interface). It's the same if they're inbuilt layouts or from 3rd parties. – Andrew Thompson Feb 21 '21 at 10:38

1 Answers1

3

I want to place buttons as grid but it places horizontally.

That's because you do not set the preferred size of the JPanel and because you add the JPanel to a JScrollPane you are effectively giving the JPanel infinite width and FlowLayout will lay out all its components in a single row until it reaches the width limit of the JPanel but because the width is infinite, all the JButtons appear on the same line. Also, because you set the horizontal scrollbar policy to NEVER, there is no way to scroll the JPanel.

You should call method setVisible(true) after you have added all the components.
Note that in the below code I use GridLayout rather than FlowLayout because FlowLayout will not display a grid of JButton. Also note that I call method pack() rather than method setSize().

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Test {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(0, 10, 5, 5));

        JScrollPane pane = new JScrollPane(panel);
        pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        for (int i=0;i<100;i++){
            panel.add(new JButton("Label"));
        }
        frame.add(pane);
        frame.pack();
        frame.setVisible(true);
    }
}

Here is a screen capture:

enter image description here

Note that, by default, JScrollPane will size itself so as to display all the JButtons. If you want the JScrollPane to only display a few rows, then you need to set its preferred size, for example

pane.setPreferredSize(new Dimension(710, 150));

EDIT

If you insist on using FlowLayout then you need to set the preferred size for both the JPanel and the JScrollPane.

import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Test {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(710, 315));
        panel.setLayout(new FlowLayout(FlowLayout.LEFT));
        for (int i = 0; i < 100; i++) {
            panel.add(new JButton("Label"));
        }

        JScrollPane pane = new JScrollPane(panel);
        pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        pane.setPreferredSize(new Dimension(720, 160));

        frame.add(pane);
        frame.pack();
        frame.setVisible(true);
    }
}

Here is a screen capture.

another screen capture

Abra
  • 19,142
  • 7
  • 29
  • 41