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(300, 150);
           frame.setVisible(true);
         }
       };
       EventQueue.invokeLater(runner);
     }
   } 
        
Tabela

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

Linhas responsáveis pela ordenação

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 ordenação.

Se você quiser adicionar sua própria ação quando for feita a ordenação, 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(300, 250);
                    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.

Execução do código

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

Após a filtragem ser feita, será apresentado apenas uma linha da tabela.

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.