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