Interfaces Gráficas: Interações Complexas 21 21.2 Gerenciando leiautes 21.2.6 GridBagLayout Este gerente de leiaute dispõe os componentes sob seu controle em um reticulado, permitindo a especificação da quantidade de células que cada componente deve ocupar. Desse modo, podemos construir reticulados do tipo mostrado na Figura 21.1 (A). A Figura 21.1 (B) mostra os nove componentes da figura à esquerda ocupando as células de um reticulado com 5 × 3 células. Os componentes comp-1, comp-2 e comp-3 ocupam uma célula cada um. O componente comp-4 ocupa duas células na segunda linha e comp-6 ocupa duas células na terceira linha. O componente comp-5 ocupa duas células na terceira coluna, enquanto comp-7 e comp-8 ocupam uma célula cada um. Já o componente comp-9 ocupa quatro células no canto inferior direito do reticulado. O gerente GridBagLayout associa a cada componente um conjunto de restrições. Estas restrições são implementadas por um objeto da classe GridBagConstraints e definem, por exemplo, quantas células o componente ocupa e o seu alinhamento em relação às células ocupadas. O uso do gerente GridBagLayout envolve os seguintes passos: 1. Criar um gerente de leiaute, gl, da classe GridBagLayout. 2. Criar um objeto, rst, da classe GridBagConstraints. 3. Criar o componente c que se quer adicionar. 4. Definir através do objeto rst as restrições que c deve obedecer. 2 Interfaces Gráficas Figura 21.1. Exemplo de reticulado de um GridBagLayout comp−1 comp−2 comp−3 comp−1 comp−2 comp−3 comp−4 comp−4 comp−5 comp−5 comp−6 comp−6 comp−7 comp−9 comp−7 comp−9 comp−8 comp−8 (A) (B) 5. Associar através do método setConstraints (executado pelo gerente de leiaute gl) o componente c às suas restrições rst. 6. Adicionar o componente c. 7. Repetir os passos 2-6 para cada novo componente. As restrições de cada componente são definidas através dos atributos do objeto usado para especificá-las. Caso um componente seja adicionado sem que um objeto da classe GridBagConstraints esteja associado a ele, o gerente de leiaute adota um valor padrão para cada restrição. Os atributos e constantes mais comuns são: gridwidth. Define o número de células horizontais (colunas) que o componente ocupará. A constante REMAINDER faz com que o componente ocupe todas as células restantes na linha, finalizando a linha corrente. O valor padrão é 1. gridheight. Define o número de células verticais (linhas) que o componente ocupará. A constante REMAINDER faz com que o componente ocupe todas as células restantes na coluna corrente. o valor padrão é 1. gridx. Define a coluna em que o componente será colocado. A constante RELATIVE especifica que o componente será colocado imediatamente após o último componente incluı́do, na mesma linha ou na primeira célula da próxima linha, se o último componente tiver finalizado sua linha corrente. Este é o comportamento padrão. gridy. Define a linha em que o componente será colocado. A constante RELATIVE especifica que o componente será colocado imediatamente abaixo do último componente incluı́do. Este é o comportamento padrão. 21.2 Gerenciando leiautes 3 O tamanho das células é calculado de modo a comportar o componente nelas contido. Ao final, a largura das colunas e a altura das linhas são ajustadas: a largura de uma coluna é dada pela largura da maior célula que a coluna contém; o mesmo ocorre para a altura de uma linha. Assim, é possı́vel termos componentes cujo tamanho é menor que a área (linhas e colunas) a eles reservada. O posicionamento de cada componente em relação ao conjunto de células que o contém é controlado pelos seguintes atributos: fill. Define como o componente deve ser redimensionado para ocupar a área a ele reservada. Pode assumir uma das seguintes constantes de GridBagConstraints: VERTICAL. Faz com que o componente ocupe verticalmente toda a área a ele reservada. HORIZONTAL. Faz com que o componente ocupe horizontalmente toda a área a ele reservada. BOTH. Faz com que o componente ocupe toda a área a ele reservada. NONE. Não redimensiona o componente. Este é o valor padrão. anchor. Define a posição do componente em relação a área a ele reservada. Pode assumir uma das seguintes constantes de GridBagConstraints: NORTH. Posiciona o componente no topo da área. SOUTH. Posiciona o componente na base da área. EAST. O componente é alinhado à direita. WEST. O componente é alinhado à esquerda. CENTER. O componente é posicionado no centro da área. Este é o valor padrão. Podemos também ter o aparecimento de espaços extras (horizontais ou verticais) em função do redimensionamento da janela na qual o reticulado está inserido. Os espaços extras são distribuı́dos proporcionalmente aos pesos de cada área. weightx. Define o peso horizontal da área associada ao componente. O peso padrão é 0, indicando que a área não recebe espaços extras. weighty. Define o peso vertical da área associada ao componente. O peso padrão é 0, indicando que a área não recebe espaços extras. Exemplo 21.1. Suponha que uma linha contenha três áreas com pesos horizontais 1.0, 3.0 e 2.0. Se a janela que contém o reticulado é redimensionada provocando o aparecimento de 120 pixels horizontais extras, eles serão distribuı́dos do seguinte modo: 20 pixels na primeira, 60 na segunda e 40 na terceira área. 4 Interfaces Gráficas Os objetos da classe GridBagConstraints também possuem os atributos insets, ipadx e ipady que permitem a especificação de espaços entre componentes e células. O uso desses atributos deve ser pesquisado na documentação da classe. Exemplo 21.2. O programa a seguir cria uma janela com nove rótulos dispostos como indicados na Figura 21.1 (A). Os rótulos criados nesse exemplo possuem uma borda para melhor visualização do comportamento do gerente de leiaute. A borda é criada com o método setBorder (linha 8) tendo como argumento um objeto da classe LineBorder (criado na linha 7). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import javax.swing.*; import java.awt.*; import javax.swing.border.*; class C21ExemploN1 { static void adicionaComp(String rotulo, Container conteudo, GridBagLayout gl, GridBagConstraints rst) { LineBorder borda = new LineBorder(Color.black); JLabel comp = new JLabel(rotulo); comp.setBorder(borda); gl.setConstraints(comp,rst); conteudo.add(comp); } public static void main(String[] arg) { JFrame janela = new JFrame("Exemplo Gerente GridBagLayout"); Container conteudo = janela.getContentPane(); GridBagLayout gl = new GridBagLayout(); conteudo.setLayout(gl); GridBagConstraints rst = new GridBagConstraints(); 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 adicionaComp("comp-1", conteudo, gl, rst); adicionaComp("comp-2", conteudo, gl, rst); rst.gridwidth = GridBagConstraints.REMAINDER; adicionaComp("comp-3", conteudo, gl, rst); rst.fill = GridBagConstraints.BOTH; rst.gridwidth=2; rst.weighty=1.0; adicionaComp("comp-4", conteudo, gl, rst); rst.gridwidth= 1; rst.gridheight = 2; adicionaComp("comp-5", conteudo, gl, rst); rst.gridx = 0; rst.gridwidth = 2; rst.gridheight = 1; adicionaComp("comp-6", conteudo, gl, rst); rst.gridy=3; rst.gridwidth = 1; adicionaComp("comp-7", conteudo, gl, rst); rst.gridy = 4; adicionaComp("comp-8", conteudo, gl, rst); rst.gridx = GridBagConstraints.RELATIVE; rst.gridy = 3; rst.gridwidth = GridBagConstraints.REMAINDER; rst.gridheight = GridBagConstraints.REMAINDER; 21.2 Gerenciando leiautes 5 adicionaComp("comp-9", conteudo, gl, rst); 37 38 janela.setDefaultCloseOperation (WindowConstants.EXIT_ON_CLOSE); janela.pack(); janela.setVisible(true); 39 40 41 42 } 43 44 } O método adicionaComp (linhas 5 a 11) cria um rótulo comp (linha 8) e o adiciona ao contêiner conteudo (linha 10). As restrições que o rótulo deve obedecer são especificadas pelo objeto rst, através do método setConstraints, na linha 9. O método principal, após criar a janela (linha 13), definir o gerente de leiaute (linhas 15-16) e criar o objeto usado para especificar as restrições (linha 17), realiza sucessivas chamadas ao método adicionaComp, em cada uma passa como argumentos o rótulo do componente que será criado, o contêiner onde o componente será adicionado, o gerente de leiaute e o objeto especificando as restrições. O programa modifica os atributos do objeto rst para especificar as restrições que cada componente deve obedecer. Na linha 24, por exemplo, o atributo gridwidth é usado para especificar que o componente comp-4 deve ocupar 2 células horizontais (a quantidade de células verticais continua com o valor padrão definido para gridheight). Também nesta linha definimos que este componente tem peso vertical (weighty) igual a 1. O método pack (linha 41) faz com que o tamanho da janela seja definido em função do tamanho dos seus componentes, neste caso o reticulado controlado pelo gerente GridBagLayout. A janela torna-se visı́vel pelo comando da linha 42.