我如何在 LocalDate 列上使用 RowFilter.dateFilter

How can i use RowFilter.dateFilter on LocalDate columns

这是日期:String date = "01.11.2020";

第 1 列SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyy");

第 2 列DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");

Column1SimpleDateFormat 解析,Column2DateTimeFormatter.

解析
//Column1      Column2
01 Kas 2020   2020-11-01

我有一个 JComboBox,其中包含这样的项目 {"ALL", "LAST 1 WEEK", "LAST 1 MONTH", "LAST 1 YEAR"} 所以当我想查看 LAST 1 WEEK 日期时,我使用这样的代码。

TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(m1);
java.util.List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2);
table.setRowSorter(sorter);

filters.add(RowFilter.dateFilter(ComparisonType.AFTER, date,columnIndex));
RowFilter<Object,Object> serviceFilter = RowFilter.andFilter(filters);
sorter.setRowFilter(serviceFilter);

Column1 配合使用效果很好。但它不会对 Column2 进行排序。我猜它不接受它作为日期。

Column1 是 table 模型中的 Date.Class* 列。 Column2 是 table 模型中的 LocalDate.Class(我尝试同时制作两个 Date.Class 但 Column2 给出错误。).

有什么方法可以在 LocalDate.Class 列上使用 RowFilter.dateFilter

我写了一些代码来更详细地解释它。这是一个 class 例如:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.RowFilter.ComparisonType;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.DefaultComboBoxModel;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;

public class frm1 extends JFrame {

    private JPanel contentPane;
    private JTable table;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    frm1 frame = new frm1();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     * @throws ParseException 
     */
    public frm1() throws ParseException {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 501, 425);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);
        
        DefaultTableModel m1 = new DefaultTableModel() {
            public Class getColumnClass(int column) {
                switch (column) {
                    case 0:
                        return Date.class;
                    case 1:
                        return LocalDate.class;
                    default:
                        return String.class;
                }
            }
            public boolean isCellEditable(int row, int column) {
                return false;
             }
        };
        
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 11, 263, 325);
        contentPane.add(scrollPane);
        
        table = new JTable();
        table.setBounds(329, 256, 1, 1);
        //contentPane.add(table);
        scrollPane.setViewportView(table);
        
        JComboBox cbx_date = new JComboBox();
        cbx_date.setModel(new DefaultComboBoxModel(new String[] {"ALL", "LAST 1 WEEK", "LAST 1 MONTH", "LAST 1 YEAR"}));
        cbx_date.setBounds(283, 53, 163, 31);
        contentPane.add(cbx_date);
        
        JComboBox cbx_localdate = new JComboBox();
        cbx_localdate.setModel(new DefaultComboBoxModel(new String[] {"ALL", "LAST 1 WEEK", "LAST 1 MONTH", "LAST 1 YEAR"}));
        cbx_localdate.setBounds(283, 125, 163, 31);
        contentPane.add(cbx_localdate);
        
        JLabel lblNewLabel = new JLabel("With Date");
        lblNewLabel.setBounds(283, 11, 163, 31);
        contentPane.add(lblNewLabel);
        
        JLabel lblWithLocaldate = new JLabel("With LocalDate");
        lblWithLocaldate.setBounds(283, 95, 163, 31);
        contentPane.add(lblWithLocaldate);
        
        //Columns
        table.setModel(m1);
        Object[] columns = {"Date","Local Date"};
        m1.setColumnIdentifiers(columns);
        
        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(m1);
        java.util.List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2);
        table.setRowSorter(sorter);
        
        //Rows
        SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyy");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
        String[] dates = {"01.08.2020","05.08.2020","20.08.2020","21.08.2020","01.09.2020","15.09.2020","01.10.2020","15.10.2020","01.11.2020","01.08.2019","01.07.2019"};
        Object[] rows = new Object[2];
        for(int i=0;i<dates.length;i++) {
            rows[0]=sdf.parse(dates[i]);
            rows[1]=LocalDate.parse(dates[i],formatter);
            m1.addRow(rows);
        }
        //Date state change event.
        cbx_date.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                filters.clear();
                String selected = cbx_date.getSelectedItem().toString();
                if(!selected.equals("ALL")) {
                    filters.add(RowFilter.dateFilter(ComparisonType.AFTER, datereturn(selected),0));
                    filters.add(RowFilter.dateFilter(ComparisonType.BEFORE,new Date(),0));
                }
                RowFilter<Object,Object> serviceFilter = RowFilter.andFilter(filters);
                sorter.setRowFilter(serviceFilter);
            }
        });
        //LocalDate state change event.
        cbx_localdate.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                filters.clear();
                String selected = cbx_localdate.getSelectedItem().toString();
                if(!selected.equals("ALL")) {
                    filters.add(RowFilter.dateFilter(ComparisonType.AFTER, datereturn(selected),1));
                    filters.add(RowFilter.dateFilter(ComparisonType.BEFORE,new Date(),1));
                }
                RowFilter<Object,Object> serviceFilter = RowFilter.andFilter(filters);
                sorter.setRowFilter(serviceFilter);
            }
        });
    }
    //Returs the date as wanted.
    public static Date datereturn (String selected) {
        if(selected.equals("LAST 1 WEEK")) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DAY_OF_MONTH, -7);
            cal.add(Calendar.DAY_OF_MONTH, -1);// make 1 less date so i can get the EQUALS day.Becouse of ComparisonType.AFTER
            Date old = cal.getTime();
            return old;
        }else if(selected.equals("LAST 1 MONTH")) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.MONTH , -1);
            cal.add(Calendar.DAY_OF_MONTH, -1);
            Date old = cal.getTime();
            return old;
        }else if(selected.equals("LAST 1 YEAR")) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.YEAR , -1);
            cal.add(Calendar.DAY_OF_MONTH, -1);
            Date old = cal.getTime();
            return old;
        }else {
            Calendar cal = Calendar.getInstance();
            Date old = cal.getTime();
            return old;
        }
    }
}

我终于想出了如何为 LocalDate 编写 RowFilter

创建 GUI 时,应使用 Swing layout managers。我使用 FlowLayoutBorderLayoutGridBagLayout 来创建 GUI。当您从一台计算机移动到另一台使用不同显示器或不同操作系统的计算机时,绝对定位很脆弱并且无法正常工作。

此外,将代码分成方法和 classes 也很有帮助。方法或 class 越小,越容易测试。相信我,在让 RowFilter 正常工作之前,我 运行 进行了数百次测试。

这是我创建的 GUI。

请查看所有代码。带有自定义 RowFilter 的代码在 LocalDateItemListener class.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.RowFilter.ComparisonType;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class DatePickerExample implements Runnable {

    private DefaultTableModel model;

    private JFrame frame;

    private JTable table;

    private TableRowSorter<TableModel> sorter;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new DatePickerExample());
    }

    @Override
    public void run() {
        frame = new JFrame("Date Picker Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createTablePanel(), BorderLayout.CENTER);
        frame.add(createControlPanel(), BorderLayout.AFTER_LINE_ENDS);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createControlPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        JPanel innerPanel = new JPanel(new GridBagLayout());
        innerPanel.setBorder(BorderFactory.createEmptyBorder(
                5, 5, 5, 5));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.gridx = 0;
        gbc.gridy = 0;

        JLabel lblNewLabel = new JLabel("With Date");
        innerPanel.add(lblNewLabel, gbc);

        String[] options = { "ALL", "LAST 1 WEEK", "LAST 1 MONTH",
                "LAST 1 YEAR" };

        gbc.gridy++;
        JComboBox<String> cbx_date = new JComboBox<>();
        cbx_date.setModel(
                new DefaultComboBoxModel<String>(options));
        cbx_date.addItemListener(new DateItemListener(sorter));
        innerPanel.add(cbx_date, gbc);

        gbc.gridy++;
        JLabel lblWithLocaldate = new JLabel("With LocalDate");
        innerPanel.add(lblWithLocaldate, gbc);

        gbc.gridy++;
        JComboBox<String> cbx_localdate = new JComboBox<>();
        cbx_localdate.setModel(
                new DefaultComboBoxModel<String>(options));
        cbx_localdate.addItemListener(new LocalDateItemListener(sorter));
        innerPanel.add(cbx_localdate, gbc);

        panel.add(innerPanel);
        return panel;
    }

    private JPanel createTablePanel() {
        JPanel panel = new JPanel(new BorderLayout());

        model = new MyTableModel();

        // Columns
        Object[] columns = { "Date", "Local Date" };
        model.setColumnIdentifiers(columns);

        // Rows
        SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyy");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
                "dd.MM.yyyy");
        String[] dates = { "01.08.2020", "05.08.2020", "20.08.2020",
                "21.08.2020", "01.09.2020", "15.09.2020",
                "01.10.2020", "15.10.2020", "01.11.2020",
                "01.08.2019", "01.07.2019" };
        Object[] rows = new Object[2];
        for (int i = 0; i < dates.length; i++) {
            try {
                rows[0] = sdf.parse(dates[i]);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            rows[1] = LocalDate.parse(dates[i], formatter);
            model.addRow(rows);
        }

        table = new JTable(model);
        sorter = new TableRowSorter<TableModel>(model);
        table.setRowSorter(sorter);

        JScrollPane scrollPane = new JScrollPane(table);
        panel.add(scrollPane, BorderLayout.CENTER);

        return panel;
    }

    public class MyTableModel extends DefaultTableModel {

        private static final long serialVersionUID = 1L;

        @Override
        public Class<?> getColumnClass(int column) {
            switch (column) {
            case 0:
                return Date.class;
            case 1:
                return LocalDate.class;
            default:
                return String.class;
            }
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }

    }

    public class DateItemListener implements ItemListener {

        private List<RowFilter<Object, Object>> filters =
                new ArrayList<RowFilter<Object, Object>>(2);

        private TableRowSorter<TableModel> sorter;

        public DateItemListener(TableRowSorter<TableModel> sorter) {
            this.sorter = sorter;
        }

        @Override
        public void itemStateChanged(ItemEvent event) {
            filters.clear();
            String selected = event.getItem().toString();
            if (!selected.equals("ALL")) {
                filters.add(RowFilter.dateFilter(
                        ComparisonType.AFTER, calculateAfterDate(
                                selected)));
                filters.add(RowFilter.dateFilter(
                        ComparisonType.BEFORE, new Date()));
            }
            RowFilter<Object, Object> serviceFilter =
                    RowFilter.andFilter(filters);
            sorter.setRowFilter(serviceFilter);
        }

        // Returns the date as wanted.
        private Date calculateAfterDate(String selected) {
            Calendar cal = Calendar.getInstance();

            if (selected.equals("LAST 1 WEEK")) {
                cal.add(Calendar.DAY_OF_MONTH, -7);
                // Make 1 less date so I can get the EQUALS day.
                // Because of ComparisonType.AFTER
                cal.add(Calendar.DAY_OF_MONTH, -1);
            } else if (selected.equals("LAST 1 MONTH")) {
                cal.add(Calendar.MONTH, -1);
                cal.add(Calendar.DAY_OF_MONTH, -1);
            } else if (selected.equals("LAST 1 YEAR")) {
                cal.add(Calendar.YEAR, -1);
                cal.add(Calendar.DAY_OF_MONTH, -1);
            }

            return cal.getTime();
        }

    }

    public class LocalDateItemListener implements ItemListener {

        private TableRowSorter<TableModel> sorter;

        public LocalDateItemListener(TableRowSorter<TableModel> sorter) {
            this.sorter = sorter;
        }

        @Override
        public void itemStateChanged(ItemEvent event) {
            String selected = event.getItem().toString();
            LocalDate afterDate = calculateAfterDate(selected);

            sorter.setRowFilter(null);

            RowFilter<TableModel, Integer> localDateFilter =
                    new RowFilter<TableModel, Integer>() {
                @Override
                public boolean include(Entry<? extends TableModel,
                        ? extends Integer> entry) {
                    TableModel model = entry.getModel();
                    LocalDate date = (LocalDate) model.getValueAt(
                            entry.getIdentifier(), 1);
                    return date.isAfter(afterDate) &&
                            date.isBefore(LocalDate.now());
                }
            };

            if (!selected.equals("ALL")) {
                sorter.setRowFilter(localDateFilter);
            }
        }

        private LocalDate calculateAfterDate(String selected) {
            LocalDate date = LocalDate.now();

            if (selected.equals("LAST 1 WEEK")) {
                date = date.plusDays(-7);
                date = date.plusDays(-1);
            } else if (selected.equals("LAST 1 MONTH")) {
                date = date.plusMonths(-1);
                date = date.plusDays(-1);
            } else if (selected.equals("LAST 1 YEAR")) {
                date = date.plusYears(-1);
                date = date.plusDays(-1);
            }

            return date;
        }

    }

}