如何在结尾处对具有空值的jtable进行排序

时间:2013-09-08 04:24:57

标签: java swing sorting jtable tablerowsorter

我试图让我的JTable在表的末尾对空值进行排序。这类似于在SO(How can i sort java JTable with an empty Row and force the Empty row always be last?)和OTN(https://forums.oracle.com/thread/1351003)处找到的线程,但这些线程中的答案对我来说不是很清楚。

尽管如此,我确实在使用这些答案方面取得了很多进展,而且我在下面发布的SSCCE中得到了很多。但我仍然试图弄清楚如何获得空值(或者,在我发布的SSCCE中,NullClassFiller s)总是在排序的底部。我觉得如果我能够在自定义Comparator内以某种方式知道哪个方向被排序(升序或降序),我可以轻松地将其工作。但是Comparator不知道排序方向......

任何?

import java.awt.Component;
import java.util.Comparator;
import javax.swing.DefaultRowSorter;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

public class Test {

    public static void main(String args[]) {
        JFrame frame = new JFrame();
        JTable table = new JTable();
        Object[][] data = new Object[8][3];
        data[0][0] = 6.5d; data[0][1] = "Name1";
        data[1][0] = new NullClassFiller(); data[1][1] = "Name2";
        data[2][0] = 2.6d; data[2][1] = "Name3";
        data[3][0] = 0d; data[3][1] = "Name4";
        data[4][0] = new NullClassFiller(); data[4][1] = "Name5";
        data[5][0] = -4d; data[5][1] = "Name6";
        data[6][0] = 0d; data[6][1] = "Name7";
        data[7][0] = -4.3d; data[7][1] = "Name8";
        table.setModel(new DefaultTableModel(data, new String[]{"One", "Two"}));
        table.setAutoCreateRowSorter(true);
        DefaultRowSorter<?, ?> sorter = (DefaultRowSorter<?, ?>) table.getRowSorter();
        sorter.setComparator(0, new CustomComparator());
        table.getColumnModel().getColumn(0).setCellRenderer(new CustomRenderer());
        JScrollPane pane = new JScrollPane(table);
        frame.add(pane);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setSize(500, 500);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    static class CustomComparator implements Comparator<Object> {
        @Override
        public int compare(Object d1, Object d2) {
            if (d1 instanceof NullClassFiller) {
                return -1;
            } else if (d2 instanceof NullClassFiller) {
                return -1;
            } else {
                return ((Comparable<Object>) d1).compareTo(d2);
            }
        }
    }

    static class NullClassFiller {}

    static class CustomRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            if(value instanceof NullClassFiller)
                renderer.setText("");

            return renderer;
        }

    }
}

2 个答案:

答案 0 :(得分:0)

我通过@MadProgrammer和@kleopatra通过后续问题(Java Comparator always reading values as Strings)解决了这个问题。

答案是创建一个自定义Comparator,可以确定表的排序方式,然后相应地返回正确的值(如果排序为ASCENDING则需要o11返回,反之亦然-1,而o2正好相反。

在我看来,这不值得多,这不是太过于苛刻并且确实解决了我的问题,所以我很满意,即使其他人没有。

以下是我的解决方案的完整代码:

import java.awt.Component;
import java.util.Comparator;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SortOrder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class Test {

    public static void main(String args[]) {
        JFrame frame = new JFrame();
        Object[][] data = new Object[8][3];
        data[0][0] = 6.5d; data[0][1] = "Name1";
        data[1][0] = new NullClassFiller(); data[1][1] = "Name2";
        data[2][0] = 2.6d; data[2][1] = "Name3";
        data[3][0] = 0d; data[3][1] = "Name4";
        data[4][0] = new NullClassFiller(); data[4][1] = "Name5";
        data[5][0] = -4d; data[5][1] = "Name6";
        data[6][0] = 0d; data[6][1] = "Name7";
        data[7][0] = -4.3d; data[7][1] = "Name8";
        JTable table = new JTable();
        table.setModel(new DefaultTableModel(data, new String[]{"One", "Two"}) {
            @Override
            public Class<?> getColumnClass(int column) {
                return column == 0 ? Double.class : String.class;
            }
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        });

        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()) {
            @Override
            public Comparator<?> getComparator(final int column) {
                Comparator c = new Comparator() {
                    @Override
                    public int compare(Object o1, Object o2) {
                        boolean ascending = getSortKeys().get(column).getSortOrder() == SortOrder.ASCENDING;
                        System.out.println(o1.getClass() + " - " + o2.getClass());
                        if (o1 instanceof NullClassFiller) {
                            if(ascending)
                                return 1;
                            else
                                return -1;
                        } else if (o2 instanceof NullClassFiller) {
                            if(ascending)
                                return -1;
                            else
                                return 1;
                        } else {
                            return ((Comparable<Object>) o1).compareTo(o2);
                        }

                    }
                };
                return c;
            }
        };
        table.setRowSorter(sorter);
        table.getColumnModel().getColumn(0).setCellRenderer(new CustomRenderer());
        JScrollPane pane = new JScrollPane(table);
        frame.add(pane);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setSize(500, 500);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    static class NullClassFiller {}

    static class CustomRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            if(value instanceof NullClassFiller)
                renderer.setText("");

            return renderer;
        }

    }
}

在我的原始帖子中,我创建了一个自定义Comparator,但它无法访问getSortKeys()。所以,我覆盖了getComparator()中的TableRowSorter方法,以便我可以访问getSortKeys()。它有效。

答案 1 :(得分:0)

getSortKeys().get()的调用必须使用 0 (即主排序键),而不是

boolean ascending = getSortKeys().get(0).getSortOrder() == SortOrder.ASCENDING;

如果用户点击了例如12或7列,则需要第一个排序键(如果用户在其他列之前单击,则最多将有3个键执行多列排序)。此排序键将具有两个属性:

  1. 排序顺序(ASCENDING,DESCENDING,UNORDERED)

    getSortKeys().get(0).getSortOrder()
    
  2. 列索引(例如12或7)

    getSortKeys().get(0).getColumn()