Reputation: 23025
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
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 aComparator
is used, and the remainining rules ignored.
- If a comparator has been specified by invoking
setComparator
, use that comparator.- If the table model reports that the column data consists of strings (T
ableModel.getColumnClass
returnsString.class
for that column), use a comparator that sorts the strings based on the current locale.- If the column class returned by
TableModel.getColumnClass
implementsComparable
, use a comparator that sorts the strings based on the values returned byComparable.compareTo
.- 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.- 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.
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