SWT, JFace e Componentes – Parte 1

Uma das partes mais importantes de uma aplicação é a sua interface com o usuário final. Este usuário pode ser tanto uma pessoa normal utilizando um computador desktop ou uma outra aplicação tentando fazer acesso via web services. De qualquer modo, se a interface não for bem construída, o usuário vai ter problemas para acessar as funcionalidades da aplicação. Em uma aplicação desktop, uma interface mal construída ou que não agrade o usuário pode ser a diferença entre o fazer ou não de uma venda ou contrato de desenvolvimento de sistemas. E para criar interfaces belas e ricas, nós precisamos de componentes!

O SWT provê um conjunto gigantesco de componentes visuais, que engloba desde botões e listas, até componentes que adicionam ícones nas barras de tarefa do seu sistema operacional (seja lá qual ele for, contanto que ele tenha uma barra de tarefas). A partir de agora nós vamos começar a conhecer estes componentes que fazem da biblioteca uma das melhores opções para o desenvolvimento de interfaces cheias de funcionalidades.

O que é o JFace?
Antes de começar a nossa viagem pelos componentes visuais do SWT, vamos conhecer outra parte da biblioteca, o JFace. Ele é um conjunto de classes que serve como apoio para o desenvolvimento de aplicações SWT. Ainda nos primórdios do Eclipse e do desenvolvimento do SWT, os responsáveis pelo projeto perceberam que poderiam facilitar o uso do SWT com algumas novas funcionalidades, mas eles queriam manter os componentes o mais limpos possíveis, então eles criaram o JFace.

Entre algumas das funcionalidades oferecidas pelo JFace estão a simplificação no controle de eventos. Às vezes você tem vários componentes visuais diferentes (botões, menus, campos) que executam uma mesma lógica, então termina tendo que espalhar o mesmo código para vários componentes, usando JFace você pode simplesmente criar uma “ação” e utilizar ela ao mesmo tempo em todos os componentes. Outra funcionalidade muito utilizada do JFace é o registro de imagens e fontes (tipos de letras), com ele você pode carregar várias imagens e fontes e deixá-las em um registro único, quando um destes objetos não for mais necessário, basta removê-lo do registro que o próprio JFace vai se preocupar em liberar os recursos do sistema operacional que estavam sendo utilizados.

Vejamos então como melhorar a aplicação apresentada no artigo anterior (Conhecendo SWT, que pode ser acessado no final desta página) utilizando algumas classes utilitárias do JFace:

Listagem 1 – Aplicação de Exemplo utilizando JFace.

package org.maujr;

 

import org.eclipse.jface.window.ApplicationWindow;

import org.eclipse.swt.SWT;

import org.eclipse.swt.events.SelectionAdapter;

import org.eclipse.swt.events.SelectionEvent;

import org.eclipse.swt.layout.RowLayout;

import org.eclipse.swt.widgets.Button;

import org.eclipse.swt.widgets.Composite;

import org.eclipse.swt.widgets.Control;

import org.eclipse.swt.widgets.Display;

 

public class ExemploJFace extends ApplicationWindow {

 

      private static  int selecoes = 0;

     

      public ExemploJFace() {

            super(null);

      }

     

      @Override

      protected Control createContents(Composite parent) {

 

            parent.setLayout(new RowLayout());

           

            Button button = new Button( parent, SWT.PUSH);

            button.setText("Clique Aqui Agora!!!");

           

            button.addSelectionListener(new SelectionAdapter() {

 

                  @Override

                  public void widgetSelected(SelectionEvent event) {

                        Button buttonClicked = (Button) event.getSource();

                        selecoes += 1;

                        buttonClicked.setText(String.format("Fui clicado %s

                                              vezes!", selecoes));

                 }      

            });   

            return parent;  

      }

     

      public static void main(String[] args) {

           

            ApplicationWindow window = new ExemploJFace();

           

            window.setBlockOnOpen(true);

            window.open();

            Display.getDefault().dispose(); 

      }
}

Com apenas 7 linhas a mais de código, nós conseguimos organizar melhor o código (agora os componentes são criados durante a inicialização da interface em um método próprio), simplificamos alguns casos especiais do SWT que você viu no material anterior, como o laço de execução de eventos da interface gráfica. Nós vamos conhecer as funcionalidades que a classe ApplicationWindow provê conforme for necessário, mas exatamente agora basta que você saiba que ela funciona como uma abstração para a “janela principal” da aplicação, que é a janela onde ficam o menu, barras de atalho ou barras de ferramentas.

Como você já conhece o código, vejamos apenas o que é específico desse novo exemplo. O construtor que nós chamamos passando “null” como parâmetro é um aviso para o ApplicationWindow que ele pode criar uma janela principal ele mesmo. O método “createContents()” é um dos métodos do ciclo de vida de um ApplicationWindow, que é chamado para que o usuário possa adicionar componentes na janela principal do sistema, o objeto Composite passado como parâmetro é o container da janela que vai ser mostrada.

Partindo para a execução do código, temos duas invocações de método, “setBlockOnOpen()”, que faz com que quando a janela seja aberta, a thread principal esteja travada para qualquer outra execução. Após isto, nós abrimos a janela principal do sistema, chamando o método “open()”, que automaticamente vai executar o “loop infinito” para o tratamento de eventos que nós havíamos definido no exemplo do primeiro artigo. Quando a janela for fechada a execução continua e o método “dispose()” é chamado no Display padrão para liberar todos os recursos que o sistema estava mantendo.

Neste primeiro momento, ainda não é completamente perceptível a facilitação no desenvolvimento da aplicação com o uso do JFace, mas seguindo em frente no material nós vamos perceber que a classe ApplicationWindow pode nos oferecer, como a possibilidade de adicionar barras de menu e de status na janela principal da aplicação.

O único problema do JFace é que ele ainda não é disponibilizado como uma biblioteca para download fora do Eclipse, você precisa ter o Eclipse em sua máquina e copiar os arquivos .JAR necessários para poder criar um projeto que use JFace em outra IDE. Para adicionar o JFace em um projeto do Eclipse basta seguir o seguinte roteiro:

  1. Clique com o botão direito no projeto
  2. Selecione a opção “Build Path”
  3. Selecione a opção “Add Library”
  4. Escolha a opção “Standard Widget Toolkit (SWT)”
  5. Na próxima página, marque a caixa com os dizeres “Include Support for JFace Libraries”

Pronto, agora o seu projeto já pode fazer uso das classes disponíveis no pacote JFace, para facilitar a construção de aplicações desktop com SWT.

Componentes
Todos os componentes do SWT herdam da classe org.eclipse.swt.widgets.Widget, mas as funcionalidades que esta classe define são simples demais para que possam ser utilizadas diretamente, então, para os componentes visuais, as classes mais importantes são Control e Composite.

Classes que herdam diretamente de Control são aquelas que representam componentes visuais que não podem conter outros componentes dentro deles, como botões e etiquetas (Labels). São componentes simples que já tem uma representação bem definida para o sistema. As classes que herdam de Composite representam os componentes que podem ter outros componentes adicionados a elas, como janelas, árvores, “split panes” e diálogos.

Como você viu no material anterior, os componentes SWT são modificados utilizando os “style bits”, na documentação (javadoc) de cada componente é possível saber quais são os “style bits” aplicáveis a cada componente.

Trabalhando com os Labels
Um Label é um dos mais simples componentes que você vai utilizar, ele simplesmente mostra um texto qualquer na posição em que está sendo colocado. Labels também podem ser utilizados em SWT para representar separadores entre componentes. Vejamos um exemplo de código que utilize Labels:

Listagem 2 – Utilizando Labels.

protected Control createContents(Composite parent) {

      parent.setLayout(new RowLayout( SWT.HORIZONTAL ));

     

      Label label = new Label( parent, SWT.CENTER );

      label.setText("Clique: ");

           

      Button button = new Button( parent, SWT.PUSH);

      button.setText("Clique Aqui Agora!!!");

                       

      this.getShell().setText("Teste SWT/JFace");

      parent.setSize(300, 100);

           

      Label separator = new Label(parent, SWT.SEPARATOR | SWT.SHADOW_OUT );

      return parent;

}

Daqui para frente estaremos sempre utilizando o método “createComponents()” da classe ApplicationWindow para executar os exemplos, pra que seja mais fácil de se testar o funcionamento e diminuir o espaço utilizado para cada exemplo. Você pode simplesmente criar uma cópia da sua classe que herda de ApplicationWindow e colar este código nela para ver o exemplo em funcionamento.

Como você pode perceber, criar um Label é igual a criar qualquer outro componente. No início nós criamos um Label comum, com um texto (passando o texto desejado no método “setText()”,  já no fim nós criamos um Label que é na verdade um separador entre componentes. Para criar um Label que seja um separador nós precisamos passar o style bit SWT.SEPARATOR no seu construtor e definir qual vai ser o tipo da sombra, se vai ser SWT.SHADOW_IN ou SWT.SHADOW_OUT. Se você tentar colocar texto em um Label que é um separador, o texto vai apenas ser ignorado e não mostrado no separador.

Trabalhando com botões
Os botões são, talvez, uma das partes mais importantes de uma interface gráfica, pois eles tanto são os locais onde o usuário indica que está fazendo uma ação como também fontes de informação. Em SWT existem diversos tipos diferentes de botões, desde o clássico botão de clicar, aos botões de “pressão”, botões do tipo “radio”, caixas de marcação e até mesmo setas nas quatro direções.

A classe que implementa todos estes tipos de botão é uma só, a classe Button, e cada botão diferente destes definidos é criado utilizando um “style bit” diferente, vejamos alguns exemplos da criação de botões em SWT:

Listagem 3 – Lidando com botões em SWT

protected Control createContents(Composite parent) {

     

      parent.setLayout(new RowLayout( SWT.HORIZONTAL | SWT.WRAP ));

                 

      Button button = new Button(parent, SWT.PUSH);

      button.setText("Botão simples");

           

      Button checkBox = new Button(parent, SWT.CHECK);

      checkBox.setText("Checkbox");

           

      Button radio1 = new Button(parent, SWT.RADIO);

      radio1.setText("Radio 1");

 

      Button radio2 = new Button(parent, SWT.RADIO);

      radio2.setText("Radio 2");

     

      Button toggle = new Button(parent, SWT.TOGGLE);

      toggle.setText("Toggle Button");

           

      Button arrowUp = new Button(parent, SWT.ARROW | SWT.UP);

      Button arrowDown = new Button(parent, SWT.ARROW | SWT.DOWN);

           

      this.getShell().setText("Teste SWT/JFace");

      parent.setSize(300, 300);

           

      return parent;

           

} 

swtcompjfacefig01.JPG
Figura 01 -
Exemplo da execução do exemplo de botões.

No exemplo nós criamos vários botões na janela principal e cada um destes botões tem características (e aparências) distintas. Botões do tipo TOGGLE, CHECK e RADIO, são aqueles que guardam o estado de seleção que pode ser acessado pelo método “getSelection()” da classe Button e alterados através do método “setSelection()”. O botão do tipo PUSH é o clássico botão de clicar e os botões ARROW são aqueles que surgem como setas na interface.

O evento mais importante para um botão normalmente é o de seleção, que é o momento no qual o usuário interage com o componente, normalmente clicando nele com o mouse ou teclado. Para responder a este evento de seleção é necessário registrar um SelectionListener no botão em questão. Revendo a Listagem 1 deste material, podemos perceber o uso de um SelectionListener para executar uma ação quando o botão for clicado. Então, se você deseja executar uma ação qualquer quando um dos botões na sua interface for clicado, basta criar uma classe que implemente a interface SelectionListener ou herde da classe SelectionAdapter.

Um detalhe importante ao lidar com botões, é entender a diferença de uso de caixas de marcação (checkboxes) e radio-buttons. Você deve utilizar botões do tipo RADIO quando apenas uma única opção em uma lista de opções pode ser escolhida, se você acha que pode escolher mais do que uma das opções disponíveis, então é melhor utilizar caixas de marcação disponíveis. Quando existe um conjunto de botões do tipo RADIO em um Composite, o próprio SWT garante que não vai haver mais do que um botão selecionado.

Trabalhando com RadioGroupFieldEditor
Criado com o objetivo de organizar mais facilmente as interfaces para o usuário, o grupo de botões de rádio apresenta uma estrutura visual simplificada para mostrar as opções. Ele cria um conjunto de linhas que fica ao redor dos componentes e com um título na parte superior.

Listagem 4 – Exemplo de grupo de botões de radio.

protected Control createContents(Composite parent) {

           

      parent.setLayout(new RowLayout( SWT.HORIZONTAL | SWT.WRAP ));

                       

      RadioGroupFieldEditor grupo = new RadioGroupFieldEditor(

            "Selecoes",

            "Selecione um",

            1,

            new String[][] {

                  {"1", "Escolha 1"},

                  {"2", "Escolha 2"},

                  {"3", "Escolha 3"}

                  } ,

            parent,

            true);

           

this.getShell().setText("Teste SWT/JFace");

      parent.setSize(300, 300);

     

      return parent;

}

swtcompjfacefig02.JPG
Figura 02 –
Imagem do exemplo de conjunto de botões do tipo RADIO.

Como você pode perceber, a visualização da aplicação fica melhor e mais organizada utilizando essa classe de “reunião” de componentes visuais.

Conclusão
Neste material você conheceu mais a fundo a biblioteca JFace e quais os seus usos no desenvolvimento de aplicações SWT. Além disso, você também aprendeu como utilizar Labels, todos os tipos de botões, eventos de clique de botões e ainda grupos de botões do tipo RADIO.

Referências

Clayberg, Eric; Rubel, Dan. 2006. Eclipse – Building Commercial-Quality Plugins. The Eclipse Series. 2º Edition. Addison-Wesley - Pearson Education.

McAffer, Jeff; Lemieux, Jean-Michel; 2006. Eclipse Rich Client Platform – Designing, Coding, and Packaging Java Applications. The Eclipse Series. Addison-Wesley – Pearson Education.

D’Anjou, Jim; Fairbrother, Scott; Kehn, Dan; Kellerman, John; McCarthy, Pat; 2005. The Java Developer’s Guide to Eclipse. Second Edition. Addison-Wesley – Pearson Education.

Scarpino, Matthew; Holder, Stephen; NG, Stanford; Mihalkovic, Laurent; 2005. SWT/JFace in Action – How to design graphical applications with Eclipse 3.0. Manning Publications.

SWT Website - http://www.eclipse.org/swt/