Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid sorting on Date in JTable

Please have a look at the 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, just try to Sort it using the Date field. It is sorting it in an invalid way! Below is the result!

enter image description here

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

like image 720
PeakGen Avatar asked Nov 14 '14 07:11

PeakGen


People also ask

How do I sort a JTable by a specific column programmatically?

Sorting JTable by a specific column programmatically To sort the table by a column programmatically, we need to create a TableRowSorter and a SortKey that specifies the column index (by which the table is sorted) and sorting order (ascending or descending).

How to use date-time sort in HTML?

Convert the date to the format YYYYMMDD and prepend to the actual value ( DD/MM/YYYY) in the <td>, wrap it in an element, set style display:none; to the elements. Now the date sort will work as a normal sort. The same can be applied to date-time sort. I know this is an old question and answers are old too.

How to order data from DataTable column in Ajax?

To the column you want ordering keep "sType": "date-uk" for example:- "data": "OrderDate", "sType": "date-uk" After the completion of Datatable script in ajax keep the below code Problem source is datetime format. The simpliest way is to add a hidden timestamp before the date in every TD tag of the column, for example:

How do I display the date in a sort order array?

When returning the sort order array, Datatables will send (in the $_POST) a 2 element array that would be equivalent to: Therefore, you may display the date in any format you want; just have your server return the sorting criteria based only upon the sortColumnName.


2 Answers

The table doesn't know that the column always contains Date instances and that it must thus sort chronologically, unless you give it that 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);

Additional bonus: the numeric and boolean columns will then automatically rendered and sorted correctly.

like image 128
JB Nizet Avatar answered Oct 21 '22 08:10

JB Nizet


@ Sniper not an answert, but I can't resist, because your code is very complicated, wrong designed, miss there lighweight required for ...

The key element missing is the override of TableModel.getColumnClass(), this is essential for table sorting to 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;
        }
    }
}
like image 42
mKorbel Avatar answered Oct 21 '22 09:10

mKorbel