Question

How do you set the size of a container which contains a JScrollPane so that the scrollbar does not appear?

Consider this SSCCE (using MigLayout):

public static void main(String[] args) {

    JPanel panel = new JPanel(new MigLayout());

    for(int i = 0; i < 15; i++) {
        JTextArea textArea = new JTextArea();
        textArea.setColumns(20);
        textArea.setRows(5);
        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);
        JScrollPane jsp = new JScrollPane(textArea);

        panel.add(new JLabel("Notes" + i));
        panel.add(jsp, "span, grow");
    }
    JScrollPane jsp = new JScrollPane(panel);


    JFrame frame = new JFrame();
    frame.add(jsp);
    frame.pack();
    frame.setSize(jsp.getViewport().getViewSize().width, 500);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

As you can see, I'm trying to figure out what to put on this line:

frame.setSize(jsp.getViewport().getViewSize().width, 500);

The goal is to set the width with respect to the contents of the viewport so that the horizontal scroll bar is not needed.

enter image description here

should be:

enter image description here

EDIT: Following camikr's advice, this is the result:

public static final int pref_height = 500;
public static void main(String[] args) {

    JPanel panel = new JPanel(new MigLayout());

    for(int i = 0; i < 15; i++) {
        JTextArea textArea = new JTextArea();
        textArea.setColumns(20);
        textArea.setRows(5);
        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);
        JScrollPane jsp = new JScrollPane(textArea);

        panel.add(new JLabel("Notes" + i));
        panel.add(jsp, "span, grow");
    }
    JScrollPane jsp = new JScrollPane(panel) {
        @Override
        public Dimension getPreferredSize() {
            setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            Dimension dim = new Dimension(super.getPreferredSize().width + getVerticalScrollBar().getSize().width, pref_height);
            setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
            return dim;
        }
    };


    JFrame frame = new JFrame();
    frame.add(jsp);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

Seems a little hackish to me, but it works.

Was it helpful?

Solution

As you can see, I'm trying to figure out what to put on this line:

Don't put anything. You should not be attempting to manage the size of the frame. For example, your code doesn't even consider the Borders of the frame. If anything your code would be changed to use the width of the frame, not the scrollpane.

The better solution is to override the getPreferredSize() method of the scroll pane to return the width of super.getPreferredSize() and then specify a reasonable height. You would need to make sure the vertical scrollbar is always visible for the calculation to work.

Then the pack() method will work as expected.

OTHER TIPS

Same thing for the horizontal case:

new JScrollPane(panel) {
    public Dimension getPreferredSize() {
      Component view = getViewport().getView();
      if (view == null) return super.getPreferredSize();
      int pref_width = view.getPreferredSize().width;
      setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
      Dimension dim = new Dimension(pref_width, super.getPreferredSize().height + getHorizontalScrollBar().getSize().height);
      setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
      return dim;
    }
}

Also it adapts properly should you switch out the view inside the scrollpane later.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top