Search code examples
javaswinglayout-managergridbaglayout

JButton in GridBagLayout in a JPanel


I am learning swing from past week, I have some issue with GridBagConstraints to put one button in top left corner but all other buttons in default in GridBagConstraints ?

I am using code that like not original but states the problem

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

@SuppressWarnings("serial")
class MyPanel extends JPanel
{
    JButton menu = new JButton("Menu"), button = new JButton("Puzzle");

    GridBagConstraints gbc1 = new GridBagConstraints(), gbc2 = new GridBagConstraints();

    private void setup()
    {
        gbc1.anchor   = GridBagConstraints.FIRST_LINE_START;
        gbc2.anchor   = GridBagConstraints.CENTER;
        gbc2.weightx  = 1.0;
        gbc2.weighty  = 1.0;
    }

    public MyPanel()
    {
        this.setLayout(new GridBagLayout());
        this.setup();
        this.button.setPreferredSize(new Dimension(250, 140));
        this.add(menu, gbc1);
        this.add(button, gbc2);
    }
}

@SuppressWarnings("serial")
public class Test extends JFrame
{
    public Test()
    {
        this.setTitle("Test");
        this.setContentPane(new MyPanel());
        this.setResizable(false);
        this.setSize(800, 600);
        this.setVisible(true);
    }

    public static void main(String args[])
    {
        SwingUtilities.invokeLater(() -> new Test());
    }
}

output

output

I want menu is top corner.

I read from here but i did not understand this Could you please explain GridBagConstraints for how to do that.

I Hope that problem is clear to understand, if not please let me know in comments.

EDIT:

@camickr suggestion works but a little problem, the Puzzle Button is not in extract center.

Thanks.


Solution

  • By default the GridBagLayout will display all the components centered horizontally and vertically, unless one of the components has a weightx/weighty value not equal to 0. Then that component will fill the extra space in the frame.

    So if you want one component at the "top/left" and one in the "center", you need to:

    1. use the "anchor" constraint. It will be different for both components.
    2. the component in the center will need to use the "weightx/weighty" constraints.

    However, an easer solution might be to use a combination of panels with different layout managers.

    For example:

    JPanel menuPanel = new JPanel( new FlowLayout(FlowLayout.LEFT) );
    menuPanel.add(menuButton);
    
    JPanel centerPanel = new JPanel( new GridBagLayout() );
    centerPanel.add(puzzle, new GridBagConstraints());
    
    frame.add(menuPanel, BorderLayout.PAGE_START);
    frame.add(centerPanel, BorderLayout.CENTER);
    

    So now the "top" of the frame will contain a panel with components displayed from the left and the "center" of the frame will contain your puzzle centered in the remaining space of the frame.

    Edit:

    I solved it but put gridx and gridy to 0 in center component, but i did not completely understand the setttings

    Well I mentioned that you would need to use the gridx/gridy constraints. You should always use those constraints as it is very obvious what grid you want to add the component to. The examples from the tutorial always specify those values.

    Using gridx/gridy both equal to 0, does not really make sense. The effect is that you have two components trying to share the same grid.

    Remove the setResizable(false) statement and shrink the size of the frame to see how the button repositions itself.

    It is not normal that two components share the same grid. Normally you would have the menu on the first row and the button on the second row. This will center the button horizontally in the frame and vertically in the space below the menu. What you are doi