Layouts - Part 3 - BoxLayout

The Box Layout is a jack of all trades. You can stack your widgets on top of each other...

Picture of Labels

...or align them side-to-side.

Picture of Labels

Along with the alignment, there are three techniques to assist you in placement of widgets in a BoxLayout.

1) You can place a rigid area to force a space between widgets. Obviously, the space will stay the same no matter how the window is resized.
2) You can also use 'glue' to place a stretchy space between the widgets. These spaces will expand and retract in relation to the size of the window.
3) You can create a special rigid area called a Filler to keep the GUI from becoming too small without re-sizing all your widgets.

To give an example of each of these and how to set up a BoxLayout, we'll go back to our JPanel example of the coloured panels. We've taken out the titles and added a few additional panels to let you see all the different ways of spacing the panels. Bear in mind, this is all done on the horizontal but the same can be done on the vertical too.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import javax.swing.*;
import java.awt.*;
import java.awt.Color;

public class BoxLayoutExample{

    public JPanel createContentPane (){

        // We create a bottom JPanel to place everything on.
        JPanel totalGUI = new JPanel();
        
        // We set the layout of the main JPanel to be BoxLayout.
        // LINE_AXIS sets them left to right, PAGE_AXIS sets them
        // from top to bottom.
        totalGUI.setLayout(new BoxLayout(totalGUI, BoxLayout.LINE_AXIS));

        JPanel redPanel = new JPanel();
        redPanel.setBackground(Color.red);
        redPanel.setMinimumSize(new Dimension(50, 50));
        redPanel.setPreferredSize(new Dimension(50, 50));
        totalGUI.add(redPanel);
        
        // This is the first spacer. This creates a spacer 10px wide that 
        // will never get bigger or smaller.
        totalGUI.add(Box.createRigidArea(new Dimension(10,0)));

        JPanel yellowPanel = new JPanel();
        yellowPanel.setBackground(Color.yellow);
        yellowPanel.setPreferredSize(new Dimension(50, 50));
        totalGUI.add(yellowPanel);

        // This spacer takes any spare space and places it as part of the spacer
        // If you drag the window wider, the space will get wider.
        totalGUI.add(Box.createHorizontalGlue());

        JPanel greenPanel = new JPanel();
        greenPanel.setBackground(Color.green);
        greenPanel.setPreferredSize(new Dimension(50, 50));
        totalGUI.add(greenPanel);
        
        // This spacer is a custom spacer.
        // The minimum size acts like a rigid area that 
        // will not get any smaller than 10 pixels on the x-axis (horizontal)
        // and not get any smaller than 50 pixels on the y axis (vertical).
        // The way the maximum size is set up means the spacer acts like glue
        // and will expand to fit the available space.
        
        Dimension minSize = new Dimension(10, 50);
        Dimension prefSize = new Dimension(10, 50);
        Dimension maxSize = new Dimension(Short.MAX_VALUE, 50);
        totalGUI.add(new Box.Filler(minSize, prefSize, maxSize));

        JPanel bluePanel = new JPanel();
        bluePanel.setBackground(Color.blue);
        bluePanel.setPreferredSize(new Dimension(50, 50));
        totalGUI.add(bluePanel);
        
        totalGUI.setOpaque(true);
        return totalGUI;
    }

    private static void createAndShowGUI() {

        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("[=] BoxLayout Demonstration! [=]");

        //Create and set up the content pane.
        BoxLayoutExample demo = new BoxLayoutExample();
        frame.setContentPane(demo.createContentPane());
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
There are very few new bits of code, but lets go through the changes.
15
        totalGUI.setLayout(new BoxLayout(totalGUI, BoxLayout.LINE_AXIS));
We set the layout to be a BoxLayout. There are two arguments. The first one is the name of the container we will be setting the BoxLayout to. If we were to use a JPanel called say "innerPanel", it would initialised as innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.LINE_AXIS));

The second argument describes how the widgets are inserted...if you use LINE_AXIS you enter them one after another, left-to-right. If you use PAGE_AXIS, the widgets are entered one below another from top to bottom.

All three of the spacers are demonstrated within this demo. The first one is the rigid area between the red and yellow panels.
25
        totalGUI.add(Box.createRigidArea(new Dimension(10,0)));
This creates a spacer of 10px on the x axis and 0px on the y axis. When you run the program and re-size the window, the space between the red and yellow panels will never change. This is the rigid spacer.

The second spacer is the glue spacer between the yellow and green panel.
34
        totalGUI.add(Box.createHorizontalGlue());
As you can see, you do not need to enter any sizes. This spacer simply uses up any spare space you have in the GUI as a spacer. If you make the window bigger, the spacer becomes bigger. If you squeeze the GUI smaller, the spacer will go smaller until it disappears.

The third spacer is a custom spacer, between the green and blue panel.
48
49
50
51
        Dimension minSize = new Dimension(10, 50);
        Dimension prefSize = new Dimension(10, 50);
        Dimension maxSize = new Dimension(Short.MAX_VALUE, 50);
        totalGUI.add(new Box.Filler(minSize, prefSize, maxSize));
We generate the minimum, preferred and maximum sizes of the spacer. The minimum size is 10 by 50px, so the frame will never be able to go smaller than 50 pixels on the vertical and the space will never shrink to under 10 pixels on the horizontal.
The preferred size is simply a size that you would want the space to start as before the screen is re-sized.
The maximum size is, as you may have guessed, the largest size the widget can go to. By using the variable Short.MAX_VALUE, the maximum is not constant so the spacer acts like a glue spacer on the horizontal.
On the vertical, we have set a specific amount, 50 pixels. This does not prevent the frame from getting bigger than 50 pixels, but it does stop the spacer from getting any larger if the frame is re-sized.

One final thing to note is the frame.pack(); command we now use. This sizes the frame so that most if not all the widgets are at their preferred sizes on start-up.
72
        frame.pack();
You should now compile and run the program. It should look like this.

Normal BoxLayout

Currently we can see the spacer between red and yellow because it is a rigid space, and the space between the green and blue panels because it has a minimum size set. There is currently no space between yellow and green because the frame has no 'left-over' space on the horizontal to put there.

Re-size the frame and make it larger on the horizontal. (by grabbing the right-hand side of the frame and dragging it out)

Long Horizontal BoxLayout

You will notice the space between the red and yellow stays the same. There is now a space between the yellow and green panels, and this space will increase depending on how wide you make the frame. The space between green and blue has done the exact same.

Re-size the frame on the vertical to make it larger.

Long Vertical BoxLayout

You will notice that not much changes apart from the widgets being dragged over the whole length. Unless you specify a maximum height, widgets will be stretched when the frame is stretched.

Attempt to make the frame as small as possible.

Tiny BoxLayout

You will notice that because of our custom widget, the frame will not go smaller than 50 pixels on the vertical. Also, the red panel will not go smaller than 50 pixels on the horizontal due to the minimum size we have put on it. The spacer between the red panel and yellow panel stays there because it is rigid and the spacer between yellow and green has disappeared again.

With proper use of these spacers, you can make your GUI very flexible with different resolutions and frame sizes.

The BoxLayout also comes with some methods for alignment, to help with aligning the widgets in the layout automatically.

To demonstrate this, we shall take the previous example and edit it slightly to restrict each coloured panel to have different sizes going from a small box to a big box.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import javax.swing.*;
import java.awt.*;
import java.awt.Color;

public class BoxLayoutExample_Extended{

    public JPanel createContentPane (){

        // We create a bottom JPanel to place everything on.
        // We set the layout of the main JPanel to be BoxLayout.
        // LINE_AXIS sets them left to right, PAGE_AXIS sets them
        // from top to bottom.
        JPanel totalGUI = new JPanel();
        totalGUI.setLayout(new BoxLayout(totalGUI, BoxLayout.LINE_AXIS));

        JPanel redPanel = new JPanel();
        redPanel.setBackground(Color.red);
        redPanel.setMinimumSize(new Dimension(40, 40));
        redPanel.setMaximumSize(new Dimension(40, 40));
        redPanel.setPreferredSize(new Dimension(40, 40));
        totalGUI.add(redPanel);

        // This is the first spacer. This creates a spacer 10px wide that
        // will never get bigger or smaller.
        totalGUI.add(Box.createRigidArea(new Dimension(10,0)));

        JPanel yellowPanel = new JPanel();
        yellowPanel.setBackground(Color.yellow);
        yellowPanel.setMinimumSize(new Dimension(60, 60));
        yellowPanel.setMaximumSize(new Dimension(60, 60));
        yellowPanel.setPreferredSize(new Dimension(60, 60));
        totalGUI.add(yellowPanel);

        // This spacer takes any spare space and places it as part of the spacer
        // If you drag the window wider, the space will get wider.
        totalGUI.add(Box.createHorizontalGlue());

        JPanel greenPanel = new JPanel();
        greenPanel.setBackground(Color.green);
        greenPanel.setMinimumSize(new Dimension(80, 80));
        greenPanel.setMaximumSize(new Dimension(80, 80));
        greenPanel.setPreferredSize(new Dimension(80, 80));
        totalGUI.add(greenPanel);

        // This spacer is a custom spacer.
        // The minimum size acts like a rigid area that
        // will not get any smaller than 10 pixels on the x-axis (horizontal)
        // and not get any smaller than 50 pixels on the y axis (vertical).
        // The way the maximum size is set up means the spacer acts like glue
        // and will expand to fit the available space.

        Dimension minSize = new Dimension(10, 50);
        Dimension prefSize = new Dimension(10, 50);
        Dimension maxSize = new Dimension(Short.MAX_VALUE, 50);
        totalGUI.add(new Box.Filler(minSize, prefSize, maxSize));

        JPanel bluePanel = new JPanel();
        bluePanel.setBackground(Color.blue);
        bluePanel.setMinimumSize(new Dimension(100, 100));
        bluePanel.setMaximumSize(new Dimension(100, 100));
        bluePanel.setPreferredSize(new Dimension(100, 100));
        totalGUI.add(bluePanel);
        
        totalGUI.setOpaque(true);
        return totalGUI;
    }

    private static void createAndShowGUI() {

        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("[=] BoxLayout Exercises [=]");

        BoxLayoutExample_Extended demo = new BoxLayoutExample_Extended();
        frame.setContentPane(demo.createContentPane());
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
Box Layout Example 1

By default the boxes are aligned by the centre spot of the Y-axis. However, if we don't want this, we can specify how the widgets are aligned with each other.

Exercises

Instead of the code for the alignment being given to you, try this yourself.

The code to align a widget with the next widget on the Y axis is .setAlignmentY().
There are three different arguments you can give this method to align the widgets in three different ways. Here's an example of how to put it in place.

21
        redPanel.setAlignmentY(Component.BOTTOM_ALIGNMENT);
Your exercise is to match the given code with the following pictures. There is the full code if you get stuck.

Position 1 - Full Code
Box Layout Example 1

Position 2 - Full Code
Box Layout Example 2

Position 3 - Full Code
Box Layout Example 3

Questions

BoxLayout questions...can you think outside the Box?

Question 1. When instantiating BoxLayout, what are the two arguments you pass in this example.

  • a) The size followed by the alignment.
  • b) The JPanel it is on followed by the size.
  • c) The JPanel it is on followed by the alignment.

Question 2. Which of these alignments does not exist?

  • a) BoxLayout.LINE_AXIS
  • b) BoxLayout.FRAME_AXIS
  • c) BoxLayout.PAGE_AXIS

Question 3. When using setAlignmentY(Component.BOTTOM_ALIGNMENT), how does the method place the widgets?

  • a) Aligns the bottom of Widget A with the bottom of Widget B.
  • b) Aligns the centre of Widget A with the bottom of Widget B.
  • c) Aligns the bottom of Widget A with the centre of Widget B.




That's it, you've mastered one of the most useful layout managers swing has. Although not specifically useful for an entire GUI, the BoxLayout is brilliant in a single panel that is part of a bigger GUI.

Back Top Next
Email Me
Code Style


Required Lessons

External Links

Created and Edited by Stuart Davidson
All Rights Reserved ©

Valid XHTML 1.0 Strict