Desenvolvendo uma aplicação passo a passo – Parte 3
Dando continuidade à criação da aplicação de uma biblioteca pessoal, esta parte da série aborda a implementação das interfaces gráficas responsáveis pela manutenção dos dados dos livros do acervo. O destaque desta etapa é a criação de um formulário mestre-detalhe, onde a tabela mestre corresponde a livro e a tabela detalhe consiste dos autores do livro. Na GUI, os campos de um registro da tabela mestre são exibidos por componentes dos tipos JTextField, JSpinner e JCheckBox, além dos rótulos desses campos que utilizam JLabel. Já os dados do detalhe são exibidos e manipulados por um JTable, onde em cada linha da tabela se pode visualizar os dados de um autor.

Em que situação o tema é útil
O tema é útil para aqueles desenvolvedores que precisam criar formulários com relacionamento mestre-detalhe, como é o caso do relacionamento entre livro e autores. Além disso, o uso de novos widgets é ensinado, aumentando a caixa de ferramentas do programador de GUIs.

Nesta série de artigos estamos desenvolvendo uma aplicação adotando um processo muito simples cujos passos foram definidos em uma matéria da Easy Java Magazine nº 4. Na primeira parte da série, publicada na Easy Java Magazine 27, foram definidos os requisitos da aplicação a ser desenvolvida e em seguida, as classes de negócio e persistentes foram criadas. As classes de negócio (ou de domínio) são Autor, Livro e Emprestimo. AutorDB, LivroDB e EmprestimoDB formam as classes persistentes, as quais utilizam os serviços da classe Conexao, cuja função é definir uma conexão com o banco de dados utilizado.

Na segunda parte, publicada na Edição 29, foi definido o projeto da interface gráfica da aplicação e um mapa navegacional que oferece uma visão geral de como o usuário irá navegar através das telas do programa. Tendo como base essa proposta, foi criada a tela principal, cujo componente mais importante é um JMenuBar, que, juntamente com um JMenu e um JMenuItem, são responsáveis por acionar as demais janelas da aplicação.

Na sequência foram desenvolvidas as classes cuja função é fazer a manutenção da tabela que guarda os autores das obras da biblioteca. Assim, foram criadas as classes AutorUI, que contém um widget JTable, cuja função é apresentar uma lista dos autores cadastrados, e CadastroAutorUI, a qual insere ou modifica um autor.

Seguindo esse mesmo princípio de projeto, iremos criar nesta etapa as classes LivroUI e CadastroLivroUI, cujas funções são semelhantes àquelas das classes de interface AutorUI e CadastroAutorUI, mas que apresentam alguns widgets novos, tais como JComboBox, JSpinner e JCheckBox.

Tela para visualização de Livros

Esta tela terá a aparência que mostramos na Figura 1. Nela será implementado um JTable que será utilizado para visualizar os livros cadastrados, e os botões Atualizar, Novo, Alterar e Remover.

Tela Livros do menu Cadastros

Figura 1. Tela Livros do menu Cadastros.

O botão Atualizar tem a função de fazer uma nova leitura no banco de dados para exibir os dados que tenham sido recentemente modificados na tabela. O botão Novo é usado para inserir um livro novo na base de dados. Já os botões Alterar e Remover atuam sobre uma linha selecionada no JTable para modificar os dados já inseridos ou deletá-los do banco.

Após essa descrição geral da interface, podemos iniciar a sua criação. Para isso, serão seguidos os mesmos passos apresentados na segunda parte desta série, empregados para construir a classe AutorUI. Visto que naquela oportunidade já foram mostradas as explicações e justificativas para cada situação, os passos serão resumidos. Deste modo:

1. Acesse o menu de contexto do pacote br.com.bibliotecapessoal.ui e escolha New | Other;

2. Selecione WindowBuilder > Swing Designer > JFrame e em seguida clique em Next;

3. Use “LivroUI” para o nome da classe e pressione Finish;

4. No código da classe, exclua o método main() criado pela ferramenta;

5. Após selecionar a aba Design, clique na barra de título da janela para mostrar o JFrame criado, e no Painel de Propriedades digite “Livro” na propriedade title e selecione HIDE_ON_CLOSE na propriedade defaultCloseOperation;

6. Agora clique no JPanel e defina o gerenciador de layout que será usado, clicando na propriedade Layout e escolhendo GroupLayout;

7. Em seguida, coloque um JButton no canto inferior direito, de maneira que ele fique alinhado conforme as linhas guia, e digite “Remover” no rótulo;

8. Adicione mais três botões, cada um sempre à esquerda do anterior respeitando o alinhamento, e defina seus rótulos como “Alterar”, “Novo” e “Atualizar”;

9. Localize o JScrollPane no grupo Containers da Paleta e posicione-o no canto superior esquerdo da janela, arrastando o mouse, conforme mostra a Figura 2, até que ele ocupe todo o espaço restante do JFrame, observando sempre as linhas guia;

Posicionando o JScrollPane na janela

Figura 2. Posicionando o JScrollPane na janela

10. Finalmente, para encerrar o desenho da interface, vamos adicionar um JTable ao JScrollPane. Para isto, posicione o JTable sobre a região viewport do JScrollPane.

Concluída a etapa de posicionamento dos widgets sobre o JFrame, iniciaremos a adição de código Java na classe LivroUI. Comecemos pela definição de alguns atributos, conforme pode ser visto na Listagem 1.

Listagem 1. Código da classe LivroUI após a definição do DefaultTableModel.


    public class LivroUI extends JFrame {
   
    private JPanel contentPane;
    private JTable tbLivro;
    private DefaultTableModel modelo = new DefaultTableModel();
    private List<Livro> lista;
    /**
     * Create the frame.
     */
    public LivroUI() {
     // código do construtor
    }
  }

Um dos atributos que foram declarados no código da Listagem 1 é um DefaultTableModel, pois como já sabemos os componentes Swing utilizam a arquitetura MVC (Model View Controller), e essa classe implementa o model padrão de um JTable, o qual é responsável pela distribuição dos dados na tabela. Além desse atributo, definiu-se também um List, que terá a função de receber a lista de livros consultados no banco de dados.

Depois dessa modificação, localize o trecho de código onde o JTable é instanciado. Acrescente as duas linhas anteriores à criação do objeto, mostradas na Listagem 2, e altere a linha tbLivro = new JTable() para que o construtor receba como parâmetro o model definido como atributo.

Listagem 2. Criação dos cabeçalhos de coluna no JTable.


   String[] nomesColuna = {"Código", "ISBN", "Título","Edição","Ano"};
   modelo.setColumnIdentifiers(nomesColuna);
   tbLivro = new JTable(modelo);
   tbLivro.getColumnModel().getColumn(0).setPreferredWidth(100);
   tbLivro.getColumnModel().getColumn(1).setPreferredWidth(120);
   tbLivro.getColumnModel().getColumn(2).setPreferredWidth(400);
   tbLivro.getColumnModel().getColumn(3).setPreferredWidth(100);
   tbLivro.getColumnModel().getColumn(4).setPreferredWidth(100);

A primeira linha na Listagem 2 define por meio de um array os identificadores de colunas no JTable. Na linha seguinte este array é adicionado ao model através da chamada ao método setColumnIdentifiers(). Por sua vez, as chamadas ao método setPreferredWidth() definem larguras diferentes para cada coluna da tabela.

A fim de popular o JTable com os dados da tabela Livro, será criado um método denominado atualizaTabela(), cujo código mostramos na Listagem 3.

Listagem 3. Método que tem a função de povoar o JTable.


     private void atualizaTabela() {
      LivroDB livroDB = new LivroDB();
      lista = livroDB.buscarTodos();
      Iterator<Livro> it = lista.iterator();
      Livro a;
      while (modelo.getRowCount() > 0) {
          modelo.removeRow(0);
      }
      while (it.hasNext()) {
        a = it.next();
        modelo.addRow(new Object[] {a.getId(), a.getIsbn(), 
        a.getTitulo(), a.getAnoEdicao(), a.getEdicao()});
      }
    }

No método atualizaTabela(), o atributo lista recebe os dados da tabela de banco de dados Livro retornados através da chamada ao método buscarTodos(). Em seguida, para limpar o JTable, são removidas todas as linhas existentes, utilizando-se chamadas sucessivas ao método removeRow(). Após limpar o JTable, faz-se uma iteração através de lista, adicionando cada um de seus elementos no modelo, por meio de chamadas a addRow(). Tal método deve receber como parâmetro um Vector de Object, onde cada elemento do vetor corresponde a uma coluna da tabela mostrada.

Após finalizarmos a criação deste método, precisamos definir onde ele será invocado. O primeiro local é no botão Atualizar, de maneira que, sempre que este for pressionado, os dados atualizados da tabela Livro sejam exibidos no JTable. Esta ação será obtida através do evento ActionEvent. A outra situação, onde nos interessa atualizar os dados, é quando a JFrame for aberta. Isto será conseguido através do evento WindowEvent, que define todos os eventos de janela, tais como abrir, fechar, ativar, entre outros.

Vamos definir, portanto, o tratamento de eventos do JButon Atualizar. Clique então com o botão direito sobre o botão Atualizar e selecione Action event handler > Action > ActionPerformed. Isto determinará a criação de um tratador de eventos e a abertura do editor de código no ponto onde devem ser inseridas as instruções que devem ser executadas. Na Listagem 4 é mostrado o trecho de código que corresponde a esse ActionListener.

Listagem 4. Adicionando um tratador de eventos ao botão Atualizar.


   JButton btnAtualizar = new JButton("Atualizar");
   btnAtualizar.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent arg0) {
       atualizaTabela();
     }
   });

O passo seguinte consiste em adicionar o WindowListener que vai tratar o evento de janela. Destaque o JFrame clicando sobre sua barra de título ou selecionando o componente na Árvore de Componentes. Em seguida, clique com o botão direito sobre a janela e escolha a opção Add event handler > Window > WindowOpened. Mostramos a parte do código correspondente a esse listener na Listagem 5.

Listagem 5. Adicionando um tratador de eventos para ser disparado na abertura do JFrame.

 ... 

Quer ler esse conteúdo completo? Tenha acesso completo