Search code examples
javaswinglayoutjtextareajdialog

How to force JContainer to re-layout itself?


I have JFrame with BorderLayout: JTextArea in the NORTH and JButton in the SOUTH. I pack() it in the beginning.

My code changes font size for the text area. How do I force the dialog window and its components to re-layout itself?

So far I tried some combinations of:

  • another pack()
  • repaint()
  • revalidate()

It does not seem to help.

Is there a guaranteed brute force approach? What is the proper way to achieve such result?

UPDATE:

While creating SCCE (see below) I found two mistakes in my original code and fixed them. The frame is re-sizing nicely now.

I still have a question whether this is the proper way to do it.

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

public class MyFrame extends JFrame implements ActionListener{

    private JTextArea txt;
    private JButton bis;
    private JFrame frame;

    int size = 10;

    private void BuildMainGUI() {
        txt = new JTextArea("This is just a line of text");
        bis = new JButton("Increase size");

        JPanel p1 = new JPanel();
        bis.addActionListener(this);

        BorderLayout bl = new BorderLayout();

        p1.setLayout(bl);
        p1.add(txt, BorderLayout.NORTH);
        p1.add(bis, BorderLayout.SOUTH);

        frame = new JFrame();
        frame.setContentPane(p1);
        frame.setVisible(true);
        frame.pack();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        size += 2;
        Font newFont = new Font("Courier", Font.PLAIN, size);
        txt.setFont(newFont);
        frame.revalidate();
        frame.pack();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        MyFrame myGUI = new MyFrame(); 
        myGUI.BuildMainGUI();
    }
}

Solution

  • all three alternativer are described in ActionListener, lets work easiest of them, seems like is coordinates is the same (I think that required deepest look into TextLayout ???)

    enter image description here enter image description here

    import java.awt.BorderLayout;
    import java.awt.Font;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.SwingUtilities;
    
    public class ResizeJTextArea {
    
        private JFrame frame = new JFrame();
        private JScrollPane scrollPane = new JScrollPane();
        private JTextArea textArea = new JTextArea(10, 15);
        private JButton button = new JButton("change");
        private Font newFont = new Font("Courier", Font.PLAIN, 10);
    
        public ResizeJTextArea() {
            textArea.setText("This is just a line of text");
            textArea.setFont(newFont);
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    textArea.setFont(textArea.getFont().deriveFont(20f));
    
                    //2. choice
                    //textArea.setColumns(20);
                    //textArea.setRows(20);
    
                    //3rd. coice
                    //override PreferredScrollableViewportSize
                    frame.pack();
                }
            });
            scrollPane.setViewportView(textArea);
            frame.add(scrollPane);
            frame.add(button, BorderLayout.SOUTH);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocation(100, 100);
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    ResizeJTextArea fs = new ResizeJTextArea();
                }
            });
        }
    }