Search code examples
javaswinglayout-managergridbaglayout

GridBagConstraints gridwidth affecting components unexpectedly


This is the result I'm going for: Wanted Results

But this is what I'm getting: Results

Now, I understand the GridBagConstraints.HORIZONTAL; allows the component to take up any empty space horizontally, but I'm not sure how to have the component only fill in the remaining amount of it's grid space. Here is my current GUI code including the GridBagConstraints:

public class LoginPanel extends JPanel {
    private JTextField userfield;
    private JPasswordField passfield;

    private JButton login;
    private JButton create;

    public LoginPanel() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.weightx = .2;

        gbc.anchor = GridBagConstraints.EAST;
        JLabel label = new JLabel("Username: ");
        gbc.gridx = 1;
        add(label, gbc);

        label = new JLabel("Password: ");
        gbc.gridy = 1;
        add(label, gbc);

        gbc.anchor = GridBagConstraints.WEST;
        userfield = new JTextField(10);
        gbc.gridx = 2;
        gbc.gridy = 0;
        add(userfield, gbc);

        passfield = new JPasswordField(10);
        gbc.gridy = 1;
        add(passfield, gbc);


        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.CENTER;
        login = new JButton("Login");
        gbc.gridwidth = 2;
        gbc.gridx = 1;
        gbc.gridy = 2;
        add(login, gbc);

        create = new JButton("Create Account");
        gbc.gridy = 3;
        add(create, gbc);


        JTextPane textpane = new JTextPane();
        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.gridwidth = 10;
        add(textpane, gbc);
    }
}

Is there any way to achieve this kind of formatting using GridBagLayout? If not, what layout/layouts do you recommend I use?

If you are still confused about what my goals are, I'm trying to have the buttons fill enough space to be even with the labels and fields, yet have my textpane at the bottom fill the entire screen.


Solution

  • Get rid of the line

    gbc.weightx = .2;
    

    It's messing with the fill properties...

    enter image description here

    Updated, missed one requirement

    Okay, you could spend the rest of your life trying to make this work, or you could break you layout down into manageable parts and layout them out separately...

    Login

    This example basically places the fields and buttons into there own container and focus on their layout requirements. It then adds this and the text field to the LoginPane and focuses on their requirements separately...

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JPasswordField;
    import javax.swing.JTextField;
    import javax.swing.JTextPane;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.border.LineBorder;
    
    public class TestLayout100 {
    
        public static void main(String[] args) {
            new TestLayout100();
        }
    
        public TestLayout100() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new LoginPanel());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class LoginPanel extends JPanel {
    
            private JTextField userfield;
            private JPasswordField passfield;
    
            private JButton login;
            private JButton create;
    
            public LoginPanel() {
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
    
                JPanel fields = new JPanel(new GridBagLayout());
    
                gbc.anchor = GridBagConstraints.EAST;
                JLabel label = new JLabel("Username: ");
                gbc.gridx = 1;
                fields.add(label, gbc);
    
                label = new JLabel("Password: ");
                gbc.gridy = 1;
                fields.add(label, gbc);
    
                gbc.anchor = GridBagConstraints.WEST;
                userfield = new JTextField(10);
                gbc.gridx = 2;
                gbc.gridy = 0;
                fields.add(userfield, gbc);
    
                passfield = new JPasswordField(10);
                gbc.gridy = 1;
                fields.add(passfield, gbc);
    
                gbc.fill = GridBagConstraints.HORIZONTAL;
                gbc.anchor = GridBagConstraints.CENTER;
                login = new JButton("Login");
                gbc.gridwidth = 2;
                gbc.gridx = 1;
                gbc.gridy = 2;
                fields.add(login, gbc);
    
                create = new JButton("Create Account");
                gbc.gridy = 3;
                fields.add(create, gbc);
    
                gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = 0;
                add(fields, gbc);
    
                JTextPane textpane = new JTextPane();
                gbc.weightx = 1;
                gbc.gridy++;
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                gbc.fill = GridBagConstraints.HORIZONTAL;
                add(textpane, gbc);
            }
        }
    
    }