无法按日期对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
组件将能够:
- 提供适当的渲染器/编辑器。 请参阅概念:编辑器和渲染器
- 自动创建行分类器,能够按预期对行进行排序。
有关更好的说明,请参阅如何使用表教程的排序和筛选部分。 但简而言之:
要确定要用于列的
Comparator
,TableRowSorter
尝试依次应用以下每个规则。 按照下面列出的顺序遵循规则; 使用第一个为分拣机提供Comparator
器的规则,并忽略剩余规则。
- 如果通过调用
setComparator
指定了比较器,请使用该比较器。- 如果表模型报告列数据由字符串组成(T
ableModel.getColumnClass
返回该列的String.class
),请使用比较器根据当前语言环境对字符串进行排序。- 如果
TableModel.getColumnClass
返回的列类实现Comparable
,请使用比较器,该比较器根据Comparable.compareTo
返回的值对字符串进行排序。- 如果通过调用
setStringConverter
为表指定了字符串转换器,请使用比较器,该比较器根据当前语言环境对结果字符串表示进行排序。- 如果以前的规则都不适用,请使用比较器对列数据调用
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中查看更多内容。