By Andrew Thompson


2013-07-26 06:50:12 8 Comments

A GUI with no white space appears 'crowded'. How can I provide white space without resorting to explicitly setting the position or size of components?­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

6 comments

@Luke Pasfield 2018-04-01 11:49:38

Whenever I have this issue, I just use JPanels. For example in a GridLayout:

JFrame frame = new JFrame;
frame.setLayout(new GridLayout(2, 0));

//We want the bottom left to be blank
frame.add(new JLabel("Top Left"));
frame.add(new JLabel("Top Right"));

//This is the position we want empty
frame.add(new JPanel());

//Now we can continue with the rest of the script

Hope this helped :)

@Andrew Thompson 2013-07-26 06:50:12

There are a number of ways in a Swing GUI to provide a separation between components, and white space around components:

But more generally, look to:

  • The spacing as can be defined in the layout constructors.
  • Borders.

Here is an example of using the layout separator hGap & vGap values & borders (specifically an EmptyBorder) to provide 'white' (actually shown as red to make it very obvious) space. Adjust the spinners to see the result.

With no GUI white space

With GUI white space

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

public class WhiteSpace {

    private JPanel gui = null;
    private BorderLayout mainLayout;
    private FlowLayout buttonLayout;
    private EmptyBorder border;

    public Container getGui() {
        if (gui==null) {
            mainLayout = new BorderLayout(0,0);
            gui = new JPanel(mainLayout);
            gui.setBackground(Color.RED);
            border = new EmptyBorder(0,0,0,0);

            JTree tree = new JTree();
            tree.setVisibleRowCount(10);
            for (int ii = tree.getRowCount(); ii>-1; ii--) {
                tree.expandRow(ii);
            }
            gui.add(new JScrollPane(
                    tree, 
                    JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                    JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), 
                    BorderLayout.LINE_START);
            gui.add(new JScrollPane(new JTextArea(10,30)));

            buttonLayout = new FlowLayout(FlowLayout.CENTER,0,0);
            JPanel buttonPanel = new JPanel(buttonLayout);
            gui.add(buttonPanel, BorderLayout.PAGE_START);

            buttonPanel.add(new JLabel("H Gap"));
            final JSpinner hSpinner = 
                    new JSpinner(new SpinnerNumberModel(0,0,15,1));
            buttonPanel.add(hSpinner);

            buttonPanel.add(new JLabel("V Gap"));
            final JSpinner vSpinner = 
                    new JSpinner(new SpinnerNumberModel(0,0,15,1));
            buttonPanel.add(vSpinner);

            buttonPanel.add(new JLabel("H Border"));
            final JSpinner hBorderSpinner = 
                    new JSpinner(new SpinnerNumberModel(0,0,15,1));
            buttonPanel.add(hBorderSpinner);

            buttonPanel.add(new JLabel("V Border"));
            final JSpinner vBorderSpinner = 
                    new JSpinner(new SpinnerNumberModel(0,0,15,1));
            buttonPanel.add(vBorderSpinner);

            ChangeListener changeListener = new ChangeListener() {

                @Override
                public void stateChanged(ChangeEvent e) {
                    int hGap = ((Integer)hSpinner.getValue()).intValue();
                    int vGap = ((Integer)vSpinner.getValue()).intValue();
                    int hBorder = ((Integer)hBorderSpinner.getValue()).intValue();
                    int vBorder = ((Integer)vBorderSpinner.getValue()).intValue();
                    adjustWhiteSpace(hGap,vGap,hBorder,vBorder);
                }
            };

            hSpinner.addChangeListener(changeListener);
            vSpinner.addChangeListener(changeListener);
            hBorderSpinner.addChangeListener(changeListener);
            vBorderSpinner.addChangeListener(changeListener);
        }

        return gui;
    }

    private void adjustWhiteSpace(int hGap, int vGap, int hBorder, int vBorder) {
        mainLayout.setHgap(hGap);
        mainLayout.setVgap(vGap);
        buttonLayout.setHgap(hGap);
        gui.setBorder(new EmptyBorder(vBorder,hBorder,vBorder,hBorder));
        Container c = gui.getTopLevelAncestor();
        if (c instanceof Window) {
            Window w = (Window)c;
            w.pack();
        }
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                WhiteSpace ws = new WhiteSpace();
                // the GUI as seen by the user (without frame)
                Container gui = ws.getGui();

                JFrame f = new JFrame("White (OK Red) Space");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See http://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.setResizable(false);
                f.pack();
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

@Jan Bodnar 2014-07-08 16:36:48

MigLayout has multiple ways of creating space. (A space is called a gap in this layout.) Gaps can be created at the highest level with layout constraints, it is possible to create gaps between rows and column and gaps can be also set between individual components with component constraints. There are also specific gaps around the borders of a container called insets which have their own specific keyword to be set.

The following example creates all these kinds of gaps:

package com.zetcode;

import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;


public class MigLayoutGaps2 extends JFrame {

    public MigLayoutGaps2() {

        initUI();

        setTitle("Gaps");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    private void initUI() {

        JPanel base = new JPanel(new MigLayout("flowy, ins 30, gap 15"));
        setContentPane(base);

        JPanel pnl1 = new JPanel();
        pnl1.setBorder(
                BorderFactory.createTitledBorder("Grid gaps")
        );

        pnl1.setLayout(new MigLayout("gap 5 5, ins 10, wrap 3"));

        pnl1.add(new JButton("1"));
        pnl1.add(new JButton("2"));
        pnl1.add(new JButton("3"));
        pnl1.add(new JButton("4"));
        pnl1.add(new JButton("5"));
        pnl1.add(new JButton("6"));

        JPanel pnl2 = new JPanel();
        pnl2.setBorder(
                BorderFactory.createTitledBorder("Column gaps")
        );

        pnl2.setLayout(new MigLayout("wrap 3", "[]10[]"));

        JLabel lbl1 = new JLabel();
        lbl1.setBorder(
            BorderFactory.createEtchedBorder()
        );

        JLabel lbl2 = new JLabel();
        lbl2.setBorder(
            BorderFactory.createEtchedBorder()
        );

        JLabel lbl3 = new JLabel();
        lbl3.setBorder(
            BorderFactory.createEtchedBorder()
        );        

        pnl2.add(lbl1, "w 40, h 110");
        pnl2.add(lbl2, "w 40, h 110");
        pnl2.add(lbl3, "w 40, h 110");

        JPanel pnl3 = new JPanel();
        pnl3.setBorder(
                BorderFactory.createTitledBorder("Row gaps")
        );

        pnl3.setLayout(new MigLayout("wrap", "", "[]15[]"));

        JLabel lbl4 = new JLabel();
        lbl4.setBorder(
            BorderFactory.createEtchedBorder()
        );

        JLabel lbl5 = new JLabel();
        lbl5.setBorder(
            BorderFactory.createEtchedBorder()
        );

        JLabel lbl6 = new JLabel();
        lbl6.setBorder(
            BorderFactory.createEtchedBorder()
        );        

        pnl3.add(lbl4, "w 150, h 20");
        pnl3.add(lbl5, "w 150, h 20");
        pnl3.add(lbl6, "w 150, h 20");        

        JPanel pnl4 = new JPanel();
        pnl4.setBorder(
                BorderFactory.createTitledBorder("Component gaps")
        );

        pnl4.setLayout(new MigLayout());

        pnl4.add(new JLabel("Name:"), "gapright 5");
        pnl4.add(new JTextField(10), "gapbottom 20, gaptop 20");

        base.add(pnl1);
        base.add(pnl2);
        base.add(pnl3);
        base.add(pnl4);

        pack();
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MigLayoutGaps2 ex = new MigLayoutGaps2();
                ex.setVisible(true);
            }
        });
    }
}

We have four panels in the layout. Each of this panels has a MigLayout manager.

JPanel base = new JPanel(new MigLayout("flowy, ins 30, gap 15"));

This line creates container insets and vertical gaps between panels.

pnl1.setLayout(new MigLayout("gap 5 5, ins 10, wrap 3"));

Here we apply gaps for the whole grid structure and also set container gaps.

pnl2.setLayout(new MigLayout("wrap 3", "[]10[]"));

This line creates gaps between columns.

pnl3.setLayout(new MigLayout("wrap", "", "[]15[]"));

Row gaps are defined with this code.

pnl4.add(new JLabel("Name:"), "gapright 5");
pnl4.add(new JTextField(10), "gapbottom 20, gaptop 20");

Finally, it is possible to create gaps between individual components.

Gaps

@javajon 2014-07-06 13:02:36

JGoodies FormLayout.

Author Karsten Lentzsch has a collection of presentations on UI design. In particular this PDF speaks to the need for aesthetic whitespace. Adding meaningful space while also paying attention to clutter separates the wheat from the chaff.

@Gearon 2014-03-20 06:23:45

When you use BoxLayout, Box.createVerticalGlue() method can help you to make some white space.

Another method is BorderFactory.createEmptyBorder(int top, int left, int bottom, int right). It can help you to make some white space around component.

Thanks for Andrew Thompson's remind.I've revised BoxLayout in recent days and I find that Box.createVerticalGlue() can add some white space depend on the panel's size and you can not set the explicit pixel value of the length of white space.But Box.createVerticalStrut() can do that. Here is a MCTaRE and show the effect of those two methods.

enter image description here

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

public class WhiteSpace extends JFrame{
    static WhiteSpace whiteSpace;
    DemoPanel demoPanel;
    boolean withGlue;
    JSpinner spinner;

    public WhiteSpace(){
        initialWindow();
        demoPanel = new DemoPanel();
        ActionPanel actionPanel = new ActionPanel();

        setLayout(new BorderLayout());

        getContentPane().add(actionPanel,BorderLayout.NORTH);
        getContentPane().add(demoPanel,BorderLayout.CENTER);
            setVisible(true);
    }

    public void initialWindow(){
        setSize(220, 300);
        setTitle("White Space");
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        //Show the window in the middle of the screen
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                whiteSpace = new WhiteSpace();
            }
        };
        SwingUtilities.invokeLater(runnable);
    }

    class DemoPanel extends JPanel{
        //Show the vertical white space between label1 and label2
        JLabel label1;
        JLabel label2;
        public void initialDemoPanel(){
            setBorder(BorderFactory.createTitledBorder(getBorder(), "DemoPanel", TitledBorder.LEADING, TitledBorder.TOP, new Font("Default",Font.PLAIN,10), Color.gray));
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

            label1 = new JLabel("This is first line");
            label2 = new JLabel("This is second line");
        }

        public DemoPanel(){
            initialDemoPanel();
            add(label1);
            if(withGlue){
                add(Box.createVerticalGlue());
            }
            add(label2);
        }

        public DemoPanel(int strutValue){
            initialDemoPanel();
            add(label1);
            add(Box.createVerticalStrut(strutValue));
            add(label2);
        }
    }

    class ActionPanel extends JPanel{
        public ActionPanel(){
            setBorder(BorderFactory.createTitledBorder(getBorder(), "ActionPanel", TitledBorder.LEADING, TitledBorder.TOP, new Font("Default",Font.PLAIN,10), Color.gray));

            setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
            JRadioButton glueButton = new JRadioButton("With Glue");
            glueButton.addActionListener(new glueButtonListener());
            add(glueButton);

            add(Box.createHorizontalStrut(10));
            //To create horizontal white space
            JLabel strutLabel = new JLabel("Strut Value");
            add(strutLabel);
            spinner = new JSpinner(new SpinnerNumberModel(0,0,50,1));
            spinner.addChangeListener(new spinnerListener());
            add(spinner);
            //public SpinnerNumberModel(Number value,Comparable minimum,Comparable maximum,Number stepSize)
        }
    }

    class glueButtonListener implements ActionListener{
        @Override
        public void actionPerformed(ActionEvent e) {
            spinner.setValue(new Integer(0));
            withGlue = (withGlue == true ? false:true);
            whiteSpace.getContentPane().remove(demoPanel);
            demoPanel = new DemoPanel();
            whiteSpace.getContentPane().add(demoPanel,BorderLayout.CENTER);
            whiteSpace.getContentPane().validate();
        }
    }

    class spinnerListener implements ChangeListener{

        @Override
        public void stateChanged(ChangeEvent e) {
            int strutValue = (Integer) spinner.getValue();
            whiteSpace.getContentPane().remove(demoPanel);
            demoPanel = new DemoPanel(strutValue);
            whiteSpace.getContentPane().add(demoPanel,BorderLayout.CENTER);
            whiteSpace.getContentPane().validate();
        }
    }
}

Box.createHorizontalGlue() and Box.createHorizontalStrut(int height) can be used too. Besides, Box.createRigidArea(Dimension d) has the ability too create white space too.

@nIcE cOw 2013-07-26 08:48:57

Using various LayoutManagers one can provide spacing between various components.

1.) BorderLayout :

2.) FlowLayout :

3.) GridLayout :

4.) GridBagLayout :

GridBagConstraints.insets

5.) CardLayout (example) :

CardLayout(int hGap, int vGap)

Example to display all constructors in action :

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

public class LayoutExample {

    private final int hGap = 5;
    private final int vGap = 5;

    private String[] borderConstraints = {
        BorderLayout.PAGE_START,
        BorderLayout.LINE_START,
        BorderLayout.CENTER,
        BorderLayout.LINE_END,
        BorderLayout.PAGE_END
    };

    private JButton[] buttons;

    private GridBagConstraints gbc;

    private JPanel borderPanel;
    private JPanel flowPanel;
    private JPanel gridPanel;
    private JPanel gridBagPanel;
    private JPanel cardPanel;

    public LayoutExample() {
        buttons = new JButton[16];
        gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.FIRST_LINE_START;   
        gbc.insets = new Insets(hGap, vGap, hGap, vGap);        
    }

    private void displayGUI() {
        JFrame frame = new JFrame("Layout Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel(
                        new GridLayout(0, 1, hGap, vGap));
        contentPane.setBorder(
            BorderFactory.createEmptyBorder(hGap, vGap, hGap, vGap));
        borderPanel = new JPanel(new BorderLayout(hGap, vGap));
        borderPanel.setBorder(
            BorderFactory.createTitledBorder("BorderLayout"));
        borderPanel.setOpaque(true);
        borderPanel.setBackground(Color.WHITE);
        for (int i = 0; i < 5; i++) {
            buttons[i] = new JButton(borderConstraints[i]);
            borderPanel.add(buttons[i], borderConstraints[i]);
        }
        contentPane.add(borderPanel);

        flowPanel = new JPanel(new FlowLayout(
                    FlowLayout.CENTER, hGap, vGap));
        flowPanel.setBorder(
            BorderFactory.createTitledBorder("FlowLayout"));
        flowPanel.setOpaque(true);
        flowPanel.setBackground(Color.WHITE);
        for (int i = 5; i < 8; i++) {
            buttons[i] = new JButton(Integer.toString(i));
            flowPanel.add(buttons[i]);
        }
        contentPane.add(flowPanel);

        gridPanel = new JPanel(new GridLayout(2, 2, hGap, vGap));
        gridPanel.setBorder(
            BorderFactory.createTitledBorder("GridLayout"));
        gridPanel.setOpaque(true);
        gridPanel.setBackground(Color.WHITE);
        for (int i = 8; i < 12; i++) {
            buttons[i] = new JButton(Integer.toString(i));
            gridPanel.add(buttons[i]);
        }
        contentPane.add(gridPanel);

        gridBagPanel = new JPanel(new GridBagLayout());
        gridBagPanel.setBorder(
            BorderFactory.createTitledBorder("GridBagLayout"));
        gridBagPanel.setOpaque(true);
        gridBagPanel.setBackground(Color.WHITE);
        buttons[12] = new JButton(Integer.toString(12));
        addComp(gridBagPanel, buttons[12], 0, 0, 1, 1
                            , GridBagConstraints.BOTH, 0.33, 0.5);
        buttons[13] = new JButton(Integer.toString(13));
        addComp(gridBagPanel, buttons[13], 1, 0, 1, 1
                            , GridBagConstraints.BOTH, 0.33, 0.5);
        buttons[14] = new JButton(Integer.toString(14));
        addComp(gridBagPanel, buttons[14], 0, 1, 2, 1
                            , GridBagConstraints.BOTH, 0.66, 0.5);
        buttons[15] = new JButton(Integer.toString(15));
        addComp(gridBagPanel, buttons[15], 2, 0, 1, 2
                            , GridBagConstraints.BOTH, 0.33, 1.0);
        contentPane.add(gridBagPanel);

        cardPanel = new JPanel(new CardLayout(hGap, vGap));
        cardPanel.setBorder(
            BorderFactory.createTitledBorder("CardLayout"));
        cardPanel.setOpaque(true);
        cardPanel.setBackground(Color.WHITE);
        cardPanel.add(getPanel(Color.BLUE));
        cardPanel.add(getPanel(Color.GREEN));
        contentPane.add(cardPanel);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel getPanel(Color bColor) {
        JPanel panel = new JPanel(new FlowLayout(
                    FlowLayout.CENTER, hGap, vGap));
        panel.setOpaque(true);
        panel.setBackground(bColor.darker().darker());
        JButton swapperButton = new JButton("Next");
        swapperButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                CardLayout cardLayout = (CardLayout) cardPanel.getLayout();
                cardLayout.next(cardPanel);
            }
        });

        panel.add(swapperButton);

        return panel;
    }

    private void addComp(JPanel panel, JComponent comp
                                , int x, int y, int gWidth
                                    , int gHeight, int fill
                                        , double weightx, double weighty) {
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.gridwidth = gWidth;
        gbc.gridheight = gHeight;
        gbc.fill = fill;
        gbc.weightx = weightx;
        gbc.weighty = weighty;      

        panel.add(comp, gbc);
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable(){
            @Override
            public void run() {
                new LayoutExample().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

OUTPUT :

LAYOUTIMAGE

@splungebob 2013-07-26 16:57:08

+1 I luuuuuv me some GridBagConstraints insets. We use GBL a lot, so I wrote some helper classes that do the dirty work for me so that the GBL code is quite terse and readable. Like the sample does here, I use a default Insets so that I don't have to type it in everytime, and the resultant look is a more "relaxed" layout.

Related Questions

Sponsored Content

9 Answered Questions

20 Answered Questions

[SOLVED] How do I change Eclipse to use spaces instead of tabs?

9 Answered Questions

[SOLVED] Tab key == 4 spaces and auto-indent after curly braces in Vim

15 Answered Questions

[SOLVED] Convert tabs to spaces in Notepad++

9 Answered Questions

[SOLVED] Remove white space below image

3 Answered Questions

[SOLVED] Java Swing how to fix JLabel size

9 Answered Questions

1 Answered Questions

[SOLVED] swing gui flickering white error

2 Answered Questions

[SOLVED] Positioning components in Swing GUIs

1 Answered Questions

[SOLVED] How to set the white space size in CoreText?

Sponsored Content