Home > front end >  How do I dynamically resize a JFrame based on its components (a JPanel)
How do I dynamically resize a JFrame based on its components (a JPanel)

Time:11-07

So basically my gui is like this:

Frame that contains a Free Designed layout JPanel called mainPanel

Inside mainPanel are 2 other panels:

A) toolPanel of layout BoxLayout

B) gamePanelof layout GridLayout

This is the significant bits of the code:

public Normalv3() {
        initComponents();
        importBombs();
    }
    
    public void importBombs(){
        
        rows = Minesweeper.rows;
        columns = Minesweeper.columns;
        total = rows*columns;
        bombsIndexes = new ArrayList<Integer>(Minesweeper.totalBombs);
        gamePanel.setLayout(new java.awt.GridLayout(rows,columns)); //Creating a new grid layout and putting it inside the old layout
        
        
        ////
        Random ran = new Random();
        int low=1;
        int high=rows*columns;
        int ranValue;
        for (int i = 0 ; i< Minesweeper.totalBombs;i  ){
            ranValue = ran.nextInt(high - low) low;
        
            if(bombsIndexes.contains(ranValue)){
                i--;
                continue;
            }
        
        bombsIndexes.add(ranValue);
        }
        ////
        
        for (int i = 1; i <= total ; i  ){
            btnMines b = new btnMines(i);
            if(bombsIndexes.contains(i)){     
                b.isBomb = true;
                b.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minesweeper/resources/bomb.png")));
            }
            b.setPreferredSize(new Dimension(20,20));
            
            gamePanel.add(b);
        }
        this.setResizable(false);
        this.setTitle("Minesweeper");
        this.pack();//sizes frame so that all components are at their preferred sizes
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.validate(); //recalculate layout
        this.setVisible(true);
    }

The problem is when I increase the number of columns, the width of either the gamePanel or mainPanel increases but the width of the frame does not.

Example:

enter image description here

How do I change the size of the frame to resize itself based on the panel sizes?

Note: btnMines is basically just a JButton with some variables attached to it.

Bonus question: how would I go about making each button into squares? As you can see I tried making it square by writing b.setPreferredSize(new Dimension(20,20)); but each resulting button are still rectangles!!

Please help!

Also, I know the code is messy. I used to separate that function into separate functions but now I decided to put it all in 1 function just to test it out properly.

Thank you!

I tried adding:

this.setResizable(false);
        this.setTitle("Minesweeper");
        this.pack();//sizes frame so that all components are at their preferred sizes
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.validate(); //recalculate layout
        this.setVisible(true);

But it didnt work since the frame didnt resize!

CodePudding user response:

Frame that contains a Free Designed layout JPanel called mainPanel

This seems to suggest that mainPanel might be using a null layout, which is going to cause you issues, but this is just a guess.

JFrame#pack should be wrapping the frame around the content based on the contents "preferred size" hints, provided via the subsequent layout managers, which is leads me to question what layout managers (if any) are involved in your design.

For example...

enter image description here

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

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

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new Normalv3(10, 10));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class Normalv3 extends JPanel {

        public Normalv3(int cols, int rows) {
            setLayout(new BorderLayout());
            add(makeControlsPane(), BorderLayout.NORTH);
            add(makeGamePane(cols, rows));
        }

        protected JPanel makeControlsPane() {
            JPanel pane = new JPanel(new FlowLayout(FlowLayout.LEADING));
            pane.add(new JButton("Back to Menu"));
            pane.add(new JButton("Reset"));
            return pane;
        }

        protected JPanel makeGamePane(int cols, int rows) {
            JPanel pane = new JPanel(new GridLayout(rows, cols));
            for (int index = 0; index < (cols * rows); index  ) {
                JButton btn = new SquareButton("*");
                pane.add(btn);
            }
            return pane;
        }
    }

    class SquareButton extends JButton {

        SquareButton(String s) {
            super(s);
        }

        @Override
        public Dimension getPreferredSize() {
            Dimension d = super.getPreferredSize();
            int s = (int) (d.getWidth() < d.getHeight() ? d.getHeight() : d.getWidth());
            return new Dimension(s, s);
        }
    }
}

Square button design take from Creating Square Buttons in Swing

As a side note - I'd encourage you NOTE to make use of form designers, they tend to become messy very quickly and are difficult to diagnose and maintain (IMHO)

  • Related