Search code examples
javaswinglayout-managerboxlayout

GUI, BoxLayout adding a panel


Studying BoxLayout and GUI in general. I want to place a panel on a frame. Later I'll add an identical panel and will test BoxLaoyout. But I can't understand why this code produces not a panel sized 200x400 but just a red point in the middle of the left side of the frame (with coordinates about (300,0)).

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

        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));

        Border border = BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.RED, Color.BLACK);

        JPanel p1 = new JPanel();
        p1.setSize(200, 400);
        p1.setBorder(border);
        p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));


        panel.add(p1);

        this.add(panel);
        this.setVisible(true);
    }

}

Solution

  • The layout manager (BoxLayout) is using the preferred size of the components of the container it is managing. By default, the preferred size of a empty JPanel is 0x0, adding in the border has produced a preferred size closer to 2x2

    When using layout managers, calling setSize is meaningless, as the layout manager will override anything you specify when the container is revalidate

    Updated

    It would appear that the combination of both BoxLayouts seems to be playing against you. If I remove the second BoxLayout from p1, it seems to work okay.

    Also, BoxLayout seems to want to work with the maximum size of the component...

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import javax.swing.BorderFactory;
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.WindowConstants;
    import javax.swing.border.BevelBorder;
    import javax.swing.border.Border;
    import javax.swing.border.LineBorder;
    
    public class View extends JFrame {
    
        public View() {
            this.setPreferredSize(new Dimension(600, 600));
            this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            this.pack();
    
            JPanel panel = new JPanel();
            panel.setBorder(new LineBorder(Color.BLUE));
            panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
    
            Border border = BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.RED, Color.BLACK);
    
            JPanel p1 = new JPanel() {
                public Dimension getMaximumSize() {
                    return new Dimension(200, 400);
                }
            };
            p1.setBorder(border);
            p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));
    
            panel.add(p1);
    
            this.add(panel);
            this.setVisible(true);
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new View();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    }