JTable中Date上的排序无效

时间:2014-11-14 07:13:34

标签: java swing sorting date jtable

请查看以下代码

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);
    }
}

现在,尝试使用Date字段对其进行排序。它以无效的方式排序!结果如下!

enter image description here

为什么会这样发生?我甚至使用过cell render

3 个答案:

答案 0 :(得分:6)

该表并不知道该列总是包含Date实例,因此必须按时间顺序排序,除非您通过覆盖表模型的getColumnClass()方法给出该信息:

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);

额外奖励:数字和布尔列将自动呈现并正确排序。

答案 1 :(得分:5)

@Sciper不是一个回答,但我无法抗拒,因为你的代码非常复杂,设计错误,错过了轻量级所需... ...

缺少的关键元素是覆盖TableModel.getColumnClass(),这对于表格排序功能至关重要

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;
        }
    }
}

答案 2 :(得分:2)

以下是使用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);

此代码进入构造函数,替换其中的前几行。