How to get a JScrollPane to resize with its parent

2019-08-12 15:33发布

My question is similar to this one (How to get JScrollPanes within a JScrollPane to follow parent's resizing), but that question wasn't clear and the answer there didn't help me..

I have this SSCCE (using MigLayout):

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

    JPanel innerPanel = new JPanel(new MigLayout());
    innerPanel.setBorder(new LineBorder(Color.YELLOW, 5));

    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);

        innerPanel.add(new JLabel("Notes" + i));
        innerPanel.add(jsp, "span, grow");
    }
    JScrollPane jsp = new JScrollPane(innerPanel) {
        @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;
        }
    };
    jsp.setBorder(new LineBorder(Color.green, 5));

    JPanel outerPanel = new JPanel();
    outerPanel.setBorder(new LineBorder(Color.RED, 5));
    outerPanel.add(jsp);

    JFrame frame = new JFrame();

    JDesktopPane jdp = new JDesktopPane();
    frame.add(jdp);
    jdp.setPreferredSize(new Dimension(800, 600));
    frame.pack();

    JInternalFrame jif = new JInternalFrame("Title", true, true, true, true);
    jif.pack();
    jif.add(outerPanel);

    jdp.add(jif);
    jif.pack();
    jif.setVisible(true);


    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

I want the JScrollPane to resize whenever the parent JPanel is resized. Basically, I want the green border to line up with the red border. Right now, the green border stays the same size no matter the red border (unless you resize too small).

2条回答
爷、活的狠高调
2楼-- · 2019-08-12 16:02

I noticed this did not have an answer that uses the original layout so here is one.

In order to make the JScrollPane resize when the parent JPanel is resized you need to do two things.

1) Set the layout of the panel to grow. This can be using the following code.

new MigLayout("",  //Layout Constraints
    "grow",        //Column Constraints
    "grow");       //Row Constraints

2) Set the component to grow. This is as simple as adding an extra argument in the add() function.

add(jsp, "grow");

Extra
In order to make the JTextArea column grow when you resize the JScrollPane you can change the layout to only make the second column change. For example

new MigLayout("",                        //Layout Constraints
    "[/*Column 1*/][grow /*Column 2*/]", //Column Constraints
    "");                                 //Row Constraints

Also, I would recommend you use wrap instead of span to use the next row as span refers using so many columns. For example span 2 //Means use 2 columns for this component. This would mean when you add your jsp to innerPanel it would become

innerPanel.add(jsp, "wrap, grow");

Edited SSSCE

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import net.miginfocom.swing.MigLayout;

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

        JPanel innerPanel = new JPanel(new MigLayout("", "[][grow]", ""));
        innerPanel.setBorder(new LineBorder(Color.YELLOW, 5));

        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);

            innerPanel.add(new JLabel("Notes" + i));
            innerPanel.add(jsp, "wrap, grow");
        }
        JScrollPane jsp = new JScrollPane(innerPanel) {
            @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;
            }
        };
        jsp.setBorder(new LineBorder(Color.green, 5));

        JPanel outerPanel = new JPanel(new MigLayout("", "grow", "grow"));
        outerPanel.setBorder(new LineBorder(Color.RED, 5));
        outerPanel.add(jsp, "grow");

        JFrame frame = new JFrame();

        JDesktopPane jdp = new JDesktopPane();
        frame.add(jdp);
        jdp.setPreferredSize(new Dimension(800, 600));
        frame.pack();

        JInternalFrame jif = new JInternalFrame("Title", true, true, true, true);
        jif.pack();
        jif.add(outerPanel);

        jdp.add(jif);
        jif.pack();
        jif.setVisible(true);


        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
查看更多
唯我独甜
3楼-- · 2019-08-12 16:03
JPanel outerPanel = new JPanel();

A JPanel uses a FlowLayout by default which always respects the size of the component added to it. As a guess, maybe you can use:

JPanel outerPanel = new JPanel( new BorderLayout() );

A BorderLayout give all the space available to the component added to the panel. By default a JInternalFrame also uses a BorderLayout. So since all the parent components of your scroll pane use a BorderLayout all the space should go to the scroll pane.

When you post a SSCCE you should post code using classes from the JDK that simulates your problem so that everybody can test your SSCCE.

查看更多
登录 后发表回答