Hello, I have looked at an example of GridBagLayout (JamesCherrill you must be thrilled : - )!!) and there are a few things that are not entirely clear to me. First here is the code taken from deitel and deitel “Java how to program”, chapter 25:

// Fig. 25.21: GridBagFrame.java
// Demonstrating GridBagLayout.
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JComboBox;

public class GridBagFrame extends JFrame 
{ 
   private GridBagLayout layout; // layout of this frame
   private GridBagConstraints constraints; // constraints of this layout

   // set up GUI
   public GridBagFrame()
   {
      super( "GridBagLayout" );
      layout = new GridBagLayout();
      setLayout( layout ); // set frame layout
      constraints = new GridBagConstraints(); // instantiate constraints

      // create GUI components
      JTextArea textArea1 = new JTextArea( "TextArea1", 5, 10 );
      JTextArea textArea2 = new JTextArea( "TextArea2", 2, 2 );

      String[] names = { "Iron", "Steel", "Brass" };
      JComboBox comboBox = new JComboBox( names );

      JTextField textField = new JTextField( "TextField" );
      JButton button1 = new JButton( "Button 1" );
      JButton button2 = new JButton( "Button 2" );
      JButton button3 = new JButton( "Button 3" );

      // weightx and weighty for textArea1 are both 0: the default
      // anchor for all components is CENTER: the default
      constraints.fill = GridBagConstraints.BOTH;
      addComponent( textArea1, 0, 0, 1, 3 );    

      // weightx and weighty for button1 are both 0: the default
      constraints.fill = GridBagConstraints.HORIZONTAL;
      addComponent( button1, 0, 1, 2, 1 );

      // weightx and weighty for comboBox are both 0: the default
      // fill is HORIZONTAL
      addComponent( comboBox, 2, 1, 2, 1 );             

      // button2
      constraints.weightx = 1000;  // can grow wider
      constraints.weighty = 1;     // can grow taller
      constraints.fill = GridBagConstraints.BOTH;
      addComponent( button2, 1, 1, 1, 1 );

      // fill is BOTH for button3
      constraints.weightx = 0;
      constraints.weighty = 0;    
      addComponent( button3, 1, 2, 1, 1 );

      // weightx and weighty for textField are both 0, fill is BOTH
      addComponent( textField, 3, 0, 2, 1 );

      // weightx and weighty for textArea2 are both 0, fill is BOTH
      addComponent( textArea2, 3, 2, 1, 1 );
   } // end GridBagFrame constructor

   // method to set constraints on 
   private void addComponent( Component component,
      int row, int column, int width, int height )
   {
      constraints.gridx = column; // set gridx
      constraints.gridy = row; // set gridy
      constraints.gridwidth = width; // set gridwidth
      constraints.gridheight = height; // set gridheight
      layout.setConstraints( component, constraints ); // set constraints
      add( component ); // add component
   } // end method addComponent
} // end class GridBagFrame

and the test class

// Fig. 25.22: GridBagDemo.java
// Demonstrating GridBagLayout.
import javax.swing.JFrame;

public class GridBagDemo
{ 
   public static void main( String[] args )
   { 
      GridBagFrame gridBagFrame = new GridBagFrame(); 
      gridBagFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      gridBagFrame.setSize( 300, 150 ); // set frame size
      gridBagFrame.setVisible( true ); // display frame
   } // end main
} // end class GridBagDemo

Right, in principle, it’s clear, but here are my questions:
1)why are they not using any JPanel and attaching everything to the JFrame? IS that for simplicity or for other reasons (like you can’t use JPanels with GridBagLayout)?
2)I have read about the various constraints of type GridBagConstraints that we can use with this layout manager, like fill, gridx, gridy etc. Now, in the program the components textArea1 and button1 (among othe others) have both a fill constraint set:

       constraints.fill = GridBagConstraints.BOTH;
      addComponent( textArea1, 0, 0, 1, 3 );           
      // weightx and weighty for button1 are both 0: the default
      constraints.fill = GridBagConstraints.HORIZONTAL;
      addComponent( button1, 0, 1, 2, 1 );

how on earth does the compiler know which component has which constraints.fill assigned to it? I mean, how does it know that this constraints.fill = GridBagConstraints.BOTH; refers to the textArea1 and this constraints.fill = GridBagConstraints.HORIZONTAL; to button1? That applies of course to the other type of constraints assigned to other components
3)import java.awt.Component; Method addComponent()

private void addComponent( Component component,
      int row, int column, int width, int height )
   {
      constraints.gridx = column; // set gridx
      constraints.gridy = row; // set gridy
      constraints.gridwidth = width; // set gridwidth
      constraints.gridheight = height; // set gridheight
      layout.setConstraints( component, constraints ); // set constraints
      add( component ); // add component
   } // end method addComponent

takes 5 parameters. A Component components is among them and I am not entirely sure as to why. Let's se if I get this right. Every JAVA component, like a JtTextField, JButton, JComboBox etc is also a Component object. Since the parameters passed to the method are of a different type ( JtTextField, JButton, JComboBox ) the safest way to make sure that the method can receive any of the above types is if it accepts a parameter of type Component (since all the components in questions as said are afterall all Components ). Correct?
But I wonder, if JtTextField, JButton, JComboBox are all objects of type Component, they are also objects of type JComponent, aren't they? So the first parameter that the addComponent() method receives could in fact be of type JComponent as opposed to Component?

OK!!!
1) Just for simplicity. You can have a GridBagLayout on a JPanel, but there's often less need for sub-panels to achieve your layout than there would be for some other managers. On average its still very common to see multiple JPanels - relating to different logical parts of the layout.
2? This makes me shudder. The program doesn't directly call the normal add method, it uses the author's own addComponent method (lines 69-78) that calls the normal add after setting the layout's constraints using the constraints variable. As an example of sharing a global variable that works via side effects it should go down in the all-time book of terrible programming.
It's like the example shown in the GridBagLayout API doc, but corrupted.
3? Every swing component is a subclass of JComponent, which in turn is a subclass of java.awt.Component. So if the method takes a Component it will accept any AWT or Swing compoent.

Cool, maybe I will try to rewrite this one then. I don't know why he had used his own method, there is probably a reason for that. Anyway, pretty much all clear. Just one thing, so I understand things correctly. Going back to my point 2 for the above program, how does the compiler know which component is using the constraints.fill=... (I appreciate that global variables are used a lot, but it's just for me to understand really)
thanks

In his horrible method - line 76 - he calls layout.setConstraints( component, constraints) before calling add

The example in the API doc is similar, except that it passes the constraints explicitly into the method, so everyone knows what's going on.

ps: Personally I always use the simple add(component, constraints) method - no extra methods and it's perfectly clear what's going on.

Edited 2 Years Ago by JamesCherrill

thanks that's clear now :-)! I guess that the reason why he did it this way is because it would save him doing things like

constraints.gridx = column; // set gridx
constraints.gridy = row; // set gridy
constraints.gridwidth = width; // set gridwidth
constraints.gridheight = height;

for each component, meaning you will still need to add the actual constraints to each of them.
yes exactly like you said, in the API everything is passed explicitly and it takes more lines of code to do that (I am not trying to defend the way my book has done it, just an observation). Also, int he API I have the same problem I had here, I don't understand how the compiler know which method the constraints are applied to

Edited 2 Years Ago by Violet_82

Either you set the constraints for the layout (like line 76 above) then those apply to whatever you add afterwards by default, OR you specify a set of constraints in the add(component, constraints) method. I prefer to stick with the standard API and expicit constraints, if only for clarity, and it's not really any extra code, eg...

constraints = new GridBagConstraints();
...
constraints.xxx = xxx // set all the common options
...
constraints.yyy = yyy // set any  unique options for component 1
add(component1, constraints);
...
constraints.zzz = zzz // set any  unique options for component 2
add(component2, constraints);
// etc

... or I frequently don't bother with a constraints variable at all, and just copy/paste/update as required, eg

import static java.awt.GridBagConstraints.*;

Insets zeroInsets = new Insets(0, 0, 0, 0);

contentPane.add(jButton1, new GridBagConstraints(0, 6, 1, 1, 0.5, 0.0,
               CENTER, HORIZONTAL, zeroInsets, 0, 0));
contentPane.add(jButton2, new GridBagConstraints(1, 6, 1, 1, 0.5, 0.0,
               CENTER, HORIZONTAL, zeroInsets, 0, 0));

Edited 2 Years Ago by JamesCherrill

This question has already been answered. Start a new discussion instead.