I have the following jtable jtable image I get the information from a database and everything is saved as string in the table, I just want to sort the second column "Fecha de recepcion" which has dates in the format dd-mm-yyyy
, I used a row classifier but it takes the dates as strings.
I made a TableCellRenderer
for just that column and applied the following properties
Table.getColumnModel().getColumn(1).setCellRenderer( new Render());
Table.setAutoCreateRowSorter(true);
but it still sorts it as string.
I would really appreciate if someone can guide me on what I'm doing wrong
This is my class that implements TableCellRenderer
public class Render implements TableCellRenderer{
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
LocalDate date = LocalDate.parse(value.toString(),formatter);
Component c = renderer.getTableCellRendererComponent(table,
date, isSelected, hasFocus, row, column);
return c;
}
}
The important thing here is the data, what's in the TableModel
, as this is what the table will use to sort by.
Based on LocalDate date = LocalDate.parse(value.toString(),formatter);
it would appear that your data is String
based, which will be the cause of you core problem.
Instead, you data should be using LocalDate
. LocalDate
is comparable by default, so you don't need any "special" comparators or additional support, it will "just work" out of the box, for example, unsorted, descending, ascending...
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
long minDay = LocalDate.of(1970, 1, 1).toEpochDay();
long maxDay = LocalDate.of(2015, 12, 31).toEpochDay();
List<LocalDate> dates = new ArrayList<>(100);
for (int index = 0; index < 100; index++) {
long randomDay = ThreadLocalRandom.current().nextLong(minDay, maxDay);
dates.add(LocalDate.ofEpochDay(randomDay));
}
JTable table = new JTable(new ExampleTabelModel(dates));
table.setDefaultRenderer(LocalDate.class, new DateCellRenderer());
table.setAutoCreateRowSorter(true);
add(new JScrollPane(table));
}
}
public class DateCellRenderer extends DefaultTableCellRenderer {
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof LocalDate) {
value = ((LocalDate) value).format(formatter);
}
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
public class ExampleTabelModel extends AbstractTableModel {
private List<LocalDate> dates;
public ExampleTabelModel(List<LocalDate> dates) {
this.dates = dates;
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0: return "Rows";
case 1: return "Dates";
}
return null;
}
@Override
public int getRowCount() {
return dates.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return Integer.class;
case 1:
return LocalDate.class;
}
return Object.class;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return rowIndex;
case 1:
return dates.get(rowIndex);
}
return null;
}
}
}