Ordenando e Filtrando Tabelas com o Java SE 6.0

 

Java Standard Edition (Java SE) 6.0 (chamado Mustang), adiciona algumas características que possibilitam fazer a ordenação e a filtragem de dados em um JTable de forma mais simples. Algumas tabelas mais modernas permitem ao usuário fazer a ordenação da coluna apenas clicando no cabeçalho desta tabela. Isto pode ser feito com o JTable. Porém esta funcionalidade(ordenar a coluna) teve que ser implementada manualmente para cada tabela que precisasse desta característica. Com o Mustang, este trabalho é reduzido. Filtrar é outra opção geralmente disponível nas interfaces do usuário. Filtrar os dados, permite aos usuários exibir somente as filas de uma tabela que sejam necessárias ao usuário. Com o Mustang, o processo de filtragem também é facilitado.

 

Ordenando as linhas de uma tabela 

A base da ordenação e filtragem de linhas no Mustang é a classe abstrata RowSorter. RowSorter mantém o mapeamento de linhas em um JTable para os elementos do modelo subjacente. Isto permite fazer a ordenação e a filtragem. A classe é genérica o sufiente para trabalhar com TableModel e ListModel. Porém, somente a classe TableRowSorter pode ser utilizada quando estamos utilizando o JTable.

No caso mais simples, você passa o TableModel ao constructor de TableRowSorter, e então passa o RowSorter criado no método setRowSorter() de JTable. O código abaixo é um programa de exemplo, que demonstra a ordenação em uma tabela:

   import javax.swing.*;
   import javax.swing.table.*;
   import java.awt.*;

   public class SortTable {
     public static void main(String args[]) {
       Runnable runner = new Runnable() {
        public void run() {
           JFrame frame = new JFrame("Ordenando um JTable");
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           Object rows[][] = {
               {"AMZN""Amazon"41.28},
               {"EBAY""eBay"41.57},
               {"GOOG""Google"388.33},
               {"MSFT""Microsoft"26.56},
               {"NOK""Nokia Corp"17.13},
               {"ORCL""Oracle Corp."12.52},
               {"SUNW""Sun Microsystems"3.86},
               {"TWX",  "Time Warner"17.66},
               {"VOD",  "Vodafone Group"26.02},
               {"YHOO""Yahoo!"37.69}
             };
           String columns[] = {"Sigla""Nome""Preço"};
           TableModel model =
               new DefaultTableModel(rows, columns) {
             public Class getColumnClass(int column) {
               Class returnValue;
               if ((column >= 0) && (column < getColumnCount())) {
                 returnValue = getValueAt(0, column).getClass();
               else {
                 returnValue = Object.class;
               }
               return returnValue;
             }
           };

           JTable table = new JTable(model);
           RowSorter<TableModel> sorter =
             new TableRowSorter<TableModel>(model);
           table.setRowSorter(sorter);
           JScrollPane pane = new JScrollPane(table);
           frame.add(pane, BorderLayout.CENTER);
           frame.setSize(300150);
           frame.setVisible(true);
         }
       };
       EventQueue.invokeLater(runner);
     }
   

fig1ordenacao e filt.JPG

Clique em uma das colunas da tabela exibida, e note que seu conteúdo é reordenado.

fig2ordenacao e filt.JPG

Estas são as três linhas responsáveis pela ordenação, fundamentais no programa apresentado anteriormente:

           JTable table = new JTable(model);
           RowSorter<TableModel> sorter =
             new TableRowSorter<TableModel>(model);
           table.setRowSorter(sorter);

A primeira linha associa o modelo com a tabela. A segunda linha cria um modelo específico de RowSorter.  A terceira linha associa o RowSorter com o JTable. Isto permite a um usuário clicar sobre o cabeçalho da coluna para que esta seja ordenada. Clicar uma segunda vez na mesma coluna inverte a ordem da ordenacao.

Se você quiser adicionar sua própria ação quando for feita a ordenacao, você pode ligar o RowSorterListener ao RowSorter. A interface tem um método que permite isso:

   void sorterChanged(RowSorterEvent e)

O método permite que você atualize o texto na barra de status, ou executa alguma tarefa adicional.  O RowSorterEvent permite que você descubra quantas linhas estavam presentes antes da sorte, caso o RowSorter filtrar linhas.

Filtrando as linhas da tabela
Você pode associar um RowFilter com o TableRowSorter e usá-lo para filtrar os índices de uma tabela.  Por exemplo, você pode usar o RowFilter de forma que uma tabela indica somente as linhas onde o nome começa com a letra A, ou onde o preço conservado em estoque é maior que $50.  A classe abstrata RowFilter tem um método que é usado para filtragem:

   boolean include(RowFilter.Entry entry)

Para cada entrada no modelo associado com o RowSorter, o método indica se a entrada especificada deve ser mostrada na vista atual do modelo.  Em muitos casos, você não necessita criar sua própria execução de RowFilter. O RowFilter ja oferece seis métodos estáticos para criar filtros.

·         andFilter(Iterable<? extends RowFilter<? super M,? super I>> filters) 
     dateFilter(RowFilter.ComparisonType type, Date date, int... indices)
     notFilter(RowFilter<M,I> filter)
     numberFilter(RowFilter.ComparisonType type, Number number, int... indices)
     orFilter(Iterable<? extends RowFilter<? super M,? super I>> filters)
     regexFilter(String regex, int... indices)

Para o RowFilter, somente o conjunto das colunas que correspondem aos índices especificados é verificado dentro o modelo. Se nenhum índice for especificado, todas as colunas serao verificadas para ver se há algum elemento em comum.

O dateFilter permite que você verifique se há datas iguais. O numberFilter checa se existem numeros em comum.  O notFilter é usado invertendo um outro filtro, ou seja inclui as entradas que o filtro fornecido desprezou.  Você pode usá-lo para fazer coisas como por exemplo: encontrar as informações que não foram geradas em 12/25/2005.  O andFilter e o orFilter (filtros logicos) podem ser utilizados para combinar um ou mais filtros. O regexFilter usa uma expressão regular para fazer a filtragem. Abaixo esta um programa chamado FilterTable  que usa um regexFilter para filtrar o índice da tabela:

   import javax.swing.*;
   import javax.swing.table.*;
   import java.awt.*;
   import java.awt.event.*;
   import java.util.regex.*;

   public class FilterTable {
     public static void main(String args[]) {
       Runnable runner = new Runnable() {
         public void run() {
           JFrame frame = new JFrame("Ordenando JTable");
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           Object rows[][] = {
             {"AMZN""Amazon"41.28},
             {"EBAY""eBay"41.57},
             {"GOOG""Google"388.33},
             {"MSFT""Microsoft"26.56},
             {"NOK""Nokia Corp"17.13},
             {"ORCL""Oracle Corp."12.52},
             {"SUNW""Sun Microsystems"3.86},
             {"TWX",  "Time Warner"17.66},
             {"VOD",  "Vodafone Group"26.02},
             {"YHOO""Yahoo!"37.69}
           };
           Object columns[] = {"Sigra""Nome""Preco"};
           TableModel model =
              new DefaultTableModel(rows, columns) {
             public Class getColumnClass(int column) {
               Class returnValue;
               if ((column >= 0) && (column < getColumnCount())) {
                 returnValue = getValueAt(0, column).getClass();
               else {
                 returnValue = Object.class;
               }
               return returnValue;
             }
           };
           JTable table = new JTable(model);
           final TableRowSorter<TableModel> sorter =
                   new TableRowSorter<TableModel>(model);
           table.setRowSorter(sorter);
           JScrollPane pane = new JScrollPane(table);
           frame.add(pane, BorderLayout.CENTER);
           JPanel panel = new JPanel(new BorderLayout());
           JLabel label = new JLabel("Filtro");
           panel.add(label, BorderLayout.WEST);
           final JTextField filterText =
               new JTextField("SUN");
           panel.add(filterText, BorderLayout.CENTER);
           frame.add(panel, BorderLayout.NORTH);
           JButton button = new JButton("Filtro");
           button.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
               String text = filterText.getText();
               if (text.length() == 0) {
                 sorter.setRowFilter(null);
               else {
                 try {
                   sorter.setRowFilter(
                       RowFilter.regexFilter(text));
                 catch (PatternSyntaxException pse) {
                   System.err.println("Erro");
                 }
               }
             }
           });
           frame.add(button, BorderLayout.SOUTH);
           frame.setSize(300250);
           frame.setVisible(true);
         }
       };
       EventQueue.invokeLater(runner);
     }
   }

A figura abaixo apresenta a execução do código apresentado acima. Neste exemplo faremos uma filtragem, fazendo com que apareça apenas siglas que contenham a palavra SUN.

fig3ordenacao e filt.JPG

Apos a filtragem ser feita, serah apresentado apenas uma linha da tabela. Isso pode ser visto na figura abaixo.

fig4ordenacao e filt.JPG

Mude o texto do filtro para mudar o conjunto de linhas mostradas na tabela.  Se você quiser ver todas as linhas na tabela, remova o texto do filtro.

Para mais informações sobre RowSorter, TableRowSorter, e RowFilter veja o javadoc javadoc dessas classes:

·                                 RowSorter

·                                 TableRowSorter

·                                 RowFilter 

 

Neste artigo voce conheceu mais algumas novidades do Java SE 6.0, mais conhecido como Mustang.