Java Notes

Example: GridBagLayout

The above small window (JFrame) has a button that displays the JDialog on the right, which uses a GridBagLayout.

DemoGridBag - Main GUI class that does layout

This class builds a JDialog using GridBagLayout with the aid of two helper classes: GBHelper and Gap. The section of code that is relevant to GridBagLayout is between lines 104 and 127.

  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 
 91 
 92 
 93 
 94 
 95 
 96 
 97 
 98 
 99 
100 
101 
102 
103 
104 
105 
106 
107 
108 
109 
110 
111 
112 
113 
114 
115 
116 
117 
118 
119 
120 
121 
122 
123 
124 
125 
126 
127 
128 
129 
130 
131 
132 
133 
134 
135 
136 
137 
138 
139 
140 
141 
142 
143 
144 
145 
146 
147 
148 
149 
// File   : layoutDemos/layoutDemoGB/DemoGridBag.java
// Purpose: Show how to make a GridBagLayout using helper classes.
//          Two GridLayout subpanels of checkboxes and buttons are
//          created because these components have no alignment
//          in common with other parts of the GUI.  They are then
//          added to the GridBagLayout as components.
// Author : Fred Swartz - 2007-02-02 - Placed in public domain.

package layoutdemogb;

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

//////////////////////////////////////////////////////////////////// DemoGridBag
public class DemoGridBag extends JFrame {
    //================================================================ constants
    private static final int BORDER = 12;  // Window border in pixels.
    private static final int GAP    = 5;   // Default gap btwn components.
    
    //=================================================================== fields
    //... GUI components
    JLabel    findLbl     = new JLabel("Find What:"   , JLabel.LEFT);
    JLabel    replaceLbl  = new JLabel("Replace With:", JLabel.LEFT);
    JTextField findTF     = new JTextField(20);
    JTextField replaceTF  = new JTextField(20);
    JButton   findBtn     = new JButton("Find");
    JButton   replaceBtn  = new JButton("Replace");
    JButton   replAllBtn  = new JButton("Replace All");
    JButton   closeBtn    = new JButton("Close");
    JButton   helpBtn     = new JButton("Help");
    JCheckBox matchCaseCB = new JCheckBox("Match Case");
    JCheckBox wholeWrdsCB = new JCheckBox("Whole Words");
    JCheckBox regexCB     = new JCheckBox("Regular Expressions");
    JCheckBox highlightCB = new JCheckBox("Highlight Results", true);
    JCheckBox wrapCB      = new JCheckBox("Wrap Around", true);
    JCheckBox selectionCB = new JCheckBox("Search Selection");
    JCheckBox backwardsCB = new JCheckBox("Search Backwards");
    JCheckBox incrementCB = new JCheckBox("Incremental Search", true);
    
    JDialog   replaceDialog = new JDialog();
    
    //============================================================== constructor
    public DemoGridBag() {
        //... Create a dialog box with GridBag content pane.
        replaceDialog.setContentPane(createContentPane());
        replaceDialog.setTitle("Find Replace");
        replaceDialog.pack();
        replaceDialog.setLocationRelativeTo(this);
        
        //... Create a button for the window to display this dialog.
        JButton showDialogBtn = new JButton("Show Find/Replace Dialog");
        showDialogBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                replaceDialog.setVisible(true);
            }
        });

        //... Create content pane with one button and set window attributes.
        JPanel windowContent = new JPanel();
        windowContent.setLayout(new BorderLayout());
        windowContent.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
        windowContent.add(showDialogBtn, BorderLayout.CENTER);
        
        //... Set the window characteristics.
        super.setContentPane(windowContent);
        super.pack();                               // Layout components.
        super.setTitle("DemoGridBag");
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.setLocationRelativeTo(null);          // Center window.
    }

    //======================================================== createContentPane
    private JPanel createContentPane() {
        selectionCB.setEnabled(false);
        
        //... Create an independent GridLayout panel of buttons. 
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(5, 1, GAP, GAP));
        buttonPanel.add(findBtn);
        buttonPanel.add(replaceBtn);
        buttonPanel.add(replAllBtn);
        buttonPanel.add(closeBtn);
        buttonPanel.add(helpBtn);
        
        //... Create an independent GridLayout panel of check boxes.
        JPanel checkBoxPanel = new JPanel();
        checkBoxPanel.setLayout(new GridLayout(4, 2));
        checkBoxPanel.add(matchCaseCB);
        checkBoxPanel.add(wrapCB);
        checkBoxPanel.add(wholeWrdsCB);
        checkBoxPanel.add(selectionCB);
        checkBoxPanel.add(regexCB);
        checkBoxPanel.add(backwardsCB);
        checkBoxPanel.add(highlightCB);
        checkBoxPanel.add(incrementCB);
        
        //... Create GridBagLayout content pane; set border.
        JPanel content = new JPanel(new GridBagLayout());
        content.setBorder(BorderFactory.createEmptyBorder(BORDER, BORDER, 
                BORDER, BORDER));

//\\//\\//\\//\\//\\ GridBagLayout code begins here
        GBHelper pos = new GBHelper();  // Create GridBag helper object.
        
        //... First row
        content.add(findLbl, pos);
        content.add(new Gap(GAP), pos.nextCol());
        content.add(findTF      , pos.nextCol().expandW());
        content.add(new Gap(GAP), pos.nextCol());
        content.add(buttonPanel , pos.nextCol().height(5)
                                             .align(GridBagConstraints.NORTH));
        
        content.add(new Gap(GAP) , pos.nextRow());  // Add a gap below
        
        //... Next row.
        content.add(replaceLbl  , pos.nextRow());
        content.add(new Gap(GAP), pos.nextCol());
        content.add(replaceTF   , pos.nextCol().expandW());
        
        content.add(new Gap(2*GAP), pos.nextRow());  // Add a big gap below
        
        //... Last content row.
        content.add(checkBoxPanel, pos.nextRow().nextCol().nextCol());
        
        //... Add an area that can expand at the bottom.
        content.add(new Gap()  , pos.nextRow().width().expandH());
 //\\//\\//\\//\\//\\ GridBagLayout code ends here
        return content;
    }
    
    //===================================================================== main
    public static void main(String[] args) {
        //... Set Look and Feel.
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception unused) {
            // Nothing can be done, so just ignore it.
        }
        
        //... Start up GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                DemoGridBag window = new DemoGridBag();
                window.setVisible(true);
            }
        });
    }
}

GBHelper - Helper class to represent the constraints

Using the raw GridBagConstraints class to specify the layout characteristics of each element is awkward, the two constructors take either no arguments or eleven arguments. The properties are all public fields, so it's possible to assign to them and share one GridBagConstraints object, but this usually becomes a source of much aggravation.

Helper class. A common solution is to define a helper class which makes it easier to work with a GridBagConstraints object. I've defined one such class below which is a subclass of GridBagConstraints, but there are many other variations available on the Internet.

  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 
 91 
 92 
 93 
 94 
 95 
// File   : layoutDemos/layoutDemoGB/GBHelper.java
// Purpose: Keeps track of current position in GridBagLayout.
//          Supports a few GridBag features: position, width, height, expansion.
//          All methods return GBHelper object for call chaining.
// Author : Fred Swartz - January 30, 2007 - Placed in public domain.

package layoutdemogb;

import java.awt.*;

//////////////////////////////////////////////////////////////////// Class
public class GBHelper extends GridBagConstraints {
    
    //============================================================== constructor
    /* Creates helper at top left, component always fills cells. */
    public GBHelper() {
        gridx = 0;
        gridy = 0;
        fill = GridBagConstraints.BOTH;  // Component fills area 
    }
    
    //================================================================== nextCol
    /* Moves the helper's cursor to the right one column. */
    public GBHelper nextCol() {
        gridx++;
        return this;
    }
    
    //================================================================== nextRow
    /* Moves the helper's cursor to first col in next row. */
    public GBHelper nextRow() {
        gridx = 0;
        gridy++;
        return this;
    }
    
    //================================================================== expandW
    /* Expandable Width.  Returns new helper allowing horizontal expansion. 
       A new helper is created so the expansion values don't
       pollute the origin helper. */
    public GBHelper expandW() {
        GBHelper duplicate = (GBHelper)this.clone();
        duplicate.weightx = 1.0;
        return duplicate;
    }
    
    //================================================================== expandH
    /* Expandable Height. Returns new helper allowing vertical expansion. */
    public GBHelper expandH() {
        GBHelper duplicate = (GBHelper)this.clone();
        duplicate.weighty = 1.0;
        return duplicate;
    }
    
    //==================================================================== width
    /* Sets the width of the area in terms of number of columns. */
    public GBHelper width(int colsWide) {
        GBHelper duplicate = (GBHelper)this.clone();
        duplicate.gridwidth = colsWide;
        return duplicate;
    }
    
    //==================================================================== width
    /* Width is set to all remaining columns of the grid. */
    public GBHelper width() {
        GBHelper duplicate = (GBHelper)this.clone();
        duplicate.gridwidth = REMAINDER;
        return duplicate;
    }
    
    //=================================================================== height
    /* Sets the height of the area in terms of rows. */
    public GBHelper height(int rowsHigh) {
        GBHelper duplicate = (GBHelper)this.clone();
        duplicate.gridheight = rowsHigh;
        return duplicate;
    }
    
    //=================================================================== height
    /* Height is set to all remaining rows. */
    public GBHelper height() {
        GBHelper duplicate = (GBHelper)this.clone();
        duplicate.gridheight = REMAINDER;
        return duplicate;
    }
    
    //==================================================================== align
    /* Alignment is set by parameter. */
    public GBHelper align(int alignment) {
        GBHelper duplicate = (GBHelper)this.clone();
        duplicate.fill   = NONE;
        duplicate.anchor = alignment;
        return duplicate;
    }
}

Gap - Helper class to build gaps

This class is used just to create elements to fill in the gaps. There are other ways, such as using the Box class methods to create rigid areas or glue.

  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 
// File   : layoutDemos/layoutDemoGB/Gap.java
// Purpose: Gaps for use in GridBagLayout (or any other).
//          Library alternatives are available in the Box class.
// Author : Fred Swartz - January 30, 2007 - Placed in public domain.

package layoutdemogb;

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

////////////////////////////////////////////////////////////////////// Class Gap
public class Gap extends JComponent {
    
    //============================================================== constructor
    /* Creates filler with minimum size, but expandable infinitely. */
    public Gap() {
        Dimension min = new Dimension(0, 0);
        Dimension max = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
        setMinimumSize(min);
        setPreferredSize(min);
        setMaximumSize(max);
    }
    
    //============================================================== constructor
    /* Creates rigid filler. */
    public Gap(int size) {
        Dimension dim = new Dimension(size, size);
        setMinimumSize(dim);
        setPreferredSize(dim);
        setMaximumSize(dim);
    }
}