javaswinggridbaglayout

How to get 2 radio buttons aligned correctly with Swing GridBagLayout


I can't get GridBagLayout to work as I'd like. I'm trying to get 2 radio buttons to align next to each other. The best I can get is inches apart. I've played with weights to no avail. Currently I have my labels spanned over 2 cells. I have my radio buttons using 1 cell each with a 2 cell label. The last row is a 2 cell label and 2 cell date control. Maybe GridBagLayout is not the correct manager.

public class GridBagLayoutTest extends JFrame {
    
    private final JPanel addScorePanel;
    private final JTextField txtScore;
    private final JRadioButton rb9;
    private final JRadioButton rb18;
    private final JDateChooser dateChooserDate;
    
    public GridBagLayoutTest() {

        setLayout(new BorderLayout());
        
        addScorePanel = new JPanel();
        addScorePanel.setLayout(new GridBagLayout());
        
        txtScore = new JTextField(3);
        
        rb9 = new JRadioButton("9");
        rb9.setActionCommand("9");
        
        rb18 = new JRadioButton("18");
        rb18.setActionCommand("18");
        rb18.setSelected(true);
        
        ButtonGroup bgHoles = new ButtonGroup();
        bgHoles.add(rb9);
        bgHoles.add(rb18);
        
        dateChooserDate = new JDateChooser();
        
        layoutControls();
        
        add(addScorePanel, BorderLayout.NORTH);
        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(600, 430);                                                          // Juggle for best look
        setMinimumSize(new Dimension(400, 375));
        setLocationRelativeTo(null);
        setVisible(true);
        }
    

    private void layoutControls() {

        Border titleBorder = BorderFactory.
                createTitledBorder("Handicap Add Score");
        
        int space = 15;
        Border spaceBorder = BorderFactory.createEmptyBorder(space, space, 
                space, space);
        
        addScorePanel.setBorder(BorderFactory.createCompoundBorder(spaceBorder, 
                titleBorder));
        
//        setBorder(BorderFactory.createLineBorder(Color.BLACK));

        GridBagConstraints gc = new GridBagConstraints();

        gc.fill = GridBagConstraints.NONE;                                          // Controls preferred size, 
        
        ////////// Score row //////////
        gc.gridy = 0;
        gc.gridx = 0;
        gc.weightx = 1.0;
        gc.weighty = 1.0;
        gc.gridwidth = 2;                                                           // Label 2 cells
        gc.anchor = GridBagConstraints.FIRST_LINE_END;
        gc.insets = new Insets(15, 0, 0, 15);
        addScorePanel.add(new JLabel("Score: "), gc);
        
        gc.gridy = 0;
        gc.gridx = 2;                                                               // Skip over 2nd label cell
        gc.gridwidth = 1;
        gc.anchor = GridBagConstraints.FIRST_LINE_START;
        gc.insets = new Insets(15, 0, 0, 15);
        addScorePanel.add(txtScore, gc);

        ////////// Holes row //////////
        gc.gridy++;
        gc.gridx = 0;
//        gc.weightx = 0.1;
//        gc.weighty = 1.0;
        gc.gridwidth = 2;                                                           // Label 2 cells
        gc.insets = new Insets(15, 0, 0, 15);
        gc.anchor = GridBagConstraints.FIRST_LINE_END;
        addScorePanel.add(new JLabel("Holes Played:"), gc);
        
        gc.gridx = 2;                                                               // Skip over 2nd label cell
//        gc.weightx = 0.1;
        gc.gridwidth = 1;
        gc.insets = new Insets(15, 0, 0, 0);
        gc.anchor = GridBagConstraints.FIRST_LINE_START;
        addScorePanel.add(rb9, gc);
         
        gc.gridx++;                                                                 // Next cell
//        gc.weightx = 1.0;
        gc.gridwidth = 1;
        gc.insets = new Insets(15, 0, 0, 0);
        gc.anchor = GridBagConstraints.FIRST_LINE_START;
        addScorePanel.add(rb18, gc);
        
        ////////// Date row //////////
        gc.gridy++;
        gc.gridx = 0;
//        gc.weightx = 1.0;
//        gc.weighty = 1.0;
        gc.gridwidth = 2;                                                           // Label 2 cells
        gc.insets = new Insets(15, 0, 0, 15);
        gc.anchor = GridBagConstraints.FIRST_LINE_END;
        addScorePanel.add(new JLabel("Date: "), gc);
        
        gc.gridx = 2;                                                               // Skip over 2nd label cell
        gc.gridwidth = 2;                                                           // Date 2 cells
        gc.anchor = GridBagConstraints.FIRST_LINE_START;
        addScorePanel.add(dateChooserDate, gc);
    }

This is what I am trying to do:

Sample output

EDIT based on @camickr:

        ////////// Score row //////////
        gc.gridy = 0;
        gc.gridx = 0;
        gc.weightx = 1.0;
        gc.weighty = 1.0;
        gc.gridwidth = 1;                                   // <-----               // Label 2 cells
        gc.anchor = GridBagConstraints.FIRST_LINE_END;
        gc.insets = new Insets(15, 0, 0, 15);
        addScorePanel.add(new JLabel("Score: "), gc);
        
        gc.gridy = 0;
        gc.gridx = 1;                                       // <-----                // Skip over 2nd label cell
        gc.gridwidth = 2;                                   // <----- 
        gc.anchor = GridBagConstraints.FIRST_LINE_START;
        gc.insets = new Insets(15, 0, 0, 15);
        addScorePanel.add(txtScore, gc);

        ////////// Holes row //////////
        gc.gridy++;
        gc.gridx = 0;
//        gc.weightx = 0.1;
//        gc.weighty = 1.0;
        gc.gridwidth = 1;                                    // <-----              // Label 2 cells
        gc.insets = new Insets(15, 0, 0, 15);
        gc.anchor = GridBagConstraints.FIRST_LINE_END;
        addScorePanel.add(new JLabel("Holes Played:"), gc);
        
        gc.gridx = 1;                                       // <-----               // Skip over 2nd label cell
//        gc.weightx = 0.1;
        gc.gridwidth = 1;
        gc.insets = new Insets(15, 0, 0, 0);
        gc.anchor = GridBagConstraints.FIRST_LINE_START;
        addScorePanel.add(rb9, gc);
         
        gc.gridx = 2;                                       // <-----               // Next cell
//        gc.weightx = 1.0;
        gc.gridwidth = 1;
        gc.insets = new Insets(15, 0, 0, 0);
        gc.anchor = GridBagConstraints.FIRST_LINE_START;
        addScorePanel.add(rb18, gc);
        
        ////////// Date row //////////
        gc.gridy++;
        gc.gridx = 0;
//        gc.weightx = 1.0;
//        gc.weighty = 1.0;
        gc.gridwidth = 1;                                 // <-----                 // Label 2 cells
        gc.insets = new Insets(15, 0, 0, 15);
        gc.anchor = GridBagConstraints.FIRST_LINE_END;
        addScorePanel.add(new JLabel("Date: "), gc);
        
        gc.gridx = 1;                                                               // Skip over 2nd label cell
        gc.gridwidth = 2;                                                           // Date 2 cells
        gc.anchor = GridBagConstraints.FIRST_LINE_START;
        addScorePanel.add(dateChooserDate, gc);

Looks pretty much the same. I think I marked my changes correctly.


Solution

  • Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Laying Out Components Within a Container section.

    I used multiple Swing layouts to get the layout you wanted.

    enter image description here

    All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.

    I used a JFrame. The only reason you would extend a Swing component, or any Java class, is if you want to override one or more of the class methods.

    I put the JRadioButtons inside a JPanel with a FlowLayout.

    I simplified the main JPanel using a GridBagLayout. It's unusual to right justify the JLabels, but I showed you how to do so.

    You probably want to add a JButton to trigger an ActionListener to read the input fields.

    Here's the complete runnable code.

    import java.awt.BorderLayout;
    import java.awt.FlowLayout;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    
    import javax.swing.BorderFactory;
    import javax.swing.ButtonGroup;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JRadioButton;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    import javax.swing.border.Border;
    
    public class GridBagLayoutTest implements Runnable {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new GridBagLayoutTest());
        }
    
        private JTextField txtScore;
        private JRadioButton rb9;
        private JRadioButton rb18;
        private JTextField dateChooserDate;
    
        @Override
        public void run() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.add(createMainPanel(), BorderLayout.CENTER);
    
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        private JPanel createMainPanel() {
            JPanel panel = new JPanel(new GridBagLayout());
            Border titleBorder = BorderFactory
                    .createTitledBorder("Handicap Add Score");
            int space = 15;
            Border spaceBorder = BorderFactory.createEmptyBorder(space, space,
                    space, space);
            panel.setBorder(
                    BorderFactory.createCompoundBorder(spaceBorder, titleBorder));
    
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.anchor = GridBagConstraints.LINE_START;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.insets = new Insets(15, 0, 0, 15);
    
            gbc.gridx = 0;
            gbc.gridy = 0;
            panel.add(createJLabel("Score:"), gbc);
    
            gbc.gridx++;
            txtScore = new JTextField(10);
            panel.add(txtScore, gbc);
    
            gbc.gridx = 0;
            gbc.gridy++;
            panel.add(createJLabel("Holes Played:"), gbc);
    
            gbc.gridx++;
            panel.add(createRadioPanel(), gbc);
    
            gbc.gridx = 0;
            gbc.gridy++;
            panel.add(createJLabel("Date:"), gbc);
    
            gbc.gridx++;
            dateChooserDate = new JTextField(10);
            panel.add(dateChooserDate, gbc);
    
            return panel;
        }
    
        private JLabel createJLabel(String text) {
            JLabel label = new JLabel(text);
            label.setHorizontalAlignment(JLabel.TRAILING);
    
            return label;
        }
    
        private JPanel createRadioPanel() {
            JPanel panel = new JPanel(new FlowLayout());
            rb9 = new JRadioButton("9");
            rb9.setActionCommand("9");
            panel.add(rb9);
    
            rb18 = new JRadioButton("18");
            rb18.setActionCommand("18");
            panel.add(rb18);
    
            ButtonGroup bgHoles = new ButtonGroup();
            bgHoles.add(rb9);
            bgHoles.add(rb18);
    
            return panel;
        }
    
    }