Search code examples
javaswinglayout-managerboxlayout

Understanding BoxLayout


Could you help me understand BoxLayout. I want to organize something like that from javadoc for BoxLayout

please, have a look at the picture

enter image description here

Well, two rectangle panels were pictured Ok. But adding the first square brings about something unexpected by me. The first panel becomes longer by the side of the square. Adding another square ruins the picture even more. Well, adding the third square gives this picture. The frame is stretched manually to the full screen whereas initially the picture was supposed to ocupy only 600 x 600. If I don't stretch the window, the first panel occupies the whole space from top to bottom ane exhibits one and a half squares.

Could you help me understand what should I do to get the desired result?

public class View extends JFrame {
    public View(){
        this.setPreferredSize(new Dimension(600, 600));
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.pack();

        // LayoutManager for the whole frame.
        this.setLayout(new BoxLayout(this.getContentPane(), BoxLayout.X_AXIS));


        JPanel firstPanel = getPanel(200, 400);

        JPanel squareOne = getPanel(100, 100);
        JPanel squareTwo = getPanel(100, 100);
        JPanel squareThree = getPanel(100, 100);

        //firstPanel.add(Box.createVerticalGlue());
        firstPanel.add(squareOne);
        //firstPanel.add(Box.createVerticalGlue());
        firstPanel.add(squareTwo);
        //firstPanel.add(Box.createVerticalGlue());
        firstPanel.add(squareThree);
        //firstPanel.add(Box.createVerticalGlue());


        JPanel secondPanel = getPanel(200, 400);


        this.add(Box.createHorizontalGlue());
        this.add(firstPanel);
        this.add(Box.createHorizontalGlue());
        this.add(secondPanel);
        this.add(Box.createHorizontalGlue());

        this.setVisible(true);
    }

    private JPanel getPanel(int width, int height) {
        Border border = BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.RED, Color.BLACK);
        JPanel panel = new JPanel();
        panel.add(Box.createRigidArea(new Dimension(width, height)));
        panel.setBorder(border);
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        return panel;
    }
}

ADDED LATER:

I changed the code like below. The picture has not changed.

public class View extends JFrame {
    public View(){
        this.setPreferredSize(new Dimension(600, 600));
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.pack();

        // LayoutManager for the whole frame.
        this.setLayout(new BoxLayout(this.getContentPane(), BoxLayout.X_AXIS));


        MyPanel firstPanel = getPanel(200, 400);

        MyPanel squareOne = getPanel(100, 100);
        MyPanel squareTwo = getPanel(100, 100);
        MyPanel squareThree = getPanel(100, 100);

        //firstPanel.add(Box.createVerticalGlue());
        firstPanel.add(squareOne);
        firstPanel.add(Box.createVerticalGlue());
        firstPanel.add(squareTwo);
        firstPanel.add(Box.createVerticalGlue());
        firstPanel.add(squareThree);
        firstPanel.add(Box.createVerticalGlue());


        MyPanel secondPanel = getPanel(200, 400);


        this.add(Box.createHorizontalGlue());
        this.add(firstPanel);
        this.add(Box.createHorizontalGlue());
        this.add(secondPanel);
        this.add(Box.createHorizontalGlue());
//
        this.setVisible(true);
    }

    private class MyPanel extends JPanel{
        int width;
        int height;
        public MyPanel(int width, int height){
            this.width = width;
            this.height = height;
        }
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(width, height);
        }
    }
    private MyPanel getPanel(int width, int height) {
        Border border = BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.RED, Color.BLACK);
        MyPanel panel = new MyPanel(width, height);
        panel.add(Box.createRigidArea(new Dimension(width, height)));
        panel.setBorder(border);
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        return panel;
    }
}

Solution

  • Override getPreferredSize() to set the preferred size of the JPanel if needed.

    JPanel panel =  new JPanel() {
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(..., ...);
        }
    };
    

    Read more Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?