Utilizando FormsLayout para criação de interfaces gráficas – Parte II

 

Na primeira parte do artigo foram vistos alguns conceitos básicos do framework FormsLayout de JGoodies. Nesta segunda parte, serão tratadas algumas classes presentes no pacote que auxiliam a montagem de interfaces gráficas.

 

ButtonBarBuilder, DefaultFormBuilder e PanelBuilder

Voltando ao código-fonte da primeira parte do artigo, no momento da inserção de componentes era feita uma chamada a add(... do painél a ser retornado, passando o componente e sua posição, ou seja, os valores x e y de cada um.

 

As classes ButtonBarBuilder, DefaultFormBuilder e PanelBuilder (presentes no pacote com.jgoodies.forms.builder) são utilizadas para adição de componentes de uma forma muito mais simples que a adição manual.

 

É interessante destacar que todas elas possuem o método getPanel() que retorna um JPanel pronto para ser adicionado ao container da aplicação.

 

A nova interface gráfica

Será construída, para exemplificar o uso das três classes citadas anteriormente, uma interface gráfica um pouco mais robusta que a anterior. Desta vez serão adicionados três painéis; o primeiro contendo os dados de cadastro de um usuário; o segundo contendo alguns itens representando os interesses e os gostos do usuário e o terceiro é apenas um painél contendo os botões para envio dos dados e outras funcionalidades.

 

Não será trabalhado o layout final da aplicação, visto que o artigo está focado na organização interna de um painél de acordo com a classe utilizada. Mas de qualquer maneira, o leitor pode criar novos painéis e organizá-los da forma que achar mais conveniente após conhecer as ferramentas presentes no framework.

 

A Listagem 01 exibe a classe Form sem os métodos responsáveis pelos painéis.

 

package br.com.jm.forms;

 

import java.awt.FlowLayout;

 

import javax.swing.BorderFactory;

import javax.swing.JButton;

import javax.swing.JCheckBox;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JTextField;

import javax.swing.UIManager;

 

import com.jgoodies.forms.builder.ButtonBarBuilder;

import com.jgoodies.forms.builder.DefaultFormBuilder;

import com.jgoodies.forms.builder.PanelBuilder;

import com.jgoodies.forms.layout.CellConstraints;

import com.jgoodies.forms.layout.FormLayout;

 

public class Form extends JFrame{

     

      private CellConstraints constraints = new CellConstraints();

     

      private JTextField tNome = new JTextField();

      private JTextField tEndereco = new JTextField();

      private JTextField tNumero = new JTextField();

      private JTextField tBairro = new JTextField();

      private JTextField tCEP = new JTextField("xxxxx-xxx");

     

      public Form(){

            super("Formulário com FormsLayout");

            super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            super.setLayout(new FlowLayout());

            this.initComponents();

            super.pack();

      }

     

      private void initComponents(){

            FormLayout layout = new FormLayout("c:p");

            DefaultFormBuilder builder = new DefaultFormBuilder(layout);

           

            builder.append(getPanelDadosPessoais());

            builder.append(getPanelInteresses());

            builder.append(getButtonBar());

           

            super.getContentPane().add(builder.getPanel());

      }

 

      //...

      //métodos dos painéis

      //...

     

      public static void main(String[] args){

            try{

                  UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

            }catch(Exception exception){}

           

            Form form = new Form();

            form.setVisible(true);

      }

}

Listagem 01

 

Inicialmente declara-se uma instância de CellConstraints - como variável de classe pois desta vez ela será utilizada em mais de um método, visto que, diferente de cada instância de FormLayout, ela pode ser única para toda a classe.

 

O método initComponents() faz uso de DefaultFormBuilder, mas esta classe será descrita mais abaixo em seu método correspondente. O que há de interessante aqui são as chamadas a getPanelDadosPessoais, getPanelInteresses e getButtonBar.

 

A Listagem 02 mostra a criação do primeiro método de retorno de painéis.

 

private JPanel getPanelDadosPessoais(){

      FormLayout layout = new FormLayout(

            "left:p, 3dlu, max(150dlu;pref), 3dlu, left:p, 3dlu, max(75dlu;pref)",

            "p, 3dlu, p, 3dlu, p" );

      PanelBuilder builder = new PanelBuilder(layout);

      builder.setBorder(BorderFactory.createTitledBorder("Dados Pessoais:"));

     

      builder.addLabel("Nome:", constraints.xy(1, 1));

      builder.add(tNome, constraints.xyw(3, 1, 5));

      builder.addLabel("Endereço:", constraints.xy(1, 3));

      builder.add(tEndereco, constraints.xy(3, 3));

      builder.addLabel("Nº:", constraints.xy(5, 3));

      builder.add(tNumero, constraints.xy(7, 3));

      builder.addLabel("Bairro:", constraints.xy(1, 5));

      builder.add(tBairro, constraints.xy(3, 5));

      builder.addLabel("CEP:", constraints.xy(5, 5));

      builder.add(tCEP, constraints.xy(7, 5));

                 

      return builder.getPanel();

}

Listagem 02

 

Desta vez será ignorada a etapa do “rascunho” da interface no papel, como visto na primeira parte do artigo.

 

As Strings passadas ao construtor de FormLayout contém medidas não vistas anteriormente, como “left:p”, que nada mais é do que uma abreviação para “left:pref”, ou seja, o tamanho definido alinhado à esquerda, ideal para labels, “max(...” que representa o tamanho “mínimo –> máximo” de um componente.

Para confecção deste painél, será utilizada a classe PanelBuilder, que não difere muito da adição manual vista anteriormente.

 

O que se destaca na classe é a capacidade de adição de labels para os componentes, evitando assim a criação de JLabels, para o caso que eles não sofrem alteração alguma durante a execução.

 

No final do método, é retornado um painél obtido da classe utilizada para adição de componentes através do método getPanel().

 

A Listagem 03 representa o método getPanelInteresses().

 

private JPanel getPanelInteresses(){

      FormLayout layout = new FormLayout("l:p, 4dlu, max(75dlu;pref)");

      DefaultFormBuilder builder = new DefaultFormBuilder(layout);

      builder.setBorder(BorderFactory.createTitledBorder("Sobre você..."));

                 

      JCheckBox[] interesses = new JCheckBox[4];

      JTextField[] melhores = new JTextField[4];

      for(int i = 0; i < interesses.length; i++){

            interesses[i] = new JCheckBox();

            melhores[i] = new JTextField();

      }

     

      builder.appendSeparator("Interesses");

      builder.append("Política", interesses[0]);

      builder.append("Economia", interesses[1]);

      builder.append("Esportes", interesses[2]);

      builder.append("Música", interesses[3]);

      builder.appendSeparator("Opinião");

      builder.append("Melhor Livro:", melhores[0]);

      builder.append("Melhor Filme:", melhores[1]);

      builder.append("Melhor Banda:", melhores[2]);

      builder.append("Outros:", melhores[3]);

     

      return builder.getPanel();        

}

Listagem 03

 

Para o desenvolvimento do painél de interesses, onde o usuário seleciona assuntos que lhe interessam e registra suas opiniões, será utilizada a classe DefaultFormBuilder, que auxilia bastante no momento da adição pois permite o desenvolvedor adicionar componentes sem definir o número de linhas.

 

Isso se demonstra na declaração de FormLayout, onde é passado apenas a String que define as dimensões  das colunas!

 

Foram criados dois arrays de CheckBoxs e JTextFields apenas para popular o painél, visto que não há eventos nem recuperação dos dados preenchidos nos mesmos.

 

Após todos os componentes criados e prontos para serem adicionados, faz-se necessário apenas uma chamada a builder.append(... passando como argumento o label e o componente a ser adicionado. As linhas são criadas dinamicamente de acordo com o número de adições feitas.

 

Há também o método appendSeparator que adiciona um separador entre os componentes na mesma hierarquia de adições feitas.

 

A Listagem 04 contém o código do último painél.

 

private JPanel getButtonBar(){

      ButtonBarBuilder builder = new ButtonBarBuilder();

     

      JButton[] jButtons = {

            new JButton("Enviar Dados"),

            new JButton("Apagar"),

            new JButton("Ajuda"),

            new JButton("Sair")

      };

     

      builder.addGriddedButtons(jButtons);

      return builder.getPanel();

}

Listagem 04

 

Para confecção do painél de botões será utilizada a classe ButtonBarBuilder, que é própria para montagem de barras de botões.

 

É interessante destacar que esta classe se responsabiliza por padrozinar tamanho, espaçamento e outras propriedades para que se evite desproporcionalidades, que são comuns em interfaces gráficas desenvolvidas manualmente.

O método addGriggedButtons cuida desta funcionalidade deixando a barra de botões com uma aparência muito agradável.

 

Como dito no início do artigo, não será trabalhada a disposição de cada painél após todos eles serem adicionados no frame da aplicação pois o ideal seria ter mais painéis, o que facilitaria seu posicionamento. Mas como o objetivo é apenas demonstrar estas três classes presentes no framework, a aplicação ficará de acordo com a Figura 01.

 

acufmcigp1fig01.jpg 

Figura 01

 

Conclusões

Na primeira parte do artigo apresentou-se uma solução para adições e posicionamento manuais de componentes em interfaces Swing, utilizando para isso o framework FormsLayout. Nesta segunda parte apresentou-se uma solução às adições feitas anteriormente, para isso utilizando classes de apoio também presentes no framework, o que mostra o quão robusto é. Em cada uma das classes apresentadas há uma série de métodos que vão atender a outras demandas, o que explica o grande número de desenvolvedores que o utilizam.

 

Um grande abraço e até a próxima,
Adriano Castro