2

I have a JPanel with FlowLayout that I'm dynamically filling with identical components (JButtons in the MWE). The JPanel is inside a JScrollPane. As I add components, I'd like them to fill left to right, kicking down to the next row once the top row would become wider than the JScrollPane.

My problem is that FlowLayout is instead widening the JPanel ad nauseum, to which the JScrollPane responds by adding a horizontal scroll. How do I prevent this?

Edit: I've seen WrapLayout; I was hoping for a solution within standard Java since I'm using NetBeans GUI Builder for my application.

MWE based on this answer:

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

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class MWE extends JFrame implements ActionListener {

    JPanel panel;
    JScrollPane pane;

    public MWE() {
        super("Add component on JFrame at runtime");
        setLayout(new BorderLayout());

        this.panel = new JPanel();
        this.pane = new JScrollPane();
        this.panel.setLayout(new FlowLayout(FlowLayout.LEFT));
        this.pane.setViewportView(this.panel);
        add(pane, BorderLayout.CENTER);

        JButton button = new JButton("CLICK HERE");
        add(button, BorderLayout.SOUTH);
        button.addActionListener(this);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(500, 500);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent evt) {
        this.panel.add(new JButton("Button"));
        this.panel.revalidate();
        validate();
    }

    public static void main(String[] args) {
        MWE mwe = new MWE();
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
LastStar007
  • 725
  • 1
  • 8
  • 21
  • This is not supported in the standard JDK layout managers. Check out: https://stackoverflow.com/questions/3592828/java-scrollpane-with-flowlayout/3592862#3592862 for one solution. – camickr Apr 19 '18 at 15:47
  • 1
    Well, that's horrifying. Oracle must really like horiscrolling. – LastStar007 Apr 19 '18 at 15:55
  • `I was hoping for a solution within standard Java since I'm using NetBeans GUI Builder` - using an IDE doesn't prevent you from using other classes. – camickr Apr 19 '18 at 23:03
  • I know, but the more I handwrite or use external libraries, the less I can take advantage of a visual GUI builder. – LastStar007 Apr 20 '18 at 09:22
  • You are thinking about it backwards. The IDE is controlling/limiting what you can do. If you ever move to a different idea you will need to learn the IDE all over again. It is better to learn how to use Java and how the IDE can help. IDE's are good for basic coding and debugging, but don't let it control how you design the application. – camickr Apr 20 '18 at 17:57

1 Answers1

-1

Try setting a preferred size for the panel :

this.panel.setPreferredSize(new Dimension(500, 500));
pikoute
  • 24
  • 2
  • 1
    (1-) then the preferred size never changes as your add/remove components or as the size of the frame changes. Setting the preferred size is the job of the layout manager. – camickr Apr 19 '18 at 18:30
  • @camickr have you tried it? because I did and the size changes when resizing the frame. It's just a workaround I'm sure there is a better way to do this. – pikoute Apr 19 '18 at 18:41
  • 1
    The issue is that the preferred size is not recalculated dynamically and whatever size you give is just a wild guess. The scrolling will only work until it doesn't because it is not based on the actual layout of the components. `I'm sure there is a better way to do this.` - see the link in my original comment. – camickr Apr 19 '18 at 20:41
  • 1
    I have already seen it, I added my answer since OP was looking for something within the standard java. Thanks anyway! – pikoute Apr 19 '18 at 21:48
  • 2
    It doesn't fix the problem. Maybe you still don't understand the problem?. Change your suggestion to use a preferred size of (200, 110) and use pack() on the frame instead of setSize(). Now when you click the button the buttons will wrap at 2 on a line, which works great for the first 6 buttons. Then try adding the 7th. You will only see half of the 7th button and no scrollbars appear. The only way to see the button is to resize the frame. The point of a JScrollPane is the scrollbars should appear when required. This logic is dependent on a dynamic preferred size calculation. – camickr Apr 19 '18 at 22:46