Rudi Kershaw
Rudi Kershaw

Reputation: 12972

Java Swing GridBagLayout Component Positioning

I am using Swing's GridBagLayout for the fist time and I have so far only added two components to a container, although I intend to add more below vertically. So far, the first component (a JLabel) is positioned correctly at PAGE_START, and I have remembered to set weight attributes for the components' corresponding GridBagConstraints. The second component (a JTextField) however is not positioning as I intended and it being centered in the container rather than moving up underneath the JLabel. I have attempted to use multiple anchor constants including FIRST_LINE_START, PAGE_START, NORTH & NORTHWEST but so far nothing is working.

And so, once again I call for the gifted coders of stackoverflow for help. Below is a snippet of the code and below that is an image of the problem graphically.

    // Instantiate components and configure their corresponding GridBagConstraints attributes
    // refPlusType properties
    refPlusType = new JLabel("<html><h3>"+"Reference"+" - "+"Job Type"+" </h3><hr /></html>");
    refPlusTypeGC = new GridBagConstraints();
    refPlusTypeGC.gridx = 0; // Grid position 
    refPlusTypeGC.gridy = 0;
    refPlusTypeGC.gridwidth = 2; // Number of colums occupied by component
    refPlusTypeGC.insets = new Insets(5, 10, 5, 10); // Specifies margin
    refPlusTypeGC.weightx = 0.1; // Required for anchor to work. 
    refPlusTypeGC.weighty = 0.1; // Required for anchor to work. 
    refPlusTypeGC.anchor = GridBagConstraints.PAGE_START; // Position in container

    // addressLine1 properties
    addressLine1 = new JTextField();
    addressLine1GC = new GridBagConstraints();
    addressLine1GC.gridx = 0; 
    addressLine1GC.gridy = 1;
    addressLine1GC.gridwidth = 2; 
    addressLine1GC.insets = new Insets(0, 10, 0, 10); 
    addressLine1GC.fill = GridBagConstraints.HORIZONTAL; // Specifies component fill Horizontal space
    addressLine1GC.weightx = 0.1; 
    addressLine1GC.weighty = 0.1; 
    addressLine1GC.anchor = GridBagConstraints.FIRST_LINE_START;

    // Add components to this HALLogisticsDetailsPanel
    this.add(refPlusType, refPlusTypeGC);
    this.add(addressLine1, addressLine1GC);

Image below;

enter image description here

Thank you all for any help you can offer.

Upvotes: 3

Views: 2445

Answers (4)

Rudi Kershaw
Rudi Kershaw

Reputation: 12972

Okay, I got it. I don't like accepting my own answers but here we go. At the end of the day I am trying to get the whole lot to bunch together properly at the top of the container. Adding weighty attributes to all the components individually means that the remaining space in the container is distributed between all of them (relative to their weighty attribute) therefore spacing them out.

The answer seems to be that by adding a weighty attribute to the lowest component in the GridBagLayout, the rest of the remaining space is allocated to below the lowest component and therefore pushing all components to the top. By default is seems that when remaining space is allocated to a component based on it's weight, it is allocated below it (at least on the y axis).

Here is the new code with three components to help demonstrate;

    // Instantiate components and configure their corresponding GridBagConstraints attributes
    // refPlusType properties
    refPlusType = new JLabel("<html><h3>"+"Reference"+" - "+"Job Type"+" </h3><hr /></html>");
    refPlusTypeGC = new GridBagConstraints();
    refPlusTypeGC.gridx = 0; // Grid position 
    refPlusTypeGC.gridy = 0;
    refPlusTypeGC.gridwidth = 2; // Number of colums occupied by component
    refPlusTypeGC.insets = new Insets(5, 10, 5, 10); // Specifies margin

    // addressLine1 properties
    addressLine1 = new JTextField();
    addressLine1GC = new GridBagConstraints();
    addressLine1GC.gridx = 0; 
    addressLine1GC.gridy = 1;
    addressLine1GC.gridwidth = 2; 
    addressLine1GC.insets = new Insets(0, 10, 0, 10); 
    addressLine1GC.fill = GridBagConstraints.HORIZONTAL; // Specifies component fill Horizontal space

    // addressLine2 properties
    addressLine2 = new JTextField();
    addressLine2GC = new GridBagConstraints();
    addressLine2GC.gridx = 0; 
    addressLine2GC.gridy = 2;
    addressLine2GC.gridwidth = 2; 
    addressLine2GC.insets = new Insets(0, 10, 0, 10); 
    addressLine2GC.fill = GridBagConstraints.HORIZONTAL; // Specifies component fill Horizontal space 
    addressLine2GC.weighty = 1; // Required for anchor to work.
    addressLine2GC.anchor = GridBagConstraints.NORTH; // Position in container

    // Add components to this HALLogisticsDetailsPanel
    this.add(refPlusType, refPlusTypeGC);
    this.add(addressLine1, addressLine1GC);
    this.add(addressLine2, addressLine2GC);

Upvotes: 1

Jim S.
Jim S.

Reputation: 231

The best 'tutorial' for GridBagLayout that I have seen was created by Scott Stanchfield. You can find a link to the PowerPoint presentation he gave at JavaOne 2001 here

There used to be an article online with the same information, but it appears to have been swallowed up by Oracle.

Please read all the warnings about why GBL is not ideal. If you are determined to use it, Scott gives a great visual lesson on how to determine all the constraints by creating a simple sketch of your GUI.

Jim S.

Upvotes: 1

Guillaume Polet
Guillaume Polet

Reputation: 47608

anchor = NORTH works like a charm:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class TestJPanels {

    private JLabel refPlusType;
    private JTextField addressLine1;

    protected void initUI() {
        final JFrame frame = new JFrame(TestJPanels.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel panel = new JPanel(new GridBagLayout());
        // Instantiate components and configure their corresponding GridBagConstraints attributes
        // refPlusType properties
        refPlusType = new JLabel("<html><h3>" + "Reference" + " - " + "Job Type" + " </h3><hr /></html>");
        GridBagConstraints refPlusTypeGC = new GridBagConstraints();
        refPlusTypeGC.gridwidth = GridBagConstraints.REMAINDER; // Number of colums occupied by component
        refPlusTypeGC.insets = new Insets(5, 10, 5, 10); // Specifies margin
        refPlusTypeGC.weightx = 1; // Required for anchor to work.
        refPlusTypeGC.anchor = GridBagConstraints.PAGE_START; // Position in container

        // addressLine1 properties
        addressLine1 = new JTextField(20);
        GridBagConstraints addressLine1GC = new GridBagConstraints();
        addressLine1GC.insets = new Insets(0, 10, 0, 10);
        addressLine1GC.fill = GridBagConstraints.HORIZONTAL; // Specifies component fill Horizontal space
        addressLine1GC.weightx = 1;
        addressLine1GC.weighty = 1;
        addressLine1GC.anchor = GridBagConstraints.NORTH;

        // Add components to this HALLogisticsDetailsPanel
        panel.add(refPlusType, refPlusTypeGC);
        panel.add(addressLine1, addressLine1GC);
        frame.add(panel);
        frame.setSize(600, 600);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestJPanels().initUI();
            }
        });
    }
}

Upvotes: 2

Bryan Hutchinson
Bryan Hutchinson

Reputation: 85

Try increasing the weighty for addressLine1 to a much larger value. I did a quick test setting it to 1000:

addressLine1GC.weighty = 1000.0;

and that pushed the addressLine1 field up under the label with the whitespace below.

Upvotes: 4

Related Questions