Search code examples
javaswinglayout-managergridbaglayout

Swing GridBagLayout acting out


In a program I'm writing I want to have 10 text fields aligned vertically. Instead I get this:

What it looks like

code here:

import java.awt.*;
import java.util.Random;
import javax.swing.*;
import java.awt.event.*;

public class Gsb extends JFrame {

    JTextField word1;
    JTextField word2;
    JTextField word3;
    JTextField word4;
    JTextField word5;
    JTextField word6;
    JTextField word7;
    JTextField word8;
    JTextField word9;
    JTextField word10;
    JButton gofor;
    JButton rego;
    JTextArea Stuff;
    JPanel panel;
    JPanel texts;
    JPanel buttons;
    JButton Quit;
    JPanel bigt;
    String[] words = new String[20];
    static int[] randnums = new int[20]; 

    int i = 0;

    public static void main(String[] args) {

        new Gsb();
        Random Rand = new Random();

        int counter = 0;
        int rand;
        int[] pick = new int[20];
        for(int i = 0; i < 20; i++)
        {
            rand = Rand.nextInt(20) + 1;
            if (CheckForDuplicate(pick, rand, counter))
            {
                pick[i] = rand;
                counter++;
            }
            else
            {
                i--;
            }
        }
        for(int p = 0; p < 20; p++) {
            randnums[p] = pick[p] - 1;
        }
    }

    static boolean CheckForDuplicate(int[] array, int number, int counter)
    {
        for (int i = 0; i < counter; i++)
        {
            if (array[i] == number)
            {
                return false;
            }
        }

        return true;   
    }

    public Gsb() {

        Toolkit tk = Toolkit.getDefaultToolkit();
        Dimension dim = tk.getScreenSize();

        int xPos = (dim.width / 2) - (this.getWidth() / 2);
        int yPos = (dim.height / 2) - (this.getHeight() / 2);
        this.setLocation(xPos, yPos);
        GridBagConstraints c = new GridBagConstraints();
        GridBagConstraints d = new GridBagConstraints();
        this.setSize(500, 500); 
        this.setTitle("checker");
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        panel = new JPanel();
        texts = new JPanel();
        buttons = new JPanel();
        bigt = new JPanel();
        word1 = new JTextField(10);
        word2 = new JTextField(10);
        word3 = new JTextField(10);
        word4 = new JTextField(10);
        word5 = new JTextField(10);
        word6 = new JTextField(10);
        word7 = new JTextField(10);
        word8 = new JTextField(10);
        word9 = new JTextField(10);
        word10 = new JTextField(10);
        gofor = new JButton("BONANZA!");
        rego = new JButton("Restart");
        Stuff = new JTextArea(40, 40);
        Quit = new JButton("Exit");
        Stuff.setLineWrap(true);
        Stuff.setWrapStyleWord(true);
        Stuff.setText("welcome to the google search bonanza! first user write 10 random words and press BONANZA!");
        JScrollPane useless = new JScrollPane(Stuff, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        panel.setLayout(new GridBagLayout());
        texts.setLayout(new GridBagLayout());
        buttons.setLayout(new GridBagLayout());
        bigt.setLayout(new GridBagLayout());
        c.fill = GridBagConstraints.CENTER;
        d.fill = GridBagConstraints.RELATIVE;

        d.gridx = 0;
        d.gridy = 0;
        texts.add(word1, d);
        d.gridx = 0;
        d.gridy = 1;
        texts.add(word2, d);
        d.gridx = 0;
        d.gridy = 2;
        texts.add(word3, d);
        d.gridx = 0;
        d.gridy = 3;
        texts.add(word4, d);
        d.gridx = 0;
        d.gridy = 4;
        texts.add(word5, d);
        d.gridx = 0;
        d.gridy = 5;
        texts.add(word6, d);
        d.gridx = 0;
        d.gridy = 6;
        texts.add(word7, d);
        d.gridx = 0;
        d.gridy = 7;
        texts.add(word8, d);
        d.gridx = 0;
        d.gridy = 8;
        texts.add(word9, d);
        d.gridx = 0;
        d.gridy = 9;
        texts.add(word10);
        c.gridx = 10;
        c.gridy = 0;
        buttons.add(gofor,c);
        c.gridx = 9;
        c.gridy = 0;
        buttons.add(Quit,c);
        c.gridx = 8;
        c.gridy = 0;
        buttons.add(rego ,c);
        Bonanza bonanzer = new Bonanza();
        Bonanzatwo bon2 = new Bonanzatwo();
        Reset Reseter = new Reset();
        Exit Exiter = new Exit();
        rego.addActionListener(Reseter);
        gofor.addActionListener(bonanzer);
        gofor.addActionListener(bon2);
        Quit.addActionListener(Exiter);
        bigt.add(Stuff);
        c.gridheight = 20;
        c.gridx = 0;
        c.gridy = 0;
        panel.add(texts, c);

        panel.add(buttons);


        panel.add(bigt);
        panel.add(useless);
        this.add(panel);
        this.setExtendedState(JFrame.MAXIMIZED_BOTH); 
        this.setUndecorated(true);
        this.setVisible(true);
        this.setTitle("The Google search bonanza");
    }

basically if it wasn't clear, im going for something like this:

What I'm going for


Solution

  • Don't use a GridBagLayout when you want to create a grid of something -- use a GridLayout, here with 1 column and 0 (for variable number of) rows. You can create a JPanel just for the JTextFields, give it a GridLayout, and then add this JPanel to the main GUI using a GridBagLayout if you wish, but the key here is to nest JPanels, each using its own layout.

    Other suggestion, when I see variables like:

    JTextField word1;
    JTextField word2;
    JTextField word3;
    JTextField word4;
    JTextField word5;
    JTextField word6;
    JTextField word7;
    JTextField word8;
    JTextField word9;
    JTextField word10;
    

    I think, doesn't her really want to use an array or ArrayList here? Or perhaps a JTable.

    Also, you're adding your JTextArea to a JScrollPane but then adding the JTextArea and not the JScrollPane to the GUI.

    For example:

    import java.awt.BorderLayout;
    import java.awt.GridBagLayout;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import javax.swing.*;
    
    public class Gsb2 extends JPanel {
        private static final int WORD_FIELD_COUNT = 10;
        private static final int COL_SIZE = 10;
        private static final int TA_ROWS = 40;
        private static final int TA_COLS = 40;
        private JTextField[] wordFields = new JTextField[WORD_FIELD_COUNT];
        private int rows;
        private JTextArea stuffArea = new JTextArea(TA_ROWS, TA_COLS);
    
        public Gsb2() {
            JPanel wordFieldsPanel = new JPanel(new GridLayout(0, 1));
            for (int i = 0; i < wordFields.length; i++) {
                wordFields[i] = new JTextField(COL_SIZE);
                wordFieldsPanel.add(wordFields[i]);
            }
    
            JPanel wrapWordFieldsPanel = new JPanel(new GridBagLayout());
            wrapWordFieldsPanel.add(wordFieldsPanel);
    
            JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
            buttonPanel.add(new JButton(new MyAction("Restart", KeyEvent.VK_R)));
            buttonPanel.add(new JButton(new MyAction("Exit", KeyEvent.VK_X)));
            buttonPanel.add(new JButton(new MyAction("BONANZA!", KeyEvent.VK_B)));
    
            JScrollPane scrollPane = new JScrollPane(stuffArea);
    
            JPanel rightPanel = new JPanel(new BorderLayout(5, 5));
            rightPanel.add(wrapWordFieldsPanel, BorderLayout.CENTER);
            rightPanel.add(buttonPanel, BorderLayout.PAGE_END);
    
            setLayout(new BorderLayout(5, 5));
            setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            add(rightPanel, BorderLayout.LINE_START);
            add(scrollPane, BorderLayout.CENTER);
    
        }
    
        private class MyAction extends AbstractAction {
            public MyAction(String name, int mnemonic) {
                super(name);
                putValue(MNEMONIC_KEY, mnemonic);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO add code
    
            }
        }
    
        private static void createAndShowGui() {
            Gsb2 mainPanel = new Gsb2();
    
            JFrame frame = new JFrame("Gsb2");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    

    OK, OK, to "match spec", use BoxLayout:

    import java.awt.GridBagLayout;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import javax.swing.*;
    
    public class Gsb3 extends JPanel {
        private static final int WORD_FIELD_COUNT = 10;
        private static final int COL_SIZE = 10;
        private static final int TA_ROWS = 40;
        private static final int TA_COLS = 40;
        private JTextField[] wordFields = new JTextField[WORD_FIELD_COUNT];
        private int rows;
        private JTextArea stuffArea = new JTextArea(TA_ROWS, TA_COLS);
    
        public Gsb3() {
            JPanel wordFieldsPanel = new JPanel(new GridLayout(0, 1));
            for (int i = 0; i < wordFields.length; i++) {
                wordFields[i] = new JTextField(COL_SIZE);
                wordFieldsPanel.add(wordFields[i]);
            }
    
            JPanel wrapWordFieldsPanel = new JPanel(new GridBagLayout());
            wrapWordFieldsPanel.add(wordFieldsPanel);
    
            JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
            buttonPanel.add(new JButton(new MyAction("Restart", KeyEvent.VK_R)));
            buttonPanel.add(new JButton(new MyAction("Exit", KeyEvent.VK_X)));
            buttonPanel.add(new JButton(new MyAction("BONANZA!", KeyEvent.VK_B)));
            buttonPanel.setMaximumSize(buttonPanel.getPreferredSize());
    
            JScrollPane scrollPane = new JScrollPane(stuffArea);
    
            setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
            setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            add(wrapWordFieldsPanel);
            add(Box.createHorizontalStrut(5));
            add(buttonPanel);
            add(Box.createHorizontalStrut(5));
            add(scrollPane);
    
        }
    
        private class MyAction extends AbstractAction {
            public MyAction(String name, int mnemonic) {
                super(name);
                putValue(MNEMONIC_KEY, mnemonic);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO add code
    
            }
        }
    
        private static void createAndShowGui() {
            Gsb3 mainPanel = new Gsb3();
    
            JFrame frame = new JFrame("Gsb2");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }