简体   繁体   English

无法按日期对JTable排序

[英]Unable to sort the JTable by Date

I have a JTable, where the first column of it is a Date. 我有一个JTable,它的第一列是一个Date。 However, this is not actually a Date object, it is a String which display the date in UK format. 但是,这实际上不是Date对象,而是一个String ,以UK格式显示日期。 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 . 如您所见,我正在尝试按Date对表格进行排序。 But unfortunately, it didn't work! 但不幸的是,它没有用! Everything just went out of order. 一切都乱了。 I am wondering this because the Date is actually a String . 我想知道这是因为Date实际上是一个String

So, how can I sort by table "correctly" according to the Date ? 因此,如何根据日期对表进行“正确”排序?

I am wondering this because the Date is actually a String. 我想知道这是因为Date实际上是一个字符串。

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. 在这种情况下,您可以完美地拥有一个Date对象,并以UK格式或您喜欢的任何格式显示它。 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. 整个问题是有关通过重写getColumnClass(columnIndex)方法在表模型实现中检索适当的类的。 If we do this correctly, then JTable component will be able to: 如果我们正确地做到这一点,那么JTable组件将能够:

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. 为了确定要使用哪个Comparator列, TableRowSorter尝试依次应用以下每个规则。 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. 使用为分类器提供Comparator器的第一条规则,其余规则被忽略。

  1. If a comparator has been specified by invoking setComparator , use that comparator. 如果通过调用setComparator指定了一个比较器,请使用该比较器。
  2. If the table model reports that the column data consists of strings (T ableModel.getColumnClass returns String.class for that column), use a comparator that sorts the strings based on the current locale. 如果表模型报告列数据由字符串组成( ableModel.getColumnClass返回该列的String.class ),请使用比较器,该比较器根据当前语言环境对字符串进行排序。
  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 . 如果TableModel.getColumnClass返回的列类实现Comparable ,请使用比较器,该比较器根据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. 如果通过调用setStringConverter为表指定了字符串转换器,请使用比较器,该比较器根据当前语言环境对结果字符串表示形式进行排序。
  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. 如果没有上述任何规则,请使用比较器,该比较器在列数据上调用toString并根据当前语言环境对结果字符串进行排序。

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. 由于Date类实现了Comparable接口,所以这是第3点的情况。因此,再次正确地重写getColumnClass()会导致您解决问题。


Off-topic 无关

Please note database calls are time consuming tasks and may block the Event Dispatch Thread (EDT) causing the GUI become unresponsive. 请注意,数据库调用是耗时的任务,并且可能会阻塞事件调度线程(EDT),从而导致GUI无法响应。 The EDT is a single and special thread where Swing components creation and update must be performed and event handling take place. EDT是一个单独的特殊线程,在其中必须执行Swing组件的创建和更新以及进行事件处理。

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. 另外,为了避免阻塞EDT,您可以考虑使用SwingWorker在后台线程中执行数据库调用并更新EDT中的Swing组件。 See more in Concurrency in Swing trail . 在Swing并发中查看更多内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM