PeakGen
PeakGen

Reputation: 23025

Unable to sort the JTable by Date

I have a JTable, where the first column of it is a Date. However, this is not actually a Date object, it is a String which display the date in UK format. Below is my code

private class DisplayAllRevenue extends ComponentAdapter
     {
         @Override
         public void componentShown(ComponentEvent e)
         {
             DefaultTableModel model = (DefaultTableModel) allRevenueTable.getModel();
             model.setRowCount(0);


             dbConnector = new DBHandler();
             dbConnector.makeConnection();

             java.sql.Date dateOfLastUpdate=null;


             ResultSet portfolioRs = dbConnector.selectAllDetails(getPortfolioData);

             try
             {
                 if(portfolioRs.isBeforeFirst()==false)
                 {
                     JOptionPane.showMessageDialog(null,"Empty");
                 }
                 else
                 {
                     while(portfolioRs.next())
                     {
                         String provider = portfolioRs.getString("Provider Name");
                         String client = portfolioRs.getString("Client Name");
                         int idPortfolio = portfolioRs.getInt("idPortfolio");
                         dateOfLastUpdate = portfolioRs.getDate("Update_Date");


                         String dateOfLastUpdateS = getDateInUKFormat(convertSQLDateToJavaDate(dateOfLastUpdate));

                         Object[]row3 = {dateOfLastUpdateS, provider, client, idPortfolio};

                         model.addRow(row3);
                         }

                     }

                    //Sort the Table
                    DefaultRowSorter sorter = ((DefaultRowSorter)allRevenueTable.getRowSorter()); 
                    ArrayList list = new ArrayList();
                    list.add( new RowSorter.SortKey(0, SortOrder.DESCENDING) );
                    sorter.setSortKeys(list);
                    sorter.sort();
                 }
             }
             catch(SQLException sql)
             {
                 JOptionPane.showMessageDialog(null,"Error displaying data");
                 sql.printStackTrace();
             }
             finally
             {
                 dbConnector.closeConnection();
             }
         }
     }

As you can see, I am trying to sort the table by the Date. But unfortunately, it didn't work! Everything just went out of order. I am wondering this because the Date is actually a String.

So, how can I sort by table "correctly" according to the Date ?

Upvotes: 1

Views: 953

Answers (1)

dic19
dic19

Reputation: 17971

I am wondering this because the Date is actually a String.

Yes, most likely. Note that you don't have to mix the data contained in the table model with its representation. In this case you could perfectly have a Date object and show it in UK format or whatever format you like. Even better, for internationalization trade you could let the table cell renderer/editor resolve the current locale and apply a date format accordingly.

The whole matter is about retrieving the appropriate class in the table model implementation by overriding getColumnClass(columnIndex) method. If we do this correctly, then JTable component will be able to:

For a better explanation see Sorting and Filtering section of How to Use Tables tutorial. But in a nutshell:

To determine which Comparator to use for a column, TableRowSorter attempts to apply each of the following rules in turn. Rules are followed in the order listed below; the first rule that provides the sorter with a Comparator is used, and the remainining rules ignored.

  1. If a comparator has been specified by invoking setComparator, use that comparator.
  2. If the table model reports that the column data consists of strings (TableModel.getColumnClass returns String.class for that column), use a comparator that sorts the strings based on the current locale.
  3. If the column class returned by TableModel.getColumnClass implements Comparable, use a comparator that sorts the strings based on the values returned by Comparable.compareTo.
  4. If a string convertor has been specified for the table by invoking setStringConverter, use a comparator that sorts the resulting string representations based on the current locale.
  5. If none of the previous rules apply, use a comparator that invokes toString on the column data and sorts the resulting strings based on the current locale.

Since Date class implements Comparable interface, then it's a case of point 3. So, once again, overriding getColumnClass() correctly will lead you to solve your problem.


Off-topic

Please note database calls are time consuming tasks and may block the Event Dispatch Thread (EDT) causing the GUI become unresponsive. The EDT is a single and special thread where Swing components creation and update must be performed and event handling take place.

Having said that, take a look to this part in your code:

private class DisplayAllRevenue extends ComponentAdapter {
     @Override
     public void componentShown(ComponentEvent e) {
         // Event handling code: it is performed in the EDT
     }
}

If you make database calls every time the component is shown then you'll have severe performance issues. You might consider add a button to let the users refresh the table's data instead of trying to do that automatically when the component is shown.

Additionally, in order to avoid blocking the EDT you might consider use a SwingWorker to perform database calls in a background thread and update Swing components in the EDT. See more in Concurrency in Swing trail.

Upvotes: 4

Related Questions