Dynamically Resize a JScrollPane?

Nyx picture Nyx · Jun 5, 2011 · Viewed 30.9k times · Source

I Have two files. One extends JFrame, and another Extends JPanel. Whenever I change the size of the frame, whether it be maximizing, dragging, whatever, i want the ScrollPane to fit itself to the current size of the frame. There's more to it, there's a top menubar and a bottom bar as well, but i left those out for simplicity.

Essentially, i want it to work like notepad.

right now, I use a ComponentListener on the frame that calls a setSize method in the the other class. The setSize method is just:

public void resize(int x, int y)
{
textA.setPreferredSize(new Dimension(x, y-50));

areaScrollPane.setPreferredSize(new Dimension(x,y-50));
}

also, for reference:

public void componentResized(ComponentEvent e)
 {
     textA.resize(panel.getWidth(),panel.getHeight());
  }

FYI, it extends JPanel because of the way I add it to the frame:

panel = (JPanel) this.getContentPane();
panel.setLayout(new BorderLayout());
panel.add(textA, BorderLayout.CENTER);

so what's the best way to do this? Thanks!

Edit: Here's the scrollpane file. It's called textA in my main.

    public class TextArea extends JPanel
    {

    JTextArea textA=new JTextArea(500,500);

    JScrollPane areaScrollPane = new JScrollPane(textA);
    Toolkit toolkit =  Toolkit.getDefaultToolkit ();
    Dimension dim = toolkit.getScreenSize();
    Dimension dim2=(new Dimension((int)(dim.getWidth()),(int)(dim.getHeight()-120)));
    public TextArea()
    {
        //textA.setLineWrap(true);
        //textA.setWrapStyleWord(true);
        textA.setEditable(true);
        textA.setForeground(Color.WHITE);

        textA.setBackground(Color.DARK_GRAY);
        this.setFont(null);



        areaScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        areaScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        areaScrollPane.setMinimumSize(new Dimension(300,300));
        areaScrollPane.setSize(new Dimension(800,800));
        textA.setPreferredSize(dim2);
        areaScrollPane.setPreferredSize(dim2);
        areaScrollPane.setMaximumSize(dim2);
        add(areaScrollPane);
     }


    @Override
    public void resize(int x, int y)
    {
    textA.setPreferredSize(new Dimension(x, y-50));
    areaScrollPane.setPreferredSize(new Dimension(x,y-50));
    }

    }

and the main:

    public class JEdit extends JFrame implements ComponentListener

    {
    TextArea textA=new TextArea();
    JPanel panel;
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {

       JEdit run=new JEdit();

    }

    public JEdit()
    {

        setTitle("JEdit");
        setLayout(new BorderLayout());
        setSize(1100, 1000);

        this.setMinimumSize(new Dimension(100,100));
        //setBackground(Color.BLACK);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException ex) {
           System.out.println("error1");
        } catch (InstantiationException ex) {
            System.out.println("error2");
        } catch (IllegalAccessException ex) {
           System.out.println("error3");
        } catch (UnsupportedLookAndFeelException ex) {
            System.out.println("error4");
        }

         panel = (JPanel) this.getContentPane();
         panel.setLayout(new BorderLayout());
         //TopBar top=new TopBar();
        // PositionBar posB=new PositionBar();
         panel.add(textA, BorderLayout.CENTER);




       // add(top,BorderLayout.NORTH);
       // add(posB,BorderLayout.SOUTH);




        addComponentListener(this);
        setVisible(true);

    }



    public void componentResized(ComponentEvent e)
    {
         textA.resize(panel.getWidth(),panel.getHeight());
    }

    public void componentMoved(ComponentEvent e) {
    textA.resize(panel.getWidth(),panel.getHeight());
    }

    public void componentShown(ComponentEvent e) {
    textA.resize(panel.getWidth(),panel.getHeight());
    }

    public void componentHidden(ComponentEvent e) {
         textA.resize(panel.getWidth(),panel.getHeight());
    }



    }

Answer

Hovercraft Full Of Eels picture Hovercraft Full Of Eels · Jun 5, 2011

Regarding the code you've posted, for one get rid of all calls to setSize -- these are generally not honored when using layout managers and get rid of all of your ComponentListener stuff as it's superfluous since you are using layout managers to resize things. The biggest problem I see though is that your allow your TextArea JPanel to use its default layout, which is FlowLayout, and doing so will prevent the JScrollPane that it holds from resizing. Give this class a BorderLayout (or better simply return a JScrollPane from the class), and you're set. e.g. with quick modifications and with renaming of classes to prevent clashes with the standard Java classes,

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

@SuppressWarnings("serial")
public class JEdit2 extends JFrame  {
   TextArea2 textA = new TextArea2();
   JPanel panel;

   public static void main(String[] args) {
      new JEdit2();
   }

   public JEdit2() {
      setTitle("JEdit 2");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      panel = (JPanel) this.getContentPane();
      panel.add(textA, BorderLayout.CENTER);

      pack(); //!! added
      setLocationRelativeTo(null);
      setVisible(true);
   }

}

@SuppressWarnings("serial")
class TextArea2 extends JPanel {
   JTextArea textA = new JTextArea(500, 500); // !! this is one friggin' huge JTextArea!
   JScrollPane areaScrollPane = new JScrollPane(textA);

   public TextArea2() {
      textA.setEditable(true);
      textA.setForeground(Color.WHITE);
      textA.setBackground(Color.DARK_GRAY);
      this.setFont(null);

      setLayout(new BorderLayout()); //!! added
      add(areaScrollPane, BorderLayout.CENTER);
   }
}