0

I have a problem with GridbagLayout; I've 5 buttons and I want to have them in this way: Target ButtonDisposition

I've already tried different approaches but no one works in the correct way.

For example:

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

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestGridBagLayout {

    protected void initUI() {
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel southPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        gbc.gridwidth = 2;
        gbc.gridy = 0;
        JButton enterRoom = new JButton("Enter room");
        JButton exitRoom = new JButton("Exit room");
        JButton login = new JButton("Login");
        JButton logout = new JButton("Logout");
        JButton whoIsIn = new JButton("Who is in");

        gbc.gridx = 1;
        southPanel.add(enterRoom, gbc);

        gbc.gridx = 5;
        southPanel.add(exitRoom, gbc);

        gbc.gridy = 1;

        gbc.gridx = 0;
        southPanel.add(login, gbc);

        gbc.gridx = 3;
        southPanel.add(logout, gbc);

        gbc.gridx = 6;
        southPanel.add(whoIsIn, gbc);

        frame.add(southPanel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        SwingUtilities.invokeLater(new Runnable() {

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

Appears: wrong buttons aligning I'm not interested in other approaches (such as GridLayout), I'd like to know what I'm missing.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Jacopo
  • 97
  • 11
  • For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example) or [SSCCE](http://www.sscce.org/) (Short, Self Contained, Correct Example). – Andrew Thompson Apr 14 '15 at 17:59
  • @AndrewThompson I put the mcve I made on my side. I think it reproduces the issue the OP is seeing. Most likely, the issue is simply that gridwidth only applies if there is another component on another row for the "spanned" column – Guillaume Polet Apr 14 '15 at 18:10

2 Answers2

2

GridbagLayout seems to require a row where a component occupies all of the columns in the row. See: Why does this GridBagLayout not appear as planned? for the basis of this solution.

Note the that horizontal strut size was choosen to be half the size of the "Logout" button so that two cells with span the width of the logout button to give the centering of components that you desire.

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

public class SSCCE extends JPanel
{
    public SSCCE()
    {
        JButton enterRoom = new JButton("Enter room");
        JButton exitRoom = new JButton("Exit room");
        JButton login = new JButton("Login");
        JButton logout = new JButton("Logout");
        JButton whoIsIn = new JButton("Who is in");

        setLayout( new GridBagLayout() );
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 0,5, 0);

        gbc.gridwidth = 2;

        gbc.gridx = 1;
        gbc.gridy = 0;
        add(enterRoom, gbc);

        gbc.gridx = 5;
        gbc.gridy = 0;
        add(exitRoom, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        add(login, gbc);

        gbc.gridx = 3;
        gbc.gridy = 1;
        add(logout, gbc);

        gbc.gridx = 6;
        gbc.gridy = 1;
        add(whoIsIn, gbc);

        //  Add dummy components so every cell has a component.

        gbc.insets = new Insets(0, 0, 0, 0);
        gbc.gridwidth = 1;
        gbc.gridy = 2;
        int strutWidth = logout.getPreferredSize().width / 2;

        for (int i = 0; i < 8; i++)
        {
            gbc.gridx = i;
            add(Box.createHorizontalStrut(strutWidth), gbc);
        }
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE(), BorderLayout.NORTH);
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}
Community
  • 1
  • 1
camickr
  • 321,443
  • 19
  • 166
  • 288
2

GridBagLayout can be a strange animal in some cases. But anyway, gridwidth is something that works, only if there is an actual component that requires some width within the "spanned" column (for example, if you say gridx=0 and gridwidth=2, column 0 has a component and the "spanned" column is column 1).

In your case, column 2, 4 & 7 have no components, so their width is set to 0. Additionnaly, column 5 also gets a width of 0, because column 6 provides enough witdth to the exit room button, so in the end you get the result you see.

Now, not sure of the kind of layout you are trying to achieve (I saw your screenshot, but how should it behave when the panel collapses/expands in width?). So find below, an example that comes a bit closer to what you describe (although I don't find it very nice)

Example

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestGridBagLayout2 {

    protected void initUI() {
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel southPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        gbc.gridy = 0;
        JButton enterRoom = new JButton("Enter room");
        JButton exitRoom = new JButton("Exit room");
        JButton login = new JButton("Login");
        JButton logout = new JButton("Logout");
        JButton whoIsIn = new JButton("Who is in");

        gbc.gridx = 0;
        gbc.weightx = 1.0;
        gbc.anchor = GridBagConstraints.EAST;
        southPanel.add(enterRoom, gbc);

        gbc.anchor = GridBagConstraints.WEST;
        gbc.gridx = 2;
        southPanel.add(exitRoom, gbc);

        gbc.gridy = 1;

        gbc.gridx = 0;
        southPanel.add(login, gbc);

        gbc.weightx = 0;
        gbc.gridx = 1;
        southPanel.add(logout, gbc);

        gbc.weightx = 1.0;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.gridx = 2;
        southPanel.add(whoIsIn, gbc);

        frame.add(southPanel);
        frame.pack();
        frame.setSize(frame.getWidth() * 4 / 3, frame.getHeight());
        frame.setMinimumSize(frame.getSize());
        frame.setVisible(true);
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestGridBagLayout().initUI();
            }
        });
    }
}
Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117