Is there any way to get GridLayout to honor the empty cells, so the buttons in both JPanels are the same size?
It is certainly doable with GridLayout
, simply 'fill' the blank squares with a JLabel
that has no text.
E.G. Here are two grid layouts, both padded to 3 rows.

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.LineBorder;
class FillGridLayout {
public static final JComponent getPaddedGrid(
ArrayList<BufferedImage> images, int width, int height) {
JPanel p = new JPanel(new GridLayout(height, width, 2, 2));
p.setBorder(new LineBorder(Color.RED));
int count = 0;
for (BufferedImage bi : images) {
p.add(new JButton(new ImageIcon(bi)));
count++;
}
for (int ii=count; ii<width*height; ii++ ) {
// add invisible component
p.add(new JLabel());
}
return p;
}
public static void main(String[] args) {
final ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
int s = 16;
for (int ii = s/4; ii < s; ii+=s/4) {
images.add(new BufferedImage(ii, s, BufferedImage.TYPE_INT_RGB));
images.add(new BufferedImage(s, ii, BufferedImage.TYPE_INT_RGB));
}
Runnable r = new Runnable() {
@Override
public void run() {
JPanel gui = new JPanel(new BorderLayout(3,3));
gui.add(getPaddedGrid(images, 3, 3), BorderLayout.LINE_START);
gui.add(getPaddedGrid(images, 4, 3), BorderLayout.LINE_END);
JOptionPane.showMessageDialog(null, gui);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}