无法按日期对JTable进行排序

我有一个JTable,其中第一列是Date。 但是,这实际上不是Date对象,它是一个以英国格式显示日期的String 。 以下是我的代码

 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(); } } } 

如您所见,我正在尝试按Date对表进行排序。 但不幸的是,它没有用! 一切都失灵了。 我想知道这个,因为Date实际上是一个String

那么,如何根据日期“正确”按表排序?

我想知道这个,因为Date实际上是一个String。

是的,很有可能。 请注意,您不必将表模型中包含的数据与其表示混合。 在这种情况下,您可以完美地拥有一个Date对象,并以英国格式或您喜欢的任何格式显示它。 更好的是,对于国际化交易,您可以让表格单元格渲染器/编辑器解析当前区域设置并相应地应用日期格式。

整个问题是通过重写getColumnClass(columnIndex)方法来检索表模型实现中的相应类。 如果我们正确地执行此操作,那么JTable组件将能够:

  • 提供适当的渲染器/编辑器。 请参阅概念:编辑器和渲染器
  • 自动创建行分类器,能够按预期对行进行排序。

有关更好的说明,请参阅如何使用表教程的排序和筛选部分。 但简而言之:

要确定要用于列的ComparatorTableRowSorter尝试依次应用以下每个规则。 按照下面列出的顺序遵循规则; 使用第一个为分拣机提供Comparator器的规则,并忽略剩余规则。

  1. 如果通过调用setComparator指定了比较器,请使用该比较器。
  2. 如果表模型报告列数据由字符串组成(T ableModel.getColumnClass返回该列的String.class ),请使用比较器根据当前语言环境对字符串进行排序。
  3. 如果TableModel.getColumnClass返回的列类实现Comparable ,请使用比较器,该比较器根据Comparable.compareTo返回的值对字符串进行排序。
  4. 如果通过调用setStringConverter为表指定了字符串转换器,请使用比较器,该比较器根据当前语言环境对结果字符串表示进行排序。
  5. 如果以前的规则都不适用,请使用比较器对列数据调用toString ,并根据当前语言环境对结果字符串进行排序。

由于Date类实现了Comparable接口,因此它是第3点的情况。因此,再次正确地覆盖getColumnClass()将引导您解决问题。


无关

请注意数据库调用是耗时的任务,可能会阻止事件调度线程(EDT)导致GUI无响应。 EDT是一个单独的特殊线程,必须执行Swing组件的创建和更新,并进行事件处理。

话虽如此,请在代码中查看此部分:

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

如果每次显示组件时都进行数据库调用,那么您将遇到严重的性能问题。 您可以考虑添加一个按钮,让用户刷新表的数据,而不是在显示组件时尝试自动执行该操作。

此外,为了避免阻止EDT,您可以考虑使用SwingWorker在后台线程中执行数据库调用并更新EDT中的Swing组件。 在Swing trail中的Concurrency中查看更多内容。