Invalid date sorting in JTable

Please see below code

import java.awt.*; import java.awt.event.*; import java.text.NumberFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.*; import javax.swing.table.*; public class TableBasic extends JFrame { public TableBasic() { String[] columnNames = {"Date", "String", "Long", "Boolean"}; Object[][] data = { {getJavaDate("13-11-2020"), "A", new Long(1), Boolean.TRUE }, {getJavaDate("13-11-2018"), "B", new Long(2), Boolean.FALSE}, {getJavaDate("12-11-2015"), "C", new Long(9), Boolean.TRUE }, {getJavaDate("12-11-2015"), "D", new Long(4), Boolean.FALSE} }; final JTable table = new JTable(data, columnNames); table.setPreferredScrollableViewportSize(table.getPreferredSize()); table.setAutoCreateRowSorter(true); table.getColumnModel().getColumn(0).setCellRenderer(tableCellRenderer); // DefaultRowSorter has the sort() method DefaultRowSorter sorter = ((DefaultRowSorter)table.getRowSorter()); ArrayList list = new ArrayList(); list.add( new RowSorter.SortKey(0, SortOrder.DESCENDING) ); sorter.setSortKeys(list); sorter.sort(); JScrollPane scrollPane = new JScrollPane( table ); getContentPane().add( scrollPane ); } private TableCellRenderer tableCellRenderer = new DefaultTableCellRenderer() { SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy"); public Component getTableCellRendererComponent(JTable table,Object value, boolean isSelected, boolean hasFocus,int row, int column) { if( value instanceof Date) { value = f.format(value); } return super.getTableCellRendererComponent(table, value, isSelected,hasFocus, row, column); } }; private Date getJavaDate(String s) { try { SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); Date d = sdf.parse(s); return d; } catch (ParseException ex) { Logger.getLogger(TableBasic.class.getName()).log(Level.SEVERE, null, ex); return null; } } public static void main(String[] args) { TableBasic frame = new TableBasic(); frame.setDefaultCloseOperation( EXIT_ON_CLOSE ); frame.pack(); frame.setLocationRelativeTo( null ); frame.setVisible(true); } } 

Now try sorting it using the Date field. This is sorting in an invalid way! Below is the result!

enter image description here

Why is this happening like this? I even used cell render !

+5
source share
3 answers

@Sniper is not the answer, but I can not resist, because your code is very complicated, incorrect, miss the extra weight there, necessary for ...

Invalid key element is overriding TableModel.getColumnClass (), this is necessary to sort the table for the function

 import java.awt.*; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.*; import static javax.swing.JFrame.EXIT_ON_CLOSE; import javax.swing.table.*; public class TableBasic { private JFrame frame = new JFrame(); private String[] columnNames = {"Date", "String", "Long", "Boolean"}; private Object[][] data = { {getJavaDate("13-11-2020"), "A", new Double(1), Boolean.TRUE}, {getJavaDate("13-11-2018"), "B", new Double(2), Boolean.FALSE}, {getJavaDate("12-11-2015"), "C", new Double(9), Boolean.TRUE}, {getJavaDate("12-11-2015"), "D", new Double(4), Boolean.FALSE} }; private DefaultTableModel model = new DefaultTableModel(data, columnNames) { @Override public Class<?> getColumnClass(int column) { return getValueAt(0, column).getClass(); } }; private JTable table = new JTable(model); private JScrollPane scrollPane = new JScrollPane(table); private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy"); public TableBasic() { table.setPreferredScrollableViewportSize(table.getPreferredSize()); table.setAutoCreateRowSorter(true); setRenderers(); // DefaultRowSorter has the sort() method table.getRowSorter().toggleSortOrder(0); frame.add(scrollPane); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } private void setRenderers() { //TableColumnModel m = table.getColumnModel(); //"Integer", "String", "Interger", "Double", "Boolean", "Double", "String", "Boolean", "Date" table.setDefaultRenderer(Date.class, new DateRenderer()); } private Date getJavaDate(String s) { try { SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); Date d = sdf.parse(s); return d; } catch (ParseException ex) { Logger.getLogger(TableBasic.class.getName()).log(Level.SEVERE, null, ex); return null; } } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { TableBasic frame = new TableBasic(); } }); } private class DateRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (!(value instanceof Date)) { return this; } setText(DATE_FORMAT.format((Date) value)); return this; } } } 
+4
source

The table does not know that the column always contains Date instances, and therefore it should be sorted in chronological order if you did not specify this information by overriding the getColumnClass() method of the table model:

 final Class<?>[] columnClasses = new Class<?>[] {Date.class, String.class, Long.class, Boolean.class}; DefaultTableModel model = new DefaultTableModel(...) { @Override public Class<?> getColumnClass(int column) { return columnClasses[column]; } }); JTable table = new JTable(model); 

Extra bonus: numeric and logical columns will be automatically displayed and sorted correctly.

+5
source

Here is the answer using code from JB Nizet

  String[] columnNames = {"Date", "String", "Long", "Boolean"}; Object[][] data = { {getJavaDate("13-11-2020"), "A", new Long(1), Boolean.TRUE }, {getJavaDate("13-11-2018"), "B", new Long(2), Boolean.FALSE}, {getJavaDate("12-11-2015"), "C", new Long(9), Boolean.TRUE }, {getJavaDate("12-11-2015"), "D", new Long(4), Boolean.FALSE} }; final Class<?>[] columnClasses = new Class<?>[] {Date.class, String.class, Long.class, Boolean.class}; DefaultTableModel model = new DefaultTableModel() { @Override public Class<?> getColumnClass(int column) { return columnClasses[column]; } }; model.setDataVector(data, columnNames); final JTable table = new JTable(model); 

This code goes into your constructor, replacing the first few lines in it.

+2
source

Source: https://habr.com/ru/post/1206854/


All Articles