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.
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