Utilizando FormsLayout para criação de interfaces gráficas
Interfaces gráficas em aplicações Swing, mesmo contendo poucos componentes, são relativamente cansativas e pouco reutilizáveis no caso de serem montadas manualmente. O objetivo deste artigo é apresentar uma solução, um pouco mais vantajosa para esse tipo de problema.
A solução será o uso de um framework – relativamente simples em comparação a outros muito mais robustos presentes, alguns open-source. É o FormsLayout, de JGoodies, disponível para download em: http://www.jgoodies.com/downloads/libraries.html (link revisado em 3 de setembro de 2007).
O mesmo fornece um suporte à construção de interfaces com um layout amigável e bem organizado; tudo isso com um número de linhas de código relativamente baixas, além de resultar em uma interface flexível e reutilizável.
Partindo de uma interface gráfica simples
Inicialmente, será montada uma interface gráfica relativamente simples. O termo mais correto seria bagunçada, sem gerenciadores de layout bem distribuídos atuando na mesma. A listagem 01 apresenta essa interface.
package br.com.jm.forms;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class SimpleForm extends JFrame {
private JButton buttonOk;
private JLabel labelCPF;
private JLabel labelDescricao;
private JLabel labelEndereco;
private JLabel labelNome;
private JTextField txtCPF;
private JTextArea txtDescricao;
private JTextField txtEndereco;
private JTextField txtNome;
private JScrollPane jScrollPane;
public SimpleForm(){
super("Formulário Simples");
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.setLayout(new FlowLayout(FlowLayout.LEFT));
buttonOk = new JButton("Ok!");
labelCPF = new JLabel("CPF:");
labelDescricao = new JLabel("Descrição:");
labelNome = new JLabel("Nome:");
labelEndereco = new JLabel("Endereço:");
txtCPF = new JTextField(20);
txtDescricao = new JTextArea(7, 50);
txtNome = new JTextField(30);
txtEndereco = new JTextField(30);
jScrollPane = new JScrollPane(txtDescricao);
super.add(labelNome);
super.add(txtNome);
super.add(labelEndereco);
super.add(txtEndereco);
super.add(labelCPF);
super.add(txtCPF);
super.add(labelDescricao);
super.add(jScrollPane);
super.add(buttonOk);
super.pack();
}
public static void main(String[] args) {
SimpleForm simpleForm = new SimpleForm();
simpleForm.setVisible(true);
}
}
Listagem 01
Como está se partindo do princípio de que o leitor tem uma noção básica de componentes swing, não será descrito em miúdos o que o código acima faz.
Ao ser executado, apresentará uma janela parecida com a figura 01.
Figura 01
É necessário notar que a mesma não possui nenhum gerenciador de layout (excluindo o fato de FlowLayout estar posicionando os objetos) atuando em seus componentes, ou seja, a interface não está nem um pouco organizada. O que será feito agora é criar o layout para esta janela e utilizar o FormsLayout para posicionar os componentes.
Adicionando o framework à aplicação
Primeiramente o desenvolvedor deverá baixar o .jar que contém o framework, disponível para download no link citado anteriormente. O arquivo, até a data de edição do artigo, chama-se forms-1_1_0.zip.
Para usuários do eclipse, clique com o botão direito na projeto presente em Package Explorer, e selecione Build Path > Add External Archives... e selecione o arquivo forms-1_1_0.zip.
Para usuários do netbeans, clique com o botão direito no projeto presente em Projects e selecione Properties, logo após clique em Libraries e na parte direita da janela de opções clique no botão Add Jar/Folder e adicione o arquivo forms-1_1_0.zip.
Com o FormsLayout configurado, será feita agora uma moldura da interface gráfica.
Desenhando a moldura da interface gráfica
O framework FormsLayout posiciona os componentes de acordo com uma espécie de tabela a qual se recomenda desenhá-la antes, até mesmo em uma folha de rascunho antes de criá-la em código.
Nesta tabela, define-se tanto o espaço entre as células quanto seu tamanho (vertical e horizontal). A figura 02 apresenta um possível esboço para a aplicação gráfica do artigo.
Figura 02
Primeiramente desenha-se uma tabela incluindo suas bordas e espaço entre células, todos eles com suas medidas. Os termos dlu e pref se referem a dimensões utilizadas pelo próprio framework, sendo esta última o valor padrão de um componente swing.
Posicionando e montando a interface gráfica
Com a tabela montada parte-se para o posicionamento a nível de código. Algumas alterações serão feitas no código da listagem 01.
//início do código (imports, etc)
public SimpleForm(){
super("Formulário Simples");
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.setLayout(new FlowLayout(FlowLayout.LEFT));
buttonOk = new JButton("Enviar dados >>>");
labelCPF = new JLabel("CPF:");
labelDescricao = new JLabel("Descrição:");
labelNome = new JLabel("Nome:");
labelEndereco = new JLabel("Endereço:");
txtCPF = new JTextField(20);
txtDescricao = new JTextArea(7, 50);
txtNome = new JTextField(30);
txtEndereco = new JTextField(30);
jScrollPane = new JScrollPane(txtDescricao);
super.add(getPanelForm());
super.pack();
}
public JPanel getPanelForm(){
FormLayout formLayout = new FormLayout(
"2dlu, pref, 2dlu, 200px, 2dlu, pref, 2dlu, 200px, 2dlu",
"2dlu, top:pref, 2dlu, top:pref, 2dlu, top:pref, 2dlu, pref, 2dlu" );
JPanel jPanel = new JPanel(formLayout);
jPanel.setBorder(BorderFactory.createTitledBorder("Preencha os dados"));
CellConstraints cellConstraints = new CellConstraints();
jPanel.add(labelNome, cellConstraints.xy(2, 2));
jPanel.add(labelCPF, cellConstraints.xy(6, 2));
jPanel.add(labelEndereco, cellConstraints.xy(2, 4));
jPanel.add(labelDescricao, cellConstraints.xy(2, 6));
jPanel.add(txtNome, cellConstraints.xy(4, 2));
jPanel.add(txtCPF, cellConstraints.xy(8, 2));
jPanel.add(txtEndereco, cellConstraints.xyw(4, 4, 5));
jPanel.add(jScrollPane, cellConstraints.xyw(4, 6, 5));
jPanel.add(buttonOk, cellConstraints.xy(4, 8));
return jPanel;
}
public static void main(String[] args) {
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e){}
SimpleForm simpleForm = new SimpleForm();
simpleForm.setVisible(true);
}
Listagem 02
No construtor, retirou-se todas as chamadas a super.add, pois agora os componentes serão adicionados não diretamente no JFrame, mas no JPanel que possui o gerenciador de layout FormLayout. Foi criado então o método getPanelForm() que retorna um JPanel contendo o formulário principal, sendo necessário apenas super.add(getPanelForm()) para adicioná-lo ao frame.
O método getPanelForm() inicialmente declara uma instância de FormLayout, passando duas Strings para seu construtor. A primeira representa as colunas e a segunda as linhas. O argumento "2dlu, pref, 2dlu, 200px, 2dlu, pref, 2dlu, 200px, 2dlu" é baseado no esboço feito anteriormente, assim como "2dlu, top:pref, 2dlu, top:pref, 2dlu, top:pref, 2dlu, pref, 2dlu", porém esse último com uma pequena diferença. Ao invés de se utilizar apenas o tamanho como pref, definiu-se top:pref, indicando que o alinhamento vertical desta célula deverá ser top, visto que os labels de cada campo deverão estar bem alinhados.
O objeto formLayout é então o gerenciador de layout do formulário e será passado como argumento para instância de JPanel criada logo abaixo.
Em seguida, cria-se uma instância de CellConstraints, que será o objeto responsável por posicionar os componentes dentro da tabela criada.
Com o gerenciador de layout, o “posicionador” e o panel criados, é hora de iniciar a adição de componentes na grade. As chamadas a jPanel.add(... são independentes do gerenciador de layout utilizado. Primeiramente passa-se o componente, por exemplo, labelNome, e em seguida, o local onde deve ser inserido, utilizando para isso o objeto cellConstraints.
Os métodos de posicionamento de cellConstraints são diversos, porém, para o exemplo em questão serão utilizados apenas dois, xy(...) e xyw(...). O primeiro, posiciona um componente de acordo com sua coluna x e sua linha y. Já o segundo posiciona de acordo também com seu comprimento w.
Por exemplo, como o label do campo nome deverá apenas ocupar uma célula, fez-se uma chamada a jPanel.add(labelNome, cellConstraints.xy(2, 2));, ou seja, a posição ocupada pelo label é na coluna 2 e linha 2. Visto que as linhas e colunas 1 são apenas para manter um espaço antes da célula. Já para o campo de endereço chamou-se jPanel.add(txtEndereco, cellConstraints.xyw(4, 4, 5));, visto que ele deve ser posicionado na coluna 4, na linha 4 e ocupar 5 células.
No método main a única mudança é uma chamada para setLookAndFeel de UIManager para alterar o look and feel da aplicação.
O resultado, após utilizar o framework é mostrado na figura 03.
Figura 03
Conclusões
Neste artigo, não foram vistas todas as capacidades deste framework, visto que são muitas. Tem-se a impressão de que o mesmo se trata de um gerenciador de layout como qualquer outro, mas se o leitor explorar bem seus recursos verá que se trata de uma ótima ferramenta para o design de aplicações gráficas.
O objetivo do artigo foi apenas de dar uma introdução básica ao FormsLayout, visto que a interface montada é extremamente simples e utiliza apenas uma pequena parte da gama de funcionalidades do framework.
Um grande abraço e até a próxima,
Adriano Castro