Tutorial sobre JTable do Swing - parte I

Bruno Rios Lima

Aprenda a usar o JTable do pacote Swing.

Download do material relacionado ao tutorial



Tutorial do JTable do Swing


Com esse tutorial voce aprenderá a criar desde uma JTable simples, até uma complexa,
utilizando as princpais classes ( editor, renderer, model, etc ).

Este tutorial estará subdividindo em diversos capitlos, aumentando sua complexidade
a medida que entrarmos em um novo capítulo.


CAPITULO 1 - Construindo uma JTable Simples

Introdução:

A classe JTable é utilizada para vizualizar dados em grid no Swing e é um dos componentes mais complexos desse pacote. Alias o JTable possui até um pacote especial, que contém diversas classes para sua utilização: javax.swing.table.

A JTable é um componente MVC: o seu trabalho é dividido em 3 partes:

Model: É a parte que cuida dos dados, quem controla e distribui os dados na jtable. É implementado pela interface TableModel ( AbstractTableModel e DefaultTableModel ). Ela é responsavel por fornecedor os dados para a tabela, a qual requisitará os dados atraves do método getValueAt, informando a linha e a coluna. Este método retorna um Object, ou seja, um objeto qualquer, que pode ser um Integer, uma String ou uma outra classe que você tenha implementado.

View: É a parte que cuida da apresentação. É implementado pela interface CellRenderer. É como a apresentação é dada celula a celula na tabela, o renderer deve ser fornecedido para uma celula especifica. Na Jtable é possivel fornecer tanto um renderer para a tabela inteira como para uma coluna especifica. Assim como na tablemodel requisitará o valor na linha e coluna especifica, aqui ele requisitara o objeto que ira apresentar o dados, passando como parametro a linha, a coluna o valor (object), a tabela (jtable), se esta celula esta selecionada e se ela celula possui o foco. Este método é o getCellRendererComponent, que irá retornar um JComponent. O DefaultCellRenderer implementa o JLabel para apresentar os dados, que é a forma de apresentação mais comum para um valor.

Controller: É a parte que controla a apresentação dos dados na view. É a própria JTable.

Como a JTable ja vem implementada para usar os tipos defaults existentes e implementados, para criar uma jtable simples não é tão complicado. O unico problema é que voce acaba se engessando quando precisar de algum recurso mais "completo".



Criando uma JTable

Vamos agora conhecer uma forma de contruir uma JTable, simplesmente fornecedor os dados que quero exibir nela.

1  String[] colunas = new String []{"Estado","Cidade"};
2  String[][] dados = new String [][] {
3         {"SP","Sao Paulo"},
4         {"RJ","Rio de Janeiro"},
5         {"RN","Rio Grande do Norte"},
6         {"PR","Parana"}
7  };
8         
9  JTable jtable = new JTable(dados, colunas);  


O exemplo acima cria uma instância da classe JTable passando como argumentos as variáveis dados e colunas. Existem diversos contrutores para a JTable, e um deles é a passagem de arrays (linhas e colunas) como argumentos. Este é o modo mais simples de fornecer à JTable os dados que deseja exibir. Ela utliza toda a estrutura default para exibição deste codigo.



Trabalhando com a JTable: DefaultTableModel()

Tendo nossa JTable criada, podemos trabalhar em cima do modelo (TableModel) que ela criou. Para obtermos o modelo dessa JTable criada, basta chamarmos o método getModel() que retorna uma instância de classe que implementa o TableModel. Como o argumento para criação de nossa JTable foi uma coleção, o modelo utilizado internamente foi o DefaultTableModel. O DefaultTableModel é uma classe de javax.swing.table e implementa a interface TableModel, fornecedo-nos todo o controle dos dados da JTable. Claro que é uma classe com métodos básicos para trabalhar com os dados da JTable.

- getValueAt(): obtem o valor de uma determinada linha e coluna na JTable.
- setValueAt(): seta o valor em uma determinada linha e coluna na JTable.
- addRow(): adiciona uma nova linha na JTable. Recebe um array simples.
- addColumn(): adiciona uma nova coluna no modelo.

Com base no exemplo anterior, digamos que seria necessario adicionar outras linhas apos a criação da nossa JTable. Vamos alterar nosso codigo para tirarmos o peso de controlar os dados da própria JTable e jogar esse trabalho pro DefaultTableModel:

01  String[][] dados = new String [][]{
02                {"SP","Sao Paulo"},
03                {"RJ","Rio de Janeiro"},
04                {"RN","Rio Grande do Norte"},
05                {"PR","Parana"}
06  };
07  String[] colunas = new String []{"Estado","Cidade"};
08  // Ao inves de passar direto, colocamos os dados em um modelo
09  DefaultTableModel modelo = new DefaultTableModel(dados, colunas);
10  // e passamos o modelo para criar a jtable
11  JTable jtable = new JTablemodelo );


O que fizemos foi pegar as colunas e os dados, e jogá-los em alguém para cuidar deles: no caso um TableModel, que é o responsavel por controlar os dados de uma JTable.


Agora que criamos uma JTable passando um TableModel que controla os dados, podemos trabalhar em cima desse modelo. Uma coisa que devemos ter em mente é sempre saber que modelo tal JTable está usando, pois assim podemos pega-lo de volta e trabalhar em cima dele.

- addRow()

Digamos que, na nossa tela, colocamos um novo botão para incluir novas linhas nessa minha JTable. E para tal, criamos o método adicionaLinha(), chamado pelo ActionPerformed deste botão. Este método irá obter o nosso modelo, quem controla os dados, e incluirá uma nova linha em branco.

1  /**
2   * Método para adicionar uma nova linha na JTable
3   */
4  public void adicionaLinha() {
5   // Obtem o modelo da JTable
6   DefaultTableModel modelo = (DefaultTableModel)getTabela().getModel();
7   // Adiciona uma nova linha em branco no modelo
8   modelo.addRownew String [] {""""} );
9  }


- removeRow()

A mesmo coisa poderia ser feito se quisermos deletar uma determinada linha. Digamos que vamos excluir a linha atualmente selecionada. Para saber qual linha está selecionada, devemos perguntar a JTable, que é o controlador. O método utilizado é o getSelectedRow() e retorna um int, a linha selecionada. Se nao houver linhas selecionadas, o retorno é -1.

01     /**
02      * Remove a linha do modelo.
03      @param linha
04      */
05     public void removeLinha(int linha){
06         
07         // Obtem o modelo da JTable
08         DefaultTableModel modelo = (DefaultTableModel)getTabela().getModel();
09         
10         // Remove a linha 
11         modelo.removeRow(linha);
12 
13     }
14     
15     /**
16      * Obtem a linha selecionada e chama o método para remover
17      * do modelo
18      */
19     public void removeLinha(){
20         
21         // Obtem a linha selecionada na tabela e chama o método
22         // para excluir a linha
23         int linhaSelecionada = getTabela().getSelectedRow();
24         
25         // Verificamos se existe realmente alguma linha selecionada
26         iflinhaSelecionada < ){
27             return;
28         }else{
29             // Remove a linha do modelo
30             removeLinha(linhaSelecionada);
31         }
32         
33 
34     }


- ListSeleciont

Trabalhar com seleção de linhas e colunas na JTable tambem é um trabalho a parte. Existem métodos para obter nao só a linha, mas o numero de linhas selecionadas, as linhas selecionadas ( que retorna um array de int[] ). Assim como as linhas, os mesmos métodos se encontram para obter as colunas seleciondas. Vale a pena dar uma olhada na API da JTable para conferir estes métodos. Para setar o modo de seleção no qual sua JTable irá trabalahar, vamos permitir somente a seleção de linhas ( unicas ) e nao multiplas.

1     .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);


- getValueAt e setValueAt

Em algum ponto de sua aplicação, voce pode querer substituir o conteúdo de uma celula, ou de várias linhas em uma determinada coluna. Com os métoso getValueAt e setValueAt podemos obter e setar o valor em uma determinada coluna e linha.

Vamos criar um método para subtituir um determinado valor por outro, em uma coluna especifica.

01     /**
02      * Método para subtituir um valor por outro em uma determinada
03      * coluna.
04      @param oldValue
05      @param newValue
06      @param column
07      @return Numero de substituições
08      */
09     public int substituirValor(String oldValue, String newValue, int column){
10         // Flag para saber se algum valor foi
11         int total = 0;
12         // Obtem o modelo da JTable
13         DefaultTableModel modelo = (DefaultTableModel)getTabela().getModel();
14         // Faz um looping em cima das linhas do modelo
15         forint linha=0; linha<modelo.getRowCount(); linha++){
16             // Obtem o valor atual na coluna
17             String valorAtual = (String)modelo.getValueAt(linha, column);
18             ifvalorAtual.equals(oldValue) ){
19                 // Substitui pelo novo valor na linha e coluna
20                 modelo.setValueAt(newValue, linha, column);
21                 // Adiciona mais um no numero de linhas atualizadas            
22                 total++;
23             }
24         }
25         return total;
26     }


Poderiamos ter utilizado o Iterator para trabalhar em cima dos dados, basta obter o iterator do vetor de linhas dos dados retornado pelo modelo e obter os valor por meio de array de strings.

1         Iterator i = modelo.getDataVector().iterator();
2         String [] row = i.next();



Implementando meu próprio TableModel

Para implementar o TableModel, existem diversos pontos que devemos cobrir - devemos tratar o controle dos dados ( colunas e linhas ). Uma opção simples para começarmos, será a de estender a classe AbstractTableModel que fornece diversos métodos já sobrescritos exceto aqueles que retornam dados:

- public Object getValueAt( int row, int col )
- public int getRowCount()
- public int getColumnCount()

Esta classe também já implementa 7 métodos de atualização da JTable ( TableModelEvents ). Estes métodos são utilizados para informar as alterações ocorridas dentro de um modelo. Exemplo seria a inclusão de uma nova linha, que dispara o método fireTableRowsInserted. Durante a criação dos métodos para trabalhar com os dados, iremos ver estes eventos.

Mas este assunto vamos tratar na próxima parte do artigo.

Até lá!


Copyright © 2002-2006 GUJ | Todas as marcas e marcas registradas que aparecem no GUJ são de propriedade de seus respectivos donos