Ex GridBagLayout e GridBagConstraints (Swing)

Segue um exemplo de uso de GridBagLayout e GridBagConstraints (Layout do Swing) pra quem está sambando com isso!

Não é recomendado usar uma classe interna estática que extende JButton como no código, foi feito assim nesse caso apenas para facilitar a visualização do uso das constraints.

Execute, observe como os botões aparecem, estique e encolha a janela com o mouse, maximize a janela…

Olhe no código como estão configuradas as constraints (GridBagConstraints) de cada botão para entender.

Divirtam-se!

:wink:

[code]package exemplo;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.swing.JButton;
import javax.swing.JFrame;

public class JanelaExemplo extends JFrame {

private static final long serialVersionUID = 1L;

public static void main(String[] args) {
	new JanelaExemplo();
}

/*

-botao01–botao02–botao03–botao04–botao05-
-botao06–botao07–botao08–botao09–botao10-
------botao11------botao12–botao13–botao14-
-botao15–botao16–botao17-|botao18|-botao19-
-botao20–botao21–botao22-| |-botao23-
*/

private List<Botao> listaBotoes;

private Botao botao1;
private Botao botao2;
private Botao botao3;
private Botao botao4;
private Botao botao5;
private Botao botao6;
private Botao botao7;
private Botao botao8;
private Botao botao9;
private Botao botao10;
private Botao botao11;
private Botao botao12;
private Botao botao13;
private Botao botao14;
private Botao botao15;
private Botao botao16;
private Botao botao17;
private Botao botao18;
private Botao botao19;
private Botao botao20;
private Botao botao21;
private Botao botao22;
private Botao botao23;

public JanelaExemplo() {
	super("BOTÕES");
	
	// NOTE QUE NO Jframe COLOCAMOS AS COISAS NO contentPane
	getContentPane().setLayout(new GridBagLayout());
	getContentPane().setPreferredSize(new Dimension(450, 300));

	listaBotoes = new ArrayList<Botao>();
	
	/* LINHA 1, Y = 0 */
	
	botao1 = new Botao(1);
	botao1.posX = 0; // X = 0
	botao1.posY = 0;
	botao1.numCelulasX = 1;
	botao1.numCelulasY = 1;
	botao1.pesoX = 0.2;
	botao1.pesoY = 0.2;
	botao1.ancora = GridBagConstraints.CENTER;
	botao1.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao1);
	
	botao2 = new Botao(2);
	botao2.posX = 1; // X = 1
	botao2.posY = 0;
	botao2.numCelulasX = 1;
	botao2.numCelulasY = 1;
	botao2.pesoX = 0.2;
	botao2.pesoY = 0.2;
	botao2.ancora = GridBagConstraints.CENTER;
	botao2.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao2);
	
	botao3 = new Botao(3);
	botao3.posX = 2; // X = 2
	botao3.posY = 0;
	botao3.numCelulasX = 1;
	botao3.numCelulasY = 1;
	botao3.pesoX = 0.2;
	botao3.pesoY = 0.2;
	botao3.ancora = GridBagConstraints.CENTER;
	botao3.preencher = GridBagConstraints.HORIZONTAL; // ESTICANDO O BOTÃO 3 APENAS NA HORIZONTAL
	listaBotoes.add(botao3);
	
	botao4 = new Botao(4);
	botao4.posX = 3; // X = 3
	botao4.posY = 0;
	botao4.numCelulasX = 1;
	botao4.numCelulasY = 1;
	botao4.pesoX = 0.2;
	botao4.pesoY = 0.2;
	botao4.ancora = GridBagConstraints.CENTER;
	botao4.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao4);
	
	botao5 = new Botao(5);
	botao5.posX = 4; // X = 4
	botao5.posY = 0;
	botao5.numCelulasX = 1;
	botao5.numCelulasY = 1;
	botao5.pesoX = 0.2;
	botao5.pesoY = 0.2;
	botao5.ancora = GridBagConstraints.CENTER;
	botao5.preencher = GridBagConstraints.BOTH;
	botao5.margemInterna = 5; // ADICIONANDO MARGEM INTERNA AO BOTÃO 5. NO CASO DO BOTÃO NÃO FAZ DIFERENÇA
	listaBotoes.add(botao5);
	
	/* LINHA 2, Y = 1 */
	
	botao6 = new Botao(6);
	botao6.posX = 0; // X = 0
	botao6.posY = 1;
	botao6.numCelulasX = 1;
	botao6.numCelulasY = 1;
	botao6.pesoX = 0.2;
	botao6.pesoY = 0.2;
	botao6.ancora = GridBagConstraints.CENTER;
	botao6.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao6);
	
	botao7 = new Botao(7);
	botao7.posX = 1; // X = 1
	botao7.posY = 1;
	botao7.numCelulasX = 1;
	botao7.numCelulasY = 1;
	botao7.pesoX = 0.2;
	botao7.pesoY = 0.2;
	botao7.ancora = GridBagConstraints.CENTER;
	botao7.preencher = GridBagConstraints.VERTICAL; // ESTICANDO O BOTÃO 7 APENAS NA VERTICAL
	listaBotoes.add(botao7);
	
	botao8 = new Botao(8);
	botao8.posX = 2; // X = 2
	botao8.posY = 1;
	botao8.numCelulasX = 1;
	botao8.numCelulasY = 1;
	botao8.pesoX = 0.2;
	botao8.pesoY = 0.2;
	botao8.ancora = GridBagConstraints.CENTER;
	botao8.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao8);
	
	botao9 = new Botao(9);
	botao9.posX = 3; // X = 3
	botao9.posY = 1;
	botao9.numCelulasX = 1;
	botao9.numCelulasY = 1;
	botao9.pesoX = 0.2;
	botao9.pesoY = 0.2;
	botao9.ancora = GridBagConstraints.CENTER;
	botao9.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao9);
	
	botao10 = new Botao(10);
	botao10.posX = 4; // X = 4
	botao10.posY = 1;
	botao10.numCelulasX = 1;
	botao10.numCelulasY = 1;
	botao10.pesoX = 0.2;
	botao10.pesoY = 0.2;
	botao10.ancora = GridBagConstraints.CENTER;
	botao10.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao10);
	
	/* LINHA 3, Y = 2 */
	
	botao11 = new Botao(11);
	botao11.posX = 0; // X = 0
	botao11.posY = 2;
	botao11.numCelulasX = 2; // DUAS CÉLULAS EM X
	botao11.numCelulasY = 1;
	botao11.pesoX = 0.2; // Repare que esse é o peso para cada célula ocupada
	botao11.pesoY = 0.2;
	botao11.ancora = GridBagConstraints.CENTER;
	botao11.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao11);

// botao11 // REPRESENTA A SEGUNDA CÉLULA HORIZONTAL OCUPADA PELO BOTÃO 11

	botao12 = new Botao(12);
	botao12.posX = 2; // X = 2, A POSIÇÃO 0 E 1 ESTÃO OCUPADAS PELO BOTÃO 11
	botao12.posY = 2;
	botao12.numCelulasX = 1;
	botao12.numCelulasY = 1;
	botao12.pesoX = 0.2;
	botao12.pesoY = 0.2;
	botao12.ancora = GridBagConstraints.CENTER;
	botao12.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao12);
	
	botao13 = new Botao(13);
	botao13.posX = 3; // X = 3
	botao13.posY = 2;
	botao13.numCelulasX = 1;
	botao13.numCelulasY = 1;
	botao13.pesoX = 0.2;
	botao13.pesoY = 0.2;
	botao13.ancora = GridBagConstraints.CENTER;
	botao13.preencher = GridBagConstraints.BOTH;
	botao13.margemExterna = 3; // ADICIONANDO MARGEM EXTERNA AO BOTÃO 13
	listaBotoes.add(botao13);
	
	botao14 = new Botao(14);
	botao14.posX = 4; // X = 4
	botao14.posY = 2;
	botao14.numCelulasX = 1;
	botao14.numCelulasY = 1;
	botao14.pesoX = 0.2;
	botao14.pesoY = 0.2;
	botao14.ancora = GridBagConstraints.CENTER;
	botao14.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao14);
	
	/* LINHA 4, Y = 3 */
	
	botao15 = new Botao(15);
	botao15.posX = 0; // X = 0
	botao15.posY = 3;
	botao15.numCelulasX = 1;
	botao15.numCelulasY = 1;
	botao15.pesoX = 0.2;
	botao15.pesoY = 0.2;
	botao15.ancora = GridBagConstraints.CENTER;
	botao15.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao15);
	
	botao16 = new Botao(16);
	botao16.posX = 1; // X = 1
	botao16.posY = 3;
	botao16.numCelulasX = 1;
	botao16.numCelulasY = 1;
	botao16.pesoX = 0.2;
	botao16.pesoY = 0.2;
	botao16.ancora = GridBagConstraints.NORTHEAST; // ALINHANDO O BOTÃO 16 NO TOPO À DIREITA DA SUA CÉLULA
	botao16.preencher = GridBagConstraints.NONE; // NÃO ESTICANDO O BOTÃO 16
	listaBotoes.add(botao16);
	
	botao17 = new Botao(17);
	botao17.posX = 2; // X = 2
	botao17.posY = 3;
	botao17.numCelulasX = 1;
	botao17.numCelulasY = 1;
	botao17.pesoX = 0.2;
	botao17.pesoY = 0.2;
	botao17.ancora = GridBagConstraints.CENTER;
	botao17.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao17);
	
	botao18 = new Botao(18);
	botao18.posX = 3; // X = 3
	botao18.posY = 3;
	botao18.numCelulasX = 1;
	botao18.numCelulasY = 2; // DUAS CÉLULAS EM Y
	botao18.pesoX = 0.2;
	botao18.pesoY = 0.2; // Repare que esse é o peso para cada célula ocupada
	botao18.ancora = GridBagConstraints.CENTER;
	botao18.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao18);
	
	botao19 = new Botao(19);
	botao19.posX = 4; // X = 4
	botao19.posY = 3;
	botao19.numCelulasX = 1;
	botao19.numCelulasY = 1;
	botao19.pesoX = 0.2;
	botao19.pesoY = 0.2;
	botao19.ancora = GridBagConstraints.WEST; // ALINHANDO O BOTÃO 19 À ESQUERDA DA SUA CÉLULA
	botao19.preencher = GridBagConstraints.NONE; // NÃO ESTICANDO O BOTÃO 19
	listaBotoes.add(botao19);
	
	/* LINHA 5, Y = 4 */
	
	botao20 = new Botao(20);
	botao20.posX = 0; // X = 0
	botao20.posY = 4;
	botao20.numCelulasX = 1;
	botao20.numCelulasY = 1;
	botao20.pesoX = 0.2;
	botao20.pesoY = 0.2;
	botao20.ancora = GridBagConstraints.CENTER;
	botao20.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao20);
	
	botao21 = new Botao(21);
	botao21.posX = 1; // X = 1
	botao21.posY = 4;
	botao21.numCelulasX = 1;
	botao21.numCelulasY = 1;
	botao21.pesoX = 0.2;
	botao21.pesoY = 0.2;
	botao21.ancora = GridBagConstraints.CENTER;
	botao21.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao21);
	
	botao22 = new Botao(22);
	botao22.posX = 2; // X = 2
	botao22.posY = 4;
	botao22.numCelulasX = 1;
	botao22.numCelulasY = 1;
	botao22.pesoX = 0.2;
	botao22.pesoY = 0.2;
	botao22.ancora = GridBagConstraints.CENTER;
	botao22.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao22);

// botao18 // REPRESENTA A SEGUNDA CÉLULA VERTICAL OCUPADA PELO BOTÃO 18

	botao23 = new Botao(23);
	botao23.posX = 4; // X = 4, A POSIÇÃO 3 ESTÁ OCUPADA PELO BOTÃO 18 NESSA LINHA E NA DE CIMA
	botao23.posY = 4;
	botao23.numCelulasX = 1;
	botao23.numCelulasY = 1;
	botao23.pesoX = 0.2;
	botao23.pesoY = 0.2;
	botao23.ancora = GridBagConstraints.CENTER;
	botao23.preencher = GridBagConstraints.BOTH;
	listaBotoes.add(botao23);
	
	addBotoes();
	
	pack();
	setDefaultCloseOperation(EXIT_ON_CLOSE);
	setLocationRelativeTo(null);
	setVisible(true);
}

private void addBotoes() {
	for(Botao botao : listaBotoes) {
		GridBagConstraints gbc = new GridBagConstraints();
		
		gbc.anchor = botao.ancora;
		
		gbc.fill = botao.preencher;
		
		gbc.gridwidth = botao.numCelulasX;
		gbc.gridheight = botao.numCelulasY;
		
		gbc.gridx = botao.posX;
		gbc.gridy = botao.posY;
		
		gbc.weightx = botao.pesoX;
		gbc.weighty = botao.pesoY;
		
		gbc.ipadx = botao.margemInterna;
		gbc.ipady = botao.margemInterna;
		
		gbc.insets = new Insets(botao.margemExterna, botao.margemExterna, botao.margemExterna, botao.margemExterna);
		
		// NOTE QUE NO Jframe COLOCAMOS AS COISAS NO contentPane
		getContentPane().add(botao, gbc);
	}
}

private static class Botao extends JButton {

	private static final long serialVersionUID = 1L;
	
	/** Formatador numérico. */
	private static final NumberFormat nFormat;
	
	static {
		nFormat = NumberFormat.getInstance(new Locale("pt", "BR"));
		nFormat.setMinimumIntegerDigits(2);
		nFormat.setMaximumIntegerDigits(2);
		nFormat.setMinimumFractionDigits(0);
		nFormat.setMaximumFractionDigits(0);
	}
	
	/** Posição x na tabela. */
	private int posX;
	
	/** Posição y na tabela. */
	private int posY;
	
	/** Quantidade de células que ocupa em x. */
	private int numCelulasX;
	
	/** Quantidade de células que ocupa em y. */
	private int numCelulasY;
	
	/**
	 * Peso na largura da célula entre 0 e 1 (0 e 100%).
	 * 
	 * Exemplo: 0.8 indica que essa célula vai ocupar 80% da largura da tabela.
	 * 
	 * A soma dos pesos em x deve resultar em 1 (100%).
	 * 
	 * O valor padrão é 0, indicando que o componente vai
	 * ficar com a largura padrão dele, sem redimensionamento.
	 */
	private double pesoX;
	
	/**
	 * Peso na altura da célula entre 0 e 1 (0 e 100%)
	 * 
	 * Exemplo: 0.8 indica que essa célula vai ocupar 80% da altura da tabela.
	 * 
	 * A soma dos pesos em y deve resultar em 1 (100%).
	 * 
	 * O valor padrão é 0, indicando que o componente vai
	 * ficar com a altura padrão dele, sem redimensionamento.
	 */
	private double pesoY;
	
	/**
	 * Constante referenciando onde o componente ficará na célula.
	 * 
	 * Ex: Canto superior esquerdo, à direita, etc...
	 */
	private int ancora;
	
	/**
	 * Constante indicando se o componente deverá ser esticado na horizontal,
	 * na vertical, em nenhum ou nos dois quando a célula for redimensionada.
	 * 
	 * Usado em conjunto com o pesoX e o pesoY.
	 */
	private int preencher;
	
	/** Tamanho da margem externa, espaço entre o componente e a borda da sua célula. */
	private int margemExterna;
	
	/** Tamanho da margem interna, espaço entre o componente e o seu conteúdo. */
	private int margemInterna;
	
	public Botao(int numero) {
        super(nFormat.format(numero));
    }
	
}

}[/code]