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!
[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]