1

I want to use GridBagLayout for a layout that has <= 3 columns, and a variable amount of rows(If anyone knows another layout that can do this easily, please tell me), everytime I press the "add" button a square will be added at the first location that is available. Like so:

|x x x|
|x x x|
|x o  |

The x's are squares, and when I press add a new square should be added where the o is now. I managed to "kind of make it work" like so:

public void addSquare(Square square) {
    c.fill = GridBagConstraints.NONE;
    c.gridx = nrOfSquares % 3;
    c.gridy = (int) (nrOfSquares / 3);
    c.weighty = 1;
    c.weightx = 1;
    c.anchor = GridBagConstraints.NORTHWEST;
    c.insets = new Insets(5, 5, 5, 5);
    this.container.add(square, c);
    this.container.revalidate();
    ++nrOfSquares;
}

the problem is that the second square I add is added like this:

|x  x  |

please note that there is an extra space between the first square and the second one. I have the same problem when an extra row is added.

Now how do I fix my code so that the squares don't "jump" and are added like in the first example I gave?

EDIT: as requested, a better example after I converted it to a regular GridLayout:

public class Square extends JPanel {
   public Square() {
       super();     
       Dimension SIZE = new Dimension(200, 200);
       this.setSize(SIZE);
       this.setPreferredSize(SIZE);
       this.setMinimumSize(SIZE);
       this.setMaximumSize(SIZE);

       this.setBackground(Color.ORANGE);

       this.setVisible(true);
   }
}

public class SquareContainer extends JPanel {
    protected JPanel realContainer;

    public SquareContainer(int width, int height) {
        super();
        this.setLayout(new BorderLayout());
        this.setBackground(Color.WHITE);
        this.setSize(width, height);
        this.realContainer = new JPanel();
        GridLayout layout = new GridLayout(0, 3);
        layout.setHgap(10);
        layout.setVgap(10);
        this.realContainer.setLayout(layout);
        this.realContainer.setBackground(this.getBackground());
        JScrollPane scroller = new JScrollPane(this.realContainer);
        scroller.getVerticalScrollBar().setUnitIncrement(20);
        this.add(scroller, BorderLayout.CENTER);
    }

    public void addSquare(Square square) {
        this.realContainer.add(square);
        this.realContainer.revalidate();
    }
}

And I just add that to a JFrame:

public class TheGreatFrame extends JFrame {
    public TheGreatFrame() {
        super();
        this.setSize(800, 800);
        this.setLocationRelativeTo(null);
        this.setLayout(new BorderLayout());
        this.setResizable(false);

        this.add(new SquareContainer(750, 660), BorderLayout.CENTER);

        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        this.setVisible(true);
    }
}
teuneboon
  • 4,034
  • 5
  • 23
  • 28

2 Answers2

4

A small example program of using GridLayout:

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

public class GridLayoutEg {

   private static void createAndShowGui() {
      final JPanel centerPanel = new JPanel(new GridLayout(0, 3)); 

      JButton addBtn = new JButton(new AbstractAction("Add Button") {

         @Override
         public void actionPerformed(ActionEvent e) {
            centerPanel.add(new JButton("X"));
            centerPanel.revalidate();
            centerPanel.repaint();  

            SwingUtilities.getWindowAncestor(centerPanel).pack();
         }
      });
      JPanel btnPanel = new JPanel();
      btnPanel.add(addBtn);

      JPanel mainPanel = new JPanel(new BorderLayout());
      mainPanel.add(centerPanel, BorderLayout.CENTER);
      mainPanel.add(btnPanel, BorderLayout.PAGE_END);
      JFrame frame = new JFrame("GridLayoutEg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • +1 because this helped me quite a bit, only problem I still have now is that my squares are stretched vertically until I got like 3 rows. EDIT: They are also stretched horizontally, didn't notice immidiatly because the width of the container is almost the same as 3x(square + margin) – teuneboon Oct 23 '11 at 21:41
  • 2
    `frame.setLocationRelativeTo(null);` [Tut-tut](http://stackoverflow.com/questions/7143287/how-to-best-position-swing-guis/). ;) – Andrew Thompson Oct 23 '11 at 21:46
  • @AndrewThompson I added something like that now – teuneboon Oct 23 '11 at 21:58
  • @teuneboon (sigh) IMO, and for the sake of getting help, there are things that are SSCCEs and there are things that are *not* SSCCEs. What you posted is in the latter group. Please read the link very carefully. – Andrew Thompson Oct 23 '11 at 22:07
2

if all JComponents could have the same HEIGHT and WEIGHT, then look for GridLayout

in case that the JComponent couldn't same WEIGHT, then put each "line" to the separate JPanel (by using BorderLayout or BoxLayout) and use GridLayout for put these JPanels into Container

mKorbel
  • 109,525
  • 20
  • 134
  • 319