Este artigo apresenta o plugin WindowBuilder com o objetivo de simplificar o desenvolvimento de interfaces gráficas a partir do Eclipse. O WindowBuilder possibilita a construção de telas empregando as principais APIs gráficas do Java Desktop. Como principais benefícios da utilização de plugins para o desenvolvimento de telas, temos a facilidade e a agilidade na projeção e construção das janelas. Assim, o tema abordado é útil para o desenvolvimento de interfaces gráficas em Java focando em agilidade e produtividade com o plugin WindowBuilder. Com ele, você não precisará mais ficar “preso” ao NetBeans para criar aplicações desktop com o auxílio de um modo gráfico. Poderá adotar também a IDE Eclipse.

A linguagem de programação Java pode ser utilizada para construir diferentes tipos de aplicações a serem executadas em diferentes plataformas. Como exemplos dessa rica variação, podemos citar as aplicações construídas para o ambiente Web, aplicações voltadas para uso exclusivo no desktop, aplicações para dispositivos móveis, ou mesmo tecnologias como televisores, geladeiras, smart cards, entre outros.

Atualmente, grande parte dos projetos desenvolvidos em Java está relacionada com a plataforma web, e para tanto, há o auxílio de vários recursos para elaboração das regras de negócio e do frontend. HTML, JavaScript e bibliotecas de tags são apenas algumas das opções que podemos citar para a camada de apresentação.

Já para aplicações construídas para desktop, tratando-se do frontend, também temos muitas bibliotecas para nos auxiliar. Como exemplo, podemos citar a pioneira AWT, e outras mais elaboradas, como Swing e SWT.

Com base nisso, neste artigo iremos aprender como construir um projeto desktop utilizando como ferramentas o Eclipse e o plugin WindowBuilder. Veremos como montar telas com componentes gráficos sofisticados e bem elaborados de maneira simples e ágil.

O nosso projeto

Nosso artigo apresentará como construir uma agenda simples que tenha como funcionalidade a inclusão de novos eventos e a listagem dos eventos previamente cadastrados. As informações dos eventos serão gravadas em um arquivo texto. Para isso, utilizaremos as classes do pacote java.io.

Como pré-requisito para iniciar a parte prática, temos a instalação e configuração do Java e do Eclipse em sua máquina, bem como o conhecimento básico desta linguagem de programação.

Download e instalação do WindowBuilder

Quando instalamos o Eclipse, o mesmo não possui inicialmente um plugin para desenvolvimento de interfaces gráficas, portanto precisamos fazer o download deste e instalá-lo.

Assim, abra o Eclipse e, no menu Help, clique em Install new software. Na tela que será exibida, informe o endereço http://download.eclipse.org/windowbuilder/WB/integration/4.2/ no campo Work with... e clique em Add... (veja a Figura 1).

Local
onde deve ser informado o endereço para baixar o plugin
Figura 1. Local onde deve ser informado o endereço para baixar o plugin.

Feito isso, serão listados os softwares disponíveis para instalação. Clique em Swing Designer, depois em WindowBuilder Engine e em Next. Neste momento será exibida uma tela apresentando a licença do plugin. Nela, apenas clique na opção Accept e em Finish. A Figura 2 demonstra os pacotes disponíveis.

Após a conclusão da instalação, reinicie o Eclipse.

Lista
de pacotes disponíveis para instalação
Figura 2. Lista de pacotes disponíveis para instalação.

Agenda de eventos

Com o plugin do WindowBuilder devidamente instalado, vamos iniciar nosso projeto. Sendo assim, crie um novo projeto Java no Eclipse chamado “Agenda”, e um pacote no projeto nomeado como “agenda.gui”. Este será o pacote que irá armazenar as nossas telas.

Após criar o projeto e o pacote para acomodar as telas, vamos criar nossa primeira classe. Para isso, clique com o botão direito sobre o pacote agenda.gui e escolha a opção New > Other. Na tela que será exibida, selecione WindowBuilder e, finalmente, JPanel.

A Figura 3 demonstra as opções gráficas que o WindowBuilder disponibiliza.

Criação
de um componente JPanel a partir do WindowBuilder
Figura 3. Criação de um componente JPanel a partir do WindowBuilder.

Nesta janela, selecione o item JPanel e clique em Next. Na tela de atributos da classe, preencha o campo Name com “CadastroEventoPanel” e clique em Finish. Com isso será aberto o editor de design do WindowBuilder. Nesta tela contamos com uma paleta de componentes gráficos na qual é possível escolher, arrastar, soltar e editar suas propriedades, conforme demonstra Figura 4.

Editor
de design do WindowBuilder
Figura 4. Editor de design do WindowBuilder.

Vamos então iniciar a edição de nossa tela. Na view de nome Structure, selecione o painel criado (javax.swing.JPanel) e na view Properties, selecione o layout (absolute). A Figura 5 demonstra a view properties. Com esta opção de layout, é possível arrastar e soltar componentes gráficos em qualquer lugar do painel.

Configurando
o atributo Layout como absolute na view Properties
Figura 5. Configurando o atributo Layout como absolute na view Properties.

Este painel irá comportar os componentes gráficos que receberão os dados de um novo evento de calendário. Nosso evento será composto pelos seguintes campos: data, descrição, periodicidade para execução do mesmo (apenas uma vez, semanal ou mensal), se existirá um alarme e se ele deve ser encaminhado por e-mail para alguém. Como neste exercício nosso foco são as telas, não iremos construir todas as funcionalidades possíveis de uma agenda, mas sim apenas o cadastramento em arquivo texto e a recuperação deles em uma tela de listagem.

Primeiramente vamos adicionar ao nosso painel um título. Para isso, clique sobre o componente gráfico JLabel, localizado na view Palette, e arraste-o até a parte superior do painel, conforme a Figura 6.

Painel
com componente JLabel adicionado a ele
Figura 6. Painel com componente JLabel adicionado a ele.

Agora, selecione o componente gráfico JLabel recém adicionado. Na view Properties, altere o item text para “Descrição do Evento”, a fonte para “Tahoma 11 bold” e a propriedade Variable para “lblDescEvento”, como demonstra a Figura 7.

Edição
das propriedades de um JLabel
Figura 7. Edição das propriedades de um JLabel.

Em seguida vamos adicionar um campo de texto para que o usuário possa escrever a descrição do evento. Deste modo, através da view Palette, arraste o componente gráfico JTextField para o canto superior esquerdo do JPanel e aumente o tamanho dele com o mouse de acordo com a Figura 8. Por fim, mude a propriedade Variable desse componente para tfDescEvento.

Redimensionamento
de um componente JTextField
Figura 8. Redimensionamento de um componente JTextField.

Faça o mesmo procedimento descrito acima para adicionar dois novos grupos de JLabel e JTextField, sendo um para a data do evento e outro para a entrada de um endereço de e-mail, que servirá para encaminhar o evento para um destinatário. Veja os nomes para os novos componentes que empregamos em nosso exemplo na Tabela 1.

Descrição
dos componentes JLabel e JTextField utilizados
Tabela 1. Descrição dos componentes JLabel e JTextField utilizados.

Imediatamente, vamos adicionar ao painel os componentes gráficos que serão responsáveis por informar a periodicidade de execução do evento: uma vez, semanal ou mensal. Como só podemos escolher uma opção, o melhor componente a ser empregado é o JRadioButton, pois ele permite que apenas uma das opções seja selecionada.

Deste modo, logo abaixo dos componentes gráficos relacionados a “Encaminhar E-mail”, adicione um JLabel (no atributo name, informe “lblPeriodicidadeEvento”, e como text, “Periodicidade do Evento”) e três componentes do tipo JRadioButton: rdbUmavez, rdbSemanal e rdbMensal. O painel ficará semelhante à Figura 9.

Visão
do painel de cadastro de eventos
Figura 9. Visão do painel de cadastro de eventos.

Da maneira como foram adicionados, os componentes JRadioButton ainda não se comportam de forma a limitar uma escolha simples entre eles. Reparem que, se clicarmos nas três opções, todas ficarão marcadas. Queremos um comportamento diferente, onde apenas uma delas fique selecionada. Para isso, devemos agrupar os JRadioButton utilizando um componente chamado ButtonGroup.

Sendo assim, clique com o botão direito no componente do tipo JRadioButton, chamado rdbUmaVez, selecione set Button group > new Standard. Repita a operação para os outros dois radiobuttons (rdbSemanal e rdbMensal), mas desta vez selecione a opção set ButtonGroup > nome do ButtonGroup recém-criado. Com isso, todos os JRadioButtons ficarão em uma estrutura abaixo do ButtonGroup e, a partir de agora, apenas um poderá ser selecionado por vez.

Após adicionar e configurar os JRadioButtons, vamos incluir uma marcação (JCheckBox) possibilitando acionar um alarme ou não e os botões para Salvar e Limpar (JButton) ao formulário. A Tabela 2 apresenta os nomes utilizados para estes componentes no exemplo.

Descrição
dos componentes JCheckBox e JButton utilizados
Tabela 2. Descrição dos componentes JCheckBox e JButton utilizados.

Ao final, essa tela que estamos projetando deverá ficar semelhante à exibida na Figura 10.

Painel
para cadastro de eventos da agenda
Figura 10. Painel para cadastro de eventos da agenda.

Montagem do painel de listagem de Eventos

Com o painel de inclusão de novos eventos pronto, vamos adicionar ao nosso projeto um novo painel, que será responsável por listar todos os eventos já cadastrados. Deste modo, clique mais uma vez com o botão direito sobre o pacote agenda.gui e escolha New > Other > WindowBuilder > Swing Designer > JPanel. Depois, informe no campo Name: “ListaEventosPanel”.

Este painel será bem mais simples do que o anterior, pois terá como responsabilidade apenas a listagem dos eventos. O componente gráfico utilizado para exibir uma lista de registros é o JTable. Quando adicionamos muitos registros no JTable, sua altura pode extrapolar os limites do JPanel ao qual ele foi adicionado. Para evitar isso, precisamos adicionar ao JTable um componente JScrollPane que permite controlar a exibição da tabela através da adição de barras de rolagem vertical e horizontal.

Para adicionar um JScrollPane, acesse a view Palette, selecione o container JScrollPane e depois clique no centro do painel. Como este componente apenas representa mais um container, visualmente nada mudará em nosso painel, porém será adicionado na view Structure o novo container logo abaixo do JPanel. Feito isso, arraste o componente gráfico JTable para o centro do painel. Deste modo teremos uma estrutura onde um JTable estará dentro do JScrollPane e este, por sua vez, dentro do JPanel, como demonstra a Figura 11. Mais à frente falaremos sobre a estrutura da tabela, isto é, as linhas e colunas.

Estrutura
montada para o painel de listagem de eventos
Figura 11. Estrutura montada para o painel de listagem de eventos.

Montagem do Frame – A tela principal da Agenda

O JPanel é um container utilizado apenas para organização dos componentes visuais. Por si só, ele não pode ser chamado para exibir a tela. Para que os componentes gráficos possam se tornar visíveis, é necessário criar um container chamado JFrame.

Para criar um JFrame no projeto, clique com o botão direito sobre o pacote agenda.gui e escolha a opção New > Other > WindowBuilder > Swing Designer > JFrame. Na tela que abrir, preencha o campo Name com “AgendaFrame” e clique em Finish.

Após definirmos o JFrame, adicionamos os painéis a ele, possibilitando assim visualizá-los. Para melhor organização dos painéis no frame, vamos adicionar um componente chamado JTabbedPane. Este permitirá acessar cada um dos painéis por meio de abas. Assim, poderemos comutar entre “inclusão de evento” e “listagem de eventos” apenas clicando em abas. Portanto, clique no container JTabbedPane e adicione-o no centro do frame. O JTabbedPane vazio apresenta apenas uma caixa em branco no centro do frame, conforme a Figura 12.

Exemplo
de um JFrame vazio
Figura 12. Exemplo de um JFrame vazio.

Após adicionar o JTabbedPane no frame, podemos incluir os JPanels previamente criados. Sendo assim, clique na aba Source (canto inferior esquerdo da tela) do Eclipse para que o código do Frame seja exibido. Veja a Figura 13.

Destaque para a aba Source no editor de design do WindowBuilder
Figura 13. Destaque para a aba Source no editor de design do WindowBuilder.

Com o código fonte da tela aberto, localize o construtor da classe AgendaFrame. Vamos utilizar o método addTab() da classe JTabbedPane para adicionar os dois painéis criados. Observe o respectivo código na Listagem 1.

Listagem 1. Construtor da classe AgendaFrame com a adição de painéis no componente JTabbedPane.

  package agenda.gui;
   
  import java.awt.BorderLayout;
   
  public class AgendaFrame extends JFrame {
   private static final long serialVersionUID = 1L;
   private JPanel contentPane;
   public AgendaFrame() {
    setTitle("Agenda");
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    setContentPane(contentPane);
    
    JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
    ListaEventosPanel listaEventosPanel = new ListaEventosPanel();
    tabbedPane.addTab("Cadastro de Eventos", 
    new CadastroEventoPanel(listaEventosPanel));
    tabbedPane.addTab("Lista de Eventos", listaEventosPanel);
    
    contentPane.add(tabbedPane, BorderLayout.CENTER);
    
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
  }

Verificamos na Listagem 1 que o método addTab() recebe dois parâmetros. Um deles é o título da aba e o segundo é o componente que se deseja adicionar. Note que é criada uma instância de JTabbedPane chamada tabbedPane. Na linha abaixo é criada uma instância do JPanel ListaEventosPanel chamada listaEventosPanel. Esta instância será incluída em tabbedPane. Também é adicionada uma aba com o título “Cadastro de Eventos”, contendo uma instância de CadastroEventoPanel. Veja que no construtor de CadastroEventoPanel passamos como parâmetro a referência de listaEventosPanel.

Após realizar as alterações descritas na Listagem 1, salve o código e clique na aba Design do Eclipse. O JFrame deverá estar semelhante à Figura 14.

Frame
principal com os painéis adicionados
Figura 14. Frame principal com os painéis adicionados.

Construção da classe de tratamento de eventos

Nossa agenda tem como principais funcionalidades cadastrar e listar eventos. Para cada evento criado, é instanciado um objeto para representá-lo (entidade). A classe que iremos construir para representar o Evento da Agenda irá conter os dados de um evento na aplicação. Portanto, nossa classe irá contar com os atributos de um evento e os métodos get e set para recuperar e alterar os valores desses atributos. Além disso, iremos reescrever o método toString() para que o mesmo possa “gerar” os valores de um objeto Evento em um formato específico para gravação em um arquivo texto. Para facilitar a leitura das informações de um Evento no arquivo texto, vamos definir como separador de atributos o caractere “;”. Na Listagem 2 temos a classe completa.

Listagem 2. Código da entidade Evento.

  package agenda.vo;
   
  import java.io.Serializable;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import agenda.utils.PeriodicidadeEnum;
   
  public class Evento implements Serializable {
   private static final long serialVersionUID = 1L;
   private Date dataEvento;
   
   private String descEvento;
   private PeriodicidadeEnum periodicidade;
   private String emailEncaminhar;
   private int alarme;
   public Evento() {
    super();
   }
   public Evento(Date dataEvento, String descEvento,
     PeriodicidadeEnum periodicidade, String emailEncaminhar, int alarme) {
    super();
    this.dataEvento = dataEvento;
    this.descEvento = descEvento;
    this.periodicidade = periodicidade;
    this.emailEncaminhar = emailEncaminhar;
    this.alarme = alarme;
   }
   public Date getDataEvento() {
    return dataEvento;
   }
   public void setDataEvento(Date dataEvento) {
    this.dataEvento = dataEvento;
   }
   public String getDescEvento() {
    return descEvento;
   }
   public void setDescEvento(String descEvento) {
    this.descEvento = descEvento;
   }
   public PeriodicidadeEnum getPeriodicidade() {
    return periodicidade;
   }
   public void setPeriodicidade(PeriodicidadeEnum periodicidade) {
    this.periodicidade = periodicidade;
   }
   public String getEmailEncaminhar() {
    return emailEncaminhar;
   }
   public void setEmailEncaminhar(String emailEncaminhar) {
    this.emailEncaminhar = emailEncaminhar;
   }
   public int getAlarme() {
    return alarme;
   }
   public void setAlarme(int alarme) {
    this.alarme = alarme;
   }
   public String toString(){
    SimpleDateFormat mascaraData = new SimpleDateFormat("dd/MM/yyyy");
    return (mascaraData.format(getDataEvento()) + ";" + getDescEvento() +
     ";" + getPeriodicidade() + ";" + getEmailEncaminhar() + ";" 
     + getAlarme());
   }
  }

Periodicidades da Agenda – PeriodicidadeEnum

Como uma regra de negócio importante a todas as agendas eletrônicas, nossa agenda também poderá armazenar eventos cíclicos, ou seja, que se repetem com certa frequência. Para a implementação deste recurso, criaremos uma Enumeration que irá controlar as opções de frequência disponíveis. Feito isso, na classe que representa o Evento, devemos referenciar esta enumeration como o tipo do atributo Periodicidade. O enum PeriodicidadeEnum será criado no pacote agenda.utils e o código pode ser visto na Listagem 3.

Listagem 3. Enumeration com as periodicidades de um Evento.

  package agenda.utils;
   
  public enum PeriodicidadeEnum {
   UNICO, SEMANAL, MENSAL;
  }

Construção da classe AgendaUtils

Para uma melhor estratégia de reutilização de código dos métodos utilitários, vamos construir uma classe para abrigar estes métodos. Em nosso caso, adicionaremos apenas um método, responsável por converter uma String em uma data. Este método será chamado no momento de recuperar a data do evento digitada na tela de cadastro. Veja o código da classe AgendaUtils na Listagem 4.

Listagem 4. Classe que possui método de conversão de data.

  package agenda.utils;
   
  import java.util.Calendar;
  import java.util.Date;
   
  public class AgendaUtils {
   
   public static Date getDateFromString(String dataStr){
    Calendar data = Calendar.getInstance();
    data.set(Calendar.YEAR, Integer.parseInt(dataStr.substring(6, 10)));
    data.set(Calendar.MONTH, Integer.parseInt(dataStr.substring(3, 5)));
    data.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dataStr.substring(0, 2)));
    
    return data.getTime();
   }
  }

Construção da classe AgendaIO

Para simplificar nossa aplicação Agenda, não iremos gravar os Eventos criados em um banco de dados. Gravaremos diretamente em um arquivo texto, na máquina local em que se está executando a aplicação.

Neste formato, a classe AgendaIO será responsável por ler e gravar as informações de nossos eventos. Para simplificar, gravaremos nosso arquivo de eventos no próprio diretório em que a aplicação estiver executando (./eventos.txt). Deste modo, a cada evento gerado pela tela de cadastro, será gravada uma linha no arquivo para representá-lo. Veja na Listagem 5 o código dessa classe.

Listagem 5. Classe de leitura e gravação de eventos em arquivo texto.

  package agenda.io;
   
  import java.io.BufferedReader;
  import java.io.BufferedWriter;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileReader;
  import java.io.FileWriter;
  import java.util.Vector;
   
  import agenda.utils.PeriodicidadeEnum;
  import agenda.vo.Evento;
   
  public class AgendaIO {
   private final String DIRETORIO = ".";
   private final String ARQUIVO = "eventos.txt";
   
   public void gravarEvento(Evento evento)throws Exception{
    try {
     BufferedWriter writer = new BufferedWriter(new FileWriter
     (new File(DIRETORIO, ARQUIVO), true));
     writer.write(evento.toString(), 0, evento.toString().length());
     writer.newLine();
     writer.close();
     
    }catch(FileNotFoundException fnfe){
     throw new Exception("Arquivo não encontrado");
     
    }catch(Exception ex){
     throw new Exception("Problemas na gravação do arquivo");
     
    }
   }
   
   public Vector<Vector<Object>> getEventos()throws Exception{
    Vector<Vector<Object>> lista = 
    new Vector<Vector<Object>>();
    
    try {
     BufferedReader reader = new BufferedReader(new FileReader
     (new File(DIRETORIO, ARQUIVO)));
     String linha = reader.readLine();
     while(linha != null){
      Vector<Object> eventoVector = new Vector<Object>();
      String[] tokens = linha.split(";");
   
      eventoVector.add(tokens[0]);
      eventoVector.add(tokens[1]);
      eventoVector.add(PeriodicidadeEnum.valueOf(tokens[2]));
      eventoVector.add(tokens[3]);
      eventoVector.add(tokens[4].equals("1") ? "LIGADO" : "DESLIGADO");
      
      lista.add(eventoVector);
      linha = reader.readLine();
     }
     
     reader.close();
     
    }catch(FileNotFoundException fnfe){
     throw new Exception("Arquivo não encontrado");
     
    }catch(Exception ex){
     throw new Exception("Problemas de leitura no arquivo de eventos");
     
    }
    return lista;
   }
  }

Basicamente, implementamos um método para gravação e outro para leitura de Eventos armazenados no arquivo texto.

O método gravarEvento(), que recebe como parâmetro uma entidade do tipo Evento, cria um objeto do tipo BufferedWriter. Este objeto, por sua vez, “enxerga” o conteúdo de um arquivo no disco através da classe FileWriter. A classe File é utilizada para indicar exatamente em qual arquivo se deseja realizar a gravação. Por fim, por meio do método BufferedWriter.write() o evento é gravado no arquivo. Repare que o método toString() é chamado para que possamos gravar os atributos do objeto evento separados por “;”.

Já o método getEventos() realiza o procedimento inverso, ou seja, ele cria uma instância de um objeto BufferedReader. Este objeto abre um stream de dados para realizar a leitura de dados do arquivo informado no construtor da classe File. O método readLine() realiza a leitura de uma linha completa dentro do arquivo. Para cada linha lida, é criada uma instância de Evento, o qual é armazenado em um Vector que é retornado pelo método.

Painel de listagem de eventos

Como apresentado no código na Listagem 1, já adicionamos o painel de listagem de eventos no frame principal da aplicação. Agora, vamos realizar algumas modificações no código da classe de listagem de eventos e criar o método que irá retornar as colunas da tabela.

Deste modo, abra o painel de listagem de eventos e clique na aba Source, localizada no canto inferior esquerdo da tela, para ter acesso ao código fonte da classe ListaEventosPanel. Para que possamos adicionar colunas em nossa tabela de listagem de eventos, criaremos um método (getNameColumns()) para retornar uma collection (java.util.Vector) com os nomes das colunas. Veja a Listagem 6.

Listagem 6. Método que retorna os nomes das colunas utilizados na tabela de listagem de eventos.

  private Vector<String> getNameColumns(){
    Vector<String> nameColumns = new Vector<String>();
    nameColumns.add("Data");
    nameColumns.add("Descrição");
    nameColumns.add("Periodicidade");
    nameColumns.add("E-mail");
    nameColumns.add("Alarme");
    return nameColumns;
  }

Com o método pronto, vamos incluir uma chamada a ele no construtor da classe ListaEventosPanel. Assim, ao iniciarmos a classe de listagem, o método de retorno das colunas já será executado. A Listagem 7 demonstra o construtor da classe ListaEventosPanel.

Listagem 7. Construtor que monta a tabela de listagem de eventos.

  public ListaEventosPanel() {
    setLayout(new BorderLayout(0, 0));
    
    table = new JTable(getDataColumns(), getNameColumns());
    JScrollPane scroll = new JScrollPane(table);
    add(scroll, BorderLayout.CENTER);
  }

Na construção do objeto JTable indicamos os dados a serem carregados e as colunas da tabela. No caso das colunas da tabela, realizamos uma chamada ao método getNameColumns(), e no caso dos dados da tabela, os mesmos serão recuperados através do método getDataColumns(), como veremos adiante.

Na Listagem 8 temos a implementação do método addNewRow(), que inclui na tabela, de forma individual, cada registro criado no painel de Cadastro de Eventos. Este método recebe um array de Object contendo os valores dos atributos de um Evento, recupera a estrutura de dados do JTable, DefaultTableModel, e, através do método addRow(), grava os valores em uma nova linha da tabela.

Listagem 8. Código do método addNewRow().

  public void addNewRow(Object[] valores){
    ((DefaultTableModel)table.getModel()).addRow(valores);
  }

Para carregarmos os dados de todos os eventos já cadastrados, criamos o método getDataColumns(). Este retorna uma collection obtida com uma chamada ao método de AgendaIO denominado getEventos(), que realiza a montagem do Vector principal contendo vários outros Vectors, cada um com os atributos de um único Evento.

A Listagem 9 demonstra o código do método getDataColumns().

Listagem 9. Código do método getDataColumns().

  private Vector<Vector<Object>> getDataColumns(){
    AgendaIO io = new AgendaIO();
    Vector<Vector<Object>> dataColumns = null;
    
    try {
     dataColumns = io.getEventos(); 
    }catch(Exception ex){
     JOptionPane.showMessageDialog(null, "ERRO", ex.getMessage(), 
     JOptionPane.ERROR_MESSAGE);
    }
    
    return dataColumns;
  }

Modificações no painel CadastroEventoPanel

Quando criamos um novo evento no painel de cadastros, o painel de listagem já deve apresentá-lo, mesmo que este painel não esteja com foco. Para que isto seja possível, precisamos incluir uma referência da classe ListaEventosPanel na classe CadastroEventoPanel. Esta referência é iniciada no construtor da classe CadastroEventoPanel, e será utilizada para que o novo Evento já seja enviado para ela. Veja o código desse construtor na Listagem 10.

Listagem 10. Código do construtor CadastroEventoPanal(ListaEventosPanel listaEventos).

  public CadastroEventoPanel(ListaEventosPanel listaEventos) {
    this.listaEventos = listaEventos;

Feito isso, vamos tratar da regra associada ao botão Salvar. Ao clicar sobre este botão devemos recuperar as informações digitadas na tela e enviá-las ao objeto que efetivamente grava as informações no disco.

A Listagem 11 exibe o método chamaCadastroEvento(), que tem por finalidade recuperar as informações digitadas na tela, criar uma instância de Evento e passá-la como parâmetro ao método gravarEvento(Evento) da classe AgendaIO.

Listagem 11. Método da classe CadastroEventoPanel que recupera as informações digitadas na tela e as envia para serem gravadas.

  private void chamaCadastroEvento(){
    AgendaIO io = new AgendaIO();
    Evento evento = new Evento();
    
    Object[] novaLinha = new Object[5];
    
    evento.setDataEvento(AgendaUtils.getDateFromString(tfDtEvento.getText()));
    evento.setDescEvento(tfDescEvento.getText());
    evento.setAlarme(chckbxAlarme.isSelected() ? 1 : 0);
    evento.setEmailEncaminhar(tfEmailEvento.getText());
    
    novaLinha[0] = tfDtEvento.getText();
    novaLinha[1] = tfDescEvento.getText();
    novaLinha[4] = chckbxAlarme.isSelected() ? "LIGADO" : "DESLIGADO";
    novaLinha[3] = tfEmailEvento.getText();
      
    if(rdbtnUmaVez.isSelected()){
     evento.setPeriodicidade(PeriodicidadeEnum.UNICO);
     novaLinha[2] = PeriodicidadeEnum.UNICO;
    }
    else if(rdbtnSemanal.isSelected()){
     evento.setPeriodicidade(PeriodicidadeEnum.SEMANAL);
     novaLinha[2] = PeriodicidadeEnum.SEMANAL;
    }
    else {
     evento.setPeriodicidade(PeriodicidadeEnum.MENSAL);
     novaLinha[2] = PeriodicidadeEnum.MENSAL;
    }
    
    try {
     io.gravarEvento(evento);             
    }catch(Exception ex){
     JOptionPane.showMessageDialog(null, "ERRO", ex.getMessage(), 
     JOptionPane.ERROR_MESSAGE);
    }
    listaEventos.addNewRow(novaLinha);
    limparCampos();
  }

Também devemos criar o método que será chamado ao clicar no botão Limpar e ao final da execução do método chamaCadastroEvento(). A Listagem 12 expõe o código do método limparCampos().

Listagem 12. Método que limpa os campos da tela de cadastro.

  private void limparCampos(){
    tfDtEvento.setText("");
    tfDescEvento.setText("");
    chckbxAlarme.setSelected(false);
    tfEmailEvento.setText("");
    rdbtnUmaVez.setSelected(true);
  }

Agora vamos adicionar, no final do construtor da classe de cadastro de eventos, os listeners dos botões responsáveis por salvar o novo evento e limpar os campos da tela.

A Listagem 13 demonstra a implementação dos listeners associados aos botões Salvar e Limpar.

Listagem 13. Trecho de código que demonstra a inclusão de listeners nos botões.

  btnSalvar.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent arg0) {
    chamaCadastroEvento();
   }
  });
    
  btnLimpar.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent arg0) {
    limparCampos();                       
   }
  });

Construção da classe Agenda

Para executar nossa aplicação, é preciso que ela tenha uma classe principal, ou seja, uma classe com o método main(). Em nosso exemplo, essa classe será bem simples e sua única funcionalidade será criar uma instância do frame AgendaFrame para que a tela principal seja exibida.

A Listagem 14 apresenta o código da classe Agenda.

Listagem 14. Código da classe Agenda.

  package agenda;
   
  import agenda.gui.AgendaFrame;
   
  public class Agenda {
   
   public static void main(String[] args) {
    new Agenda().iniciarTela();
   
   }
   
   private void iniciarTela(){
    AgendaFrame frame = new AgendaFrame();
    frame.setVisible(true);
   }
  }

Executando a aplicação

Pronto! Concluímos o desenvolvimento de nossa aplicação. Agora vamos executá-la para ver os resultados. Para isso, no Eclipse, clique com o botão direito do mouse na classe Agenda e escolha a opção: Run as > Java application. De acordo com o demonstrado na Listagem 14, essa classe irá construir uma referência para o frame principal (AgendaFrame) e chamar o método setVisible(true), tornando a tela visível.

Com a aplicação funcionando, podemos começar a cadastrar nossos eventos. Deste modo, visualizando o painel de cadastro de eventos, preencha os campos da tela e clique em Salvar. Observação: de acordo com a regra implementada no método getDateFromString() da classe AgendaUtils, a data deve ser digitada no formato: dd/mm/aaaa.

A Figura 15 demonstra a tela da agenda com os campos preenchidos.

Exemplo
do frame principal da aplicação com os campos preenchidos
Figura 15. Exemplo do frame principal da aplicação com os campos preenchidos.

Após clicar no botão Salvar, a tela de cadastro será limpa e o novo registro cadastrado poderá ser visto na aba Lista de Eventos. Observe a Figura 16.

Exemplo
do frame exibindo a aba que lista os eventos cadastrados
Figura 16. Exemplo do frame exibindo a aba que lista os eventos cadastrados.
Conclusão

Atualmente a maioria dos projetos desenvolvidos em Java corresponde a projetos para a plataforma Web. Isto implica em construções de interfaces gráficas empregando tecnologias como HTML, JavaScript, entre outras. Porém, para os casos de desenvolvimento em que não se utiliza o Java voltado para a plataforma Web, a API Swing é poderosa e nos proporciona uma vasta coleção de componentes gráficos, sendo possível construir aplicações que nada perdem, em termos gráficos, para outras tecnologias.

Confira também