# 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);
        }
    }