Combine Rowfilter.andFilter with Rowfilter.orFilter

Asked

Viewed 97 times

1

I have a project that has a table and items to be filtered. They are a categoryJComboBox, an id JTextField and a date interval JDateCooser.

I made all filters separately with RowFilter.andFilter and now I need to join them in one RowFilter.orFilter so that anyone can happen at any time.

I need it to be possible to filter table data using different combinations of filled fields:

  • category, name and date range simultaneously (filtered)
  • category only (filterCateg)
  • name only (filtroId, yes the name is that same)
  • date range only (filterData)
  • name and date range simultaneously (filterIdData)
  • category and name simultaneously (filterIdCateg)
  • category and date interval simultaneously (filterDattateg)

They all need to be possible to happen according to what the program user decides to fill when pressing the filter button.

Representing category by C, name by N and date range by D what I need to happen would look like this:

((C && N && D) || (C) || (N) || (D) || (N && D) || (C && N) || (C && D))

Filters

    import java.awt.Dimension;
    import java.util.Date;
    import java.util.HashSet;
    import java.util.Set;
    import javax.swing.JButton;
    import javax.swing.JScrollBar;
    import javax.swing.JScrollPane;
    import javax.swing.RowFilter;
    import javax.swing.RowFilter.ComparisonType;
    import javax.swing.table.TableModel;
    import javax.swing.table.TableRowSorter;


    public class Filtros extends javax.swing.JFrame {

        private final int ITENS_POR_PAG = 5;

        public Filtros() {
            initComponents();
        }

        private void initComponents() {

            jScrollPane = new javax.swing.JScrollPane();
            table = new javax.swing.JTable();
            btnFirst = new javax.swing.JButton();
            btnPrevious = new javax.swing.JButton();
            btnNext = new javax.swing.JButton();
            btnLast = new javax.swing.JButton();
            lblCategoria = new javax.swing.JLabel();
            cbxCategoria = new javax.swing.JComboBox<>();
            jLabel1 = new javax.swing.JLabel();
            txtNome = new javax.swing.JTextField();
            btnFiltrar = new javax.swing.JButton();
            lblDataDeInicio = new javax.swing.JLabel();
            jdcDataDeInicio = new com.toedter.calendar.JDateChooser();
            lblDataDeFim = new javax.swing.JLabel();
            jdcDataDeFim = new com.toedter.calendar.JDateChooser();

            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

            jdcDataDeInicio.setDateFormatString("dd/MM/yyyy");
            jdcDataDeFim.setDateFormatString("dd/MM/yyyy");

            model = new MatriculaTableModel(JSONUtils.JSONtoList());
            table.setModel(model);
            sorter = new TableRowSorter<TableModel>(model);
            table.setRowSorter(sorter);   
            table.setDefaultRenderer(Date.class, new MatriculaTableRenderer());

            jScrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
                    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            jScrollPane.setPreferredSize(new Dimension(getPreferredSize().width - 20, table.getRowHeight() * ITENS_POR_PAG + table.getTableHeader().getPreferredSize().height));

            jScrollPane.setViewportView(table);


            btnFirst = new JButton("<<");
            btnFirst.addActionListener(e -> {
                JScrollBar bar = jScrollPane.getVerticalScrollBar();
                bar.setValue(0);
            });

            btnPrevious = new JButton("<");
            btnPrevious.addActionListener(e -> {
                int height = table.getRowHeight() * (ITENS_POR_PAG);
                JScrollBar bar = jScrollPane.getVerticalScrollBar();
                bar.setValue(bar.getValue() - height);
            });

            btnNext = new JButton(">");
            btnNext.addActionListener(e -> {
                int height = table.getRowHeight() * (ITENS_POR_PAG);
                JScrollBar bar = jScrollPane.getVerticalScrollBar();
                bar.setValue(bar.getValue() + height);
            });

            btnLast = new JButton(">>");
            btnLast.addActionListener(e -> {
                JScrollBar bar = jScrollPane.getVerticalScrollBar();
                bar.setValue(bar.getMaximum());
            });

            btnFiltrar.addActionListener(e -> {
                aplicaFiltros();
            });

            lblCategoria.setText("Categoria");

            cbxCategoria.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Todas", "Fundamental", "Médio" }));

            jLabel1.setText("Nome:");

            btnFiltrar.setText("Filtrar");

            lblDataDeInicio.setText("De:");

            lblDataDeFim.setText("Até:");

            javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
            getContentPane().setLayout(layout);
            layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                .addGroup(layout.createSequentialGroup()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(layout.createSequentialGroup()
                                    .addGap(94, 94, 94)
                                    .addComponent(btnFirst)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(btnPrevious)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(btnNext)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(btnLast))
                                .addGroup(layout.createSequentialGroup()
                                    .addContainerGap()
                                    .addComponent(lblDataDeInicio)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(jdcDataDeInicio, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addGap(18, 18, 18)
                                    .addComponent(lblDataDeFim)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(jdcDataDeFim, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)))
                            .addGap(0, 16, Short.MAX_VALUE))
                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                            .addComponent(lblCategoria)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(cbxCategoria, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                            .addComponent(jLabel1)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(txtNome)
                            .addGap(18, 18, 18)
                            .addComponent(btnFiltrar)))
                    .addContainerGap())
            );
            layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addComponent(jScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(btnFirst)
                        .addComponent(btnPrevious)
                        .addComponent(btnNext)
                        .addComponent(btnLast))
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 21, Short.MAX_VALUE)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(cbxCategoria, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(lblCategoria)
                        .addComponent(jLabel1)
                        .addComponent(txtNome, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(btnFiltrar))
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(lblDataDeInicio)
                        .addComponent(jdcDataDeInicio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(lblDataDeFim)
                        .addComponent(jdcDataDeFim, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGap(20, 20, 20))
            );

            pack();
        }// </editor-fold>               

            public static void main(String args[]) {
            /* Set the Nimbus look and feel */
            //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
            /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
             * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
             */
            try {
                for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(info.getName())) {
                        javax.swing.UIManager.setLookAndFeel(info.getClassName());
                        break;
                    }
                }
            } catch (ClassNotFoundException ex) {
                java.util.logging.Logger.getLogger(Filtros.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (InstantiationException ex) {
                java.util.logging.Logger.getLogger(Filtros.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                java.util.logging.Logger.getLogger(Filtros.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (javax.swing.UnsupportedLookAndFeelException ex) {
                java.util.logging.Logger.getLogger(Filtros.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
            //</editor-fold>

            /* Create and display the form */
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new Filtros().setVisible(true);
                }
            });
        }

     public void aplicaFiltros(){

            String nome = txtNome.getText().trim(),
                    categoria = cbxCategoria.getSelectedItem().toString().trim();      

            Date dataInicio = jdcDataDeInicio.getDate(),
                    dataFim = jdcDataDeFim.getDate();

            //Filtra Categoria, nome e intervalo de data (AND)
            Set<RowFilter<Object, Object>> filtrosAnd = new HashSet<>();
            String frmNome = String.format("^%s$", nome);
            filtrosAnd.add(RowFilter.regexFilter(frmNome, 1));

            if(!categoria.equals("Todas")) {
                String frmCateg = String.format("^%s$", categoria);
                filtrosAnd.add(RowFilter.regexFilter(frmCateg, 3));
            }

            filtrosAnd.add(RowFilter.dateFilter(ComparisonType.AFTER, dataInicio, 2));
            filtrosAnd.add(RowFilter.dateFilter(ComparisonType.BEFORE, dataFim, 2));
            sorter.setRowFilter(RowFilter.andFilter(filtrosAnd));

/*
            //Filtra só categoria
            Set<RowFilter<Object, Object>> filtroCateg = new HashSet<>();

            if(!categoria.equals("Todas")) {
                String frmCateg = String.format("^%s$", categoria);
                filtroCateg.add(RowFilter.regexFilter(frmCateg, 3));
            }
            sorter.setRowFilter(RowFilter.andFilter(filtroCateg));

            //Filtra só nome
            Set<RowFilter<Object, Object>> filtroId = new HashSet<>();

            frmNome = String.format("^%s$", nome);
            filtroId.add(RowFilter.regexFilter(frmNome, 1));

            sorter.setRowFilter(RowFilter.andFilter(filtroId));

            //Filtra só intervalo de data

            Set<RowFilter<Object, Object>> filtroData = new HashSet<>();

            filtroData.add(RowFilter.dateFilter(ComparisonType.AFTER, dataInicio, 2));
            filtroData.add(RowFilter.dateFilter(ComparisonType.BEFORE, dataFim, 2));

            sorter.setRowFilter(RowFilter.andFilter(filtroData));

            //Filtra nome e intervalo de data
            Set<RowFilter<Object, Object>> filtroIdData = new HashSet<>();

            frmNome = String.format("^%s$", nome);
            filtroId.add(RowFilter.regexFilter(frmNome, 1));

            filtroIdData.add(RowFilter.dateFilter(ComparisonType.AFTER, dataInicio, 2));
            filtroIdData.add(RowFilter.dateFilter(ComparisonType.BEFORE, dataFim, 2));

            sorter.setRowFilter(RowFilter.andFilter(filtroIdData));

            //Filtra categoria e nome
            Set<RowFilter<Object, Object>> filtroIdCateg = new HashSet<>();

            frmNome = String.format("^%s$", nome);
            filtroIdCateg.add(RowFilter.regexFilter(frmNome, 1));

            if(!categoria.equals("Todas")) {
                String frmCateg = String.format("^%s$", categoria);
                filtroIdCateg.add(RowFilter.regexFilter(frmCateg, 3));
            }
            sorter.setRowFilter(RowFilter.andFilter(filtroIdCateg));

            //Filtra categoria e intervalo de data
            Set<RowFilter<Object, Object>> filtroDataCateg = new HashSet<>();

            filtroDataCateg.add(RowFilter.dateFilter(ComparisonType.AFTER, dataInicio, 2));
            filtroDataCateg.add(RowFilter.dateFilter(ComparisonType.BEFORE, dataFim, 2));

            if(!categoria.equals("Todas")) {
                String frmCateg = String.format("^%s$", categoria);
                filtroDataCateg.add(RowFilter.regexFilter(frmCateg, 3));
            }
            sorter.setRowFilter(RowFilter.andFilter(filtroDataCateg)); */

        }

        // Variables declaration - do not modify                     
        private javax.swing.JButton btnFiltrar;
        private javax.swing.JButton btnFirst;
        private javax.swing.JButton btnLast;
        private javax.swing.JButton btnNext;
        private javax.swing.JButton btnPrevious;
        private javax.swing.JComboBox<String> cbxCategoria;
        private com.toedter.calendar.JDateChooser jdcDataDeFim;
        private javax.swing.JLabel jLabel1;
        private JScrollPane jScrollPane;
        private com.toedter.calendar.JDateChooser jdcDataDeInicio;
        private javax.swing.JLabel lblCategoria;
        private javax.swing.JLabel lblDataDeFim;
        private javax.swing.JLabel lblDataDeInicio;
        private javax.swing.JTable table;
        private javax.swing.JTextField txtNome;
            private MatriculaTableModel model;
        private TableRowSorter<TableModel> sorter;
        // End of variables declaration                   
    }

Jsonutils

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

public class JSONUtils {

    private static String strjson = null;

    private JSONUtils() {

        if (strjson == null)
            strjson = lerArquivo();
    }

    public static List<MatriculaModel> JSONtoList() {
        String str = lerArquivo();
        Type type = new TypeToken<List<MatriculaModel>>() {
        }.getType();

        Gson gson = new GsonBuilder().setDateFormat("dd/MM/yyyy").create();      

        List<MatriculaModel> lista = gson.fromJson(str, type);

        for (MatriculaModel teste : lista) {
            System.out.println(teste.getSelecionado());
            System.out.println(teste.getNome());
            System.out.println(teste.getData());
        }
        return lista;
    }

    private static String lerArquivo() {
        String linha = "";

        try {
            FileReader arq = new FileReader("C:\\Users\\maily\\Documents\\NetBeansProjects\\Filtros\\src\\filtros\\dados.json");
            BufferedReader lerArq = new BufferedReader(arq);

            linha = lerArq.readLine();
            /*
             * while (linha != null) { System.out.printf(linha); linha = lerArq.readLine();
             * // lê da segunda até a última linha }
             */
            arq.close();

        } catch (IOException e) {
            System.err.printf("Erro na abertura do arquivo: %s.\n", e.getMessage());
        }
        // System.out.println(linha);
        return linha;
    }

}

Matriculamodel

import java.util.Date;

public class MatriculaModel {
    private boolean selecionado;
    private String nome;
    private Date data;
    private String categoria;

    public boolean getSelecionado() {
        return selecionado;
    }

    public void setSelecionado(boolean selecionado) {
        this.selecionado = selecionado;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Date getData() {
        return data;
    }

    public void setData(Date data) {
        this.data = data;
    }

    public String getCategoria() {
        return categoria;
    }

    public void setCategoria(String categoria) {
        this.categoria = categoria;
    }


}

Matriculatablemodel

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.table.AbstractTableModel;

public class MatriculaTableModel extends AbstractTableModel {


    private List<MatriculaModel> dados = new ArrayList<>();
    private final String[] colunas = {"Selecionar", "Nome", "Data", "Categoria"};

    public MatriculaTableModel(List<MatriculaModel> model) {
        this.dados = model;
    }


    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0:
                return Boolean.class;
            case 2:
                return Date.class;
            default:
                return super.getColumnClass(columnIndex);
        }
    }

    @Override
    public String getColumnName(int column){
        return colunas[column];
    }

    @Override
    public int getColumnCount() {
        return colunas.length;
    }

    @Override
    public int getRowCount() {
        return dados.size();
    }

    @Override
    public Object getValueAt(int linha, int coluna) {
        switch(coluna){
            case 0:
                return dados.get(linha).getSelecionado();
            case 1:
                return dados.get(linha).getNome();
            case 2:
                return dados.get(linha).getData();
            case 3:
                return dados.get(linha).getCategoria();
        }

        return null;
    }

    public void setValueAt(Object valor, int linha, int coluna) {
        MatriculaModel tm = dados.get(linha);
        switch (coluna) {
        case 0:
            tm.setSelecionado(new Boolean((Boolean) valor));
            break;
        }
        fireTableDataChanged();
    }

    public void addRow(MatriculaModel tm) {
        this.dados.add(tm);
        this.fireTableDataChanged();    
    }

    public void removeRow(int linha){
        this.dados.remove(linha);
        this.fireTableRowsDeleted(linha, linha);
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return columnIndex == 0; 
    }

    public void deletarLinhas() {
        this.dados.clear();
        this.fireTableDataChanged();
    }

}

Matriculatablerenderer

import java.awt.Component;
import java.text.SimpleDateFormat;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

public class MatriculaTableRenderer extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        switch (column) {
            case 2:
                setText(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(value));
                break;
            default:
                break;
        } 
        return this;
    }

    @Override
    protected void setValue(Object value) {
        super.setValue(value); 
    }      
}

json data.

[{"selecionado": false, "nome": "João", "data": "23/10/2000 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Maria", "data": "03/05/2006 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Pedro", "data": "30/02/2002 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Laura", "data": "03/07/2008 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Manoel", "data": "05/11/2018 00:00:00", "categoria": "Fundamental"},{"selecionado": false, "nome": "João", "data": "23/10/2000 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Maria", "data": "03/05/2006 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Pedro", "data": "30/02/2002 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Laura", "data": "03/07/2008 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Manoel", "data": "05/11/2018 00:00:00", "categoria": "Fundamental"},{"selecionado": false, "nome": "João", "data": "23/10/2000 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Maria", "data": "03/05/2006 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Pedro", "data": "30/02/2002 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Laura", "data": "03/07/2008 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Manoel", "data": "05/11/2018 00:00:00", "categoria": "Fundamental"}]

Download libs: Jcalendar, Gson

  • Again, it is not clear what is filter or what should be filter and, it may seem clear to you who made the code, but it is not clear to who is reading your question. You need to be more specific.

1 answer

1


You don’t need all this complexity, the filter you’re using already does that, you just check the fields before adding them, the ones that aren’t filled (are null or blank), you don’t add in the list andfilters.

If you always add all fields, the filter will always require all fields to be filled in, or will pop some exception when trying to apply the filters and there is some null or unfilled field. If you pass only those that the user fills in, the filter is applied only to them.

See below:

inserir a descrição da imagem aqui

  • It is not so simple unfortunately. I edited the question to try to explain better.

  • @Maybe because you didn’t read the documentation. If you want to use separate filters, you don’t need to orfilter, andfilter already does that. Just don’t add empty fields. Again I reinforce that not reading the documentation is only making Oce create unnecessary complexity for a simple problem. The solution you want is not the easiest solution to this problem, which makes your doubt an XY problem again

  • I don’t really know if I understand. If the user doesn’t want to fill in, there will be some empty field and the and won’t work.

  • @Lys is just do not pass the fields that are not filled in to the filter, simple. See the edition of the answer proving that it is so simple, it does not need as much logical complexity as the one you suggested in the question.

  • And not the amount of stuff I implemented in the code. I just need to test the fields first. Now I get it. Thank you so much for your patience to understand my prolema and even more to try to make me understand the solution.

  • @Lys yes, it’s very simple, if Voce doesn’t want that in the filter, just don’t add, don’t reproduce in code you already did it yourself, when checking if the combobox is selected. Just play the check for the other fields, only you now have to check if it is different from null or is empty (empty)

  • It was exactly this simplicity that was not in my head. I was already able to reproduce in the original code. I thank you again.

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.