3

I have this code below, in which, after a mouseClick event it filters the rows based on a JList getSelectedItem().toString(), here is the code:

try{
        TableRowSorter<TableModel> rowSorter = new TableRowSorter<>(easypath.doctorBusiness_table.getModel());
        easypath.doctorBusiness_table.setRowSorter(rowSorter);
        String selected = easypath.drname_jlist.getSelectedValue().toString();
        rowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + selected));

    }

It works fine, and filters the rows based on the selected String.


But, I further I wish to filter the filtered model based on dates, although the date filtering works fine on the DefaultTableModel but when I try to pass the current table model it does not work

So, I hope I could explain my problem here as I need to pass a filtered TableModelfor date filtering. Any suggestions would help.

Thanks for your time

UPDATE

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.RowFilter;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class testFilter extends javax.swing.JFrame {

    public testFilter() {
        initComponents();
    }

public void dateSearch() {
    try {
        DateFormat format = new SimpleDateFormat("dd/MM/yyyy");

        String string1 = "01/07/2015";
        Date startDate = format.parse(string1);
        System.out.println(startDate);

        String string2 = "31/07/2015";
        Date endDate = format.parse(string2);
        System.out.println(endDate);

        TableRowSorter<TableModel> rowSorter = new TableRowSorter<>(dataTable.getModel());
        dataTable.setRowSorter(rowSorter);

        List<RowFilter<Object, Object>> filters = new ArrayList<RowFilter<Object, Object>>(2);
        filters.add(RowFilter.dateFilter(RowFilter.ComparisonType.AFTER, startDate));
        filters.add(RowFilter.dateFilter(RowFilter.ComparisonType.BEFORE, endDate));
        RowFilter<Object, Object> rf = RowFilter.andFilter(filters);
        rowSorter.setRowFilter(rf);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void dateString_Search(){
    try {
        TableRowSorter<TableModel> rowSorter = new TableRowSorter<>(dataTable.getModel()); //  String Filtering 
        dataTable.setRowSorter(rowSorter);                                                 //  table here
        String selected = "Nissan SUV";                                                    //  to get
        rowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + selected));                  //  current TableModel 

        JOptionPane.showMessageDialog(null, dataTable.getRowCount()); // <--- For checking current Row Count

        DateFormat format = new SimpleDateFormat("dd/MM/yyyy");

        String string1 = "01/07/2015";
        Date startDate = format.parse(string1);
        System.out.println(startDate);
        String string2 = "31/07/2015";
        Date endDate = format.parse(string2);
        System.out.println(endDate);

        TableRowSorter<TableModel> filteredRowSorter = new TableRowSorter<>(dataTable.getModel()); //<-- Getting the current table Model After String Search
        dataTable.setRowSorter(filteredRowSorter); 
        List<RowFilter<Object, Object>> filters = new ArrayList<RowFilter<Object, Object>>(2);
        filters.add(RowFilter.dateFilter(RowFilter.ComparisonType.AFTER, startDate));
        filters.add(RowFilter.dateFilter(RowFilter.ComparisonType.BEFORE, endDate));
        RowFilter<Object, Object> rf = RowFilter.andFilter(filters);
        filteredRowSorter.setRowFilter(rf);


    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, e);
    }
}



private void initComponents() {

    jScrollPane1 = new javax.swing.JScrollPane();
    dataTable = new javax.swing.JTable();
    dateSearch_btn = new javax.swing.JButton();
    stringSearch_btn = new javax.swing.JButton();
    dateStringSearch_btn = new javax.swing.JButton();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setResizable(false);

    dataTable.setModel(new javax.swing.table.DefaultTableModel(
        new Object [][] {
            {"Nissan Micra", new Date(), "20000"},
            {"Nissan SUV", new Date(), "30000"},
            {"Nissan SUV", new Date(), "40000"},
            {"Nissan SUV", new Date(), "50000"},
            {"Nissan SUV", new Date(), "50000"},
            {"Ford Mustang", new Date(), "70000"},
            {"Ford Cobra", new Date(), "70000"},
            {"Nissan SUV", new Date(), "40000"},
            {"Nissan SUV", new Date(), "60000"},
            {"Nissan SUV", new Date(), "65000"},
            {"Nissan SUV", new Date(), "70000"},
            {"Tata Sumo", new Date(), "70000"}
        },
        new String [] {
            "Name", "Date", "Rate"
        }
    ));
    putDateInTable();
    jScrollPane1.setViewportView(dataTable);

    dateSearch_btn.setText("Date Search");
    dateSearch_btn.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            dateSearch_btnActionPerformed(evt);
        }
    });

    stringSearch_btn.setText("String Search");
    stringSearch_btn.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            stringSearch_btnActionPerformed(evt);
        }
    });

    dateStringSearch_btn.setText("Date+String");
    dateStringSearch_btn.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            dateStringSearch_btnActionPerformed(evt);
        }
    });

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 463, Short.MAX_VALUE)
                .addGroup(layout.createSequentialGroup()
                    .addComponent(dateSearch_btn)
                    .addGap(90, 90, 90)
                    .addComponent(stringSearch_btn)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(dateStringSearch_btn)))
            .addContainerGap())
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 223, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(18, 18, 18)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(dateSearch_btn)
                .addComponent(stringSearch_btn)
                .addComponent(dateStringSearch_btn))
            .addContainerGap(25, Short.MAX_VALUE))
    );

    pack();
}

private void stringSearch_btnActionPerformed(java.awt.event.ActionEvent evt) {                                                 
    try {
        TableRowSorter<TableModel> rowSorter = new TableRowSorter<>(dataTable.getModel());
        dataTable.setRowSorter(rowSorter);
        String selected = "Nissan SUV";
        rowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + selected));
        JOptionPane.showMessageDialog(null, dataTable.getRowCount());

    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, e);
    }
}

private void dateSearch_btnActionPerformed(java.awt.event.ActionEvent evt) {                                               
    dateSearch();
}

private void dateStringSearch_btnActionPerformed(java.awt.event.ActionEvent evt) {                                                     
    dateString_Search();
}

private void putDateInTable() {
    Date formatDate = new Date();
    Calendar c = Calendar.getInstance();
    c.setTime(formatDate);
    c.add(Calendar.DATE, - 1);

    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 0, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, +5);

    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 1, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, +1);

    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 2, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, - 16);

    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 3, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, +30);

    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 4, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, +55);

    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 5, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, +155);

    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 6, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, -23);

    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 7, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, -22);

    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 8, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, -21);
    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 9, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, -29);
    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 10, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, -50);
    formatDate = c.getTime();
    dataTable.setValueAt(formatDate, 11, 1);
    c.setTime(formatDate);
    c.add(Calendar.DATE, +100);


}

public static void main(String args[]) {

    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new testFilter().setVisible(true);
        }
    });
}
private javax.swing.JTable dataTable;
private javax.swing.JButton dateSearch_btn;
private javax.swing.JButton dateStringSearch_btn;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JButton stringSearch_btn;
}

Here is the modified code for the filtering, Created the eventListeners dateSearch, stringSearch and dateStringSearch. First two works fine but the third one is not working properly even if I try to create a get the current model. Please suggest, Thanks

mustangDC
  • 945
  • 1
  • 12
  • 33
  • @camickr, You have mistaken, i would request to re-read the question till the end, date is the question here – mustangDC Jul 18 '15 at 19:57
  • `I need to filter the filtered rows` - you need an "andFilter" like was demonstrated in your last question. When you use "&&" if an if statement are you limited to only two conditions or can you use more than two conditions? – camickr Jul 18 '15 at 19:58
  • Yes, you are absolutely correct, but what I have asked here is not completely dependent on the dates, I have also mentioned about `JList` here, where the problem is not the dates but **I AM NOT GETTING THE FILTERED TABLE MODEL** depending on the String passed form `JList`, for which I have provided full details – mustangDC Jul 18 '15 at 20:02
  • @camickr, I hope I have successfully explained what I am trying to achieve here – mustangDC Jul 18 '15 at 20:05
  • 1
    I'm not talking about the dates. You have a filter condition you created from the selected item in the JList, then you have two more conditions for the dates, so you have an "andFilter" with 3 conditions. You can't do two separate filters, you need to combine all the condition into one filter. – camickr Jul 18 '15 at 20:05
  • I completely understand what you are trying to state here, but that does not work because the program logic is unable to give the filtered table model, which is an input for date date filtering(works fine) – mustangDC Jul 18 '15 at 20:12
  • 2
    `I completely understand what you are trying to state here` - I don't think so. `does not work because the program logic is unable to give the filtered table model,` - you can't give the filtered table model (unless you want to copy all the data and create an new TableModel to display in the table. You are trying to filter the original TableModel with 3 conditions, not 1. – camickr Jul 18 '15 at 20:18
  • Ok, now I have got what you have said. Wil try now and let you know, Thanks :) – mustangDC Jul 18 '15 at 20:18
  • Could you help with the construct as I have tried passing table rowfilter to the date filter but it does not work, if you want I can update the question and post what I triied – mustangDC Jul 18 '15 at 20:43
  • @camickr : wOULD YOU LIKE HELP ME WITH THE CODE CONSTRUCT ABOUT THE CURRENT ROWFILTERING? i AM NEW TO JAVA AND I AM CURRENTLY TRYING TO EXPAND MY KNOWLEDGE. WOULD VERY MUCH APPRECIATE IF YOU KINDLY SUGGEST ME WITH THE CODE FOR THE **THIRD FILTER** – mustangDC Jul 19 '15 at 15:10
  • `i AM NEW TO JAVA AND I AM CURRENTLY TRYING TO EXPAND MY KNOWLEDGE.` - start by learning how to create a [SSCCE](http://sscce.org/) to demonstrate a problem. The point of a `SSCCE` is to simplify the problem. So create a frame with a table (and a few rows of hardcoded data) and 3 buttons. The first button will simple filter on a keyword. The second button will filter on a date range. The third button will combine the first and second filters in an "and filter" to filter on 3 conditions. Show us the effort you have made and we can make suggestions. You don't learn if we write the code for you. – camickr Jul 19 '15 at 18:19
  • First get the filters working with hardcode conditions. That is hard code the filter string. Once you get the basic concept working you can move on to making the filter dynamic by getting the filter string from the JList. Same with the dates. Use hard coded dates and later provide a Swing component for the user to change the data range. – camickr Jul 19 '15 at 18:22
  • posting the SSCCE ASAP – mustangDC Jul 19 '15 at 18:29
  • the main fact is I cannot append the **third filter**. Anyways I will be posting my code, – mustangDC Jul 19 '15 at 18:49
  • Updated the code, as suggested by you. Please see.@camickr – mustangDC Jul 20 '15 at 16:12

2 Answers2

1

Why are you trying to get the TableModel after the string search? I said you can't do this unless you want to copy all the data and create a new TableModel.

The TableModel doesn't change when you do filtering on the JTable. All the data is still stored in the TableModel. What changes is the View. The JTable only displays the filtered rows.

Why does your filter code not look like the code from the Swing tutorial on filtering? In your code you create a new TableRowSorter and add it to the table. In the Swing tutorial they just reset the filter on the TableRowSorter using the setRowFilter(...) method. This is minor, but it demonstrates to me that you haven't read the tutorial or if you did, why did you modify the code to make is more complex?

In my comments I suggested you have an "andFilter" with 3 conditions. I tried to explain this multiple ways comparing it to an if statement with 3 conditions. Why does your "andFilter" only have two conditions when you do the "date/string search"?

I copied the code from the "date search" and made the following changes to create your date/string filter:

List<RowFilter<Object, Object>> filters = new ArrayList<RowFilter<Object, Object>>(3);
String selected = "Nissan SUV";
filters.add(RowFilter.regexFilter("(?i)" + selected)); // added the string filter
filters.add(RowFilter.dateFilter(RowFilter.ComparisonType.AFTER, startDate));
filters.add(RowFilter.dateFilter(RowFilter.ComparisonType.BEFORE, endDate));
RowFilter<Object, Object> rf = RowFilter.andFilter(filters);
rowSorter.setRowFilter(rf);

Now you have an "andFilter" with 3 conditions.

However a better design would be to create methods like getStartDateFilter(), getEndDateFilter(), getStringFilter() so you don't duplicate code. Then you can build the filter like:

List<RowFilter<Object, Object>> filters = new ArrayList<RowFilter<Object, Object>>(3);
filters.add(getStringFilter());
filters.add(getStartDateFilter());
filters.add(getEndDateFilter();
RowFilter<Object, Object> rf = RowFilter.andFilter(filters);
rowSorter.setRowFilter(rf);
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Oh sorry for the mistake, i tried 3 `andfilters`, and everything you told is of course correct. The client demands to design the code like this. So he can see the table in three different ways. – mustangDC Jul 21 '15 at 04:47
  • One more thing that I mistakenly posted this code as I was trying to know **Why the table cannot give me the current model whereas it gives me the current row count** . In `public void dateString_Search(){}` I gave a `JOptionPane` to show the current row count. But anyways now I learnt that it will be `DefaultTableModel` always. Still a long way to go for me. But a huge Thanks – mustangDC Jul 21 '15 at 04:51
  • 1
    @mustangDC, The requirement of 3 filters is fine. How the code is designed is up to you. Reusable code is easier to maintain and provides flexibility. A filtered table just keeps a List (or maybe an Array) of indexes into the real TableModel. Same as when you reorder columns. The TableModel doesn't change. The table just keeps track of the column order itself. This is how the Model-View-Controller design work. The Model stores the data and in Swing the View (which is a combined View-Controller) displays the data. The View can display the data however it wants – camickr Jul 21 '15 at 14:42
1

Unfortunately, the design of JTable functionality treats TableSorter along with its underlying RowFilter as non-model functionality. As a result, it does not create a wrapping TableModel instance. Instead, JTable works directly with the sorter to display rows correctly.

As a hack, you can create your own TableModel that wraps entire underlying JTable, listens to its updates and returns cell values as they appear in JTable. Depending on where you intend to use such a model, this might be horrible or brilliant idea. Take a look at the example below to get an idea of what I'm talking about. Please note, that listening and event firing functionality is not done properly in the example below. It needs a lot more work to properly listen and react to various model and UI events, so the date in the model always reflects JTable's contents. Architecturally, this model should not be considered a proper model class, but it allows other tables to display data in sync with underlying JTable.

public class UIBasedTableModel extends AbstractTableModel {
    private final JTable _underlyingTable;

    public UIBasedTableModel(JTable underlyingTable) {
        _underlyingTable = underlyingTable;
        _underlyingTable.addPropertyChangeListener("sorter", new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
               fireTableDataChanged();
            }
        });
        _underlyingTable.getModel().addTableModelListener(new TableModelListener() {

            @Override
            public void tableChanged(TableModelEvent e) {
                fireTableDataChanged();
            }
        });
    }

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

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

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return _underlyingTable.getValueAt(rowIndex, columnIndex);
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return _underlyingTable.getColumnClass(columnIndex);
    }

    @Override
    public String getColumnName(int columnIndex) {
        return _underlyingTable.getColumnName(columnIndex);
    }
}

Another alternative would be to implement a similar sorting/filtering functionality on your own. That might also be a good and bad idea at the same time as you would have to properly integrate sorting into the TableUI.

I would be happy to elaborate more, but would have to know your requirements.

ATrubka
  • 3,982
  • 5
  • 33
  • 52