0

我试图让我JTable在表的末尾对空值进行排序。这类似于在 SO(我如何使用空行对 java JTable 进行排序并强制空行始终排在最后?)和 OTN(https://forums.oracle.com/thread/1351003)上找到的线程,但答案这些线程对我来说不是很清楚。

不过,我确实在使用这些答案方面取得了很大进展,而且我得到了下面发布的 SSCCE。但我仍在试图弄清楚如何让空值(或者,在我发布的 SSCCE 中,NullClassFillers)始终排在排序的底部。我觉得如果我可以在自定义中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;
        }

    }
}
4

2 回答 2

0

感谢@MadProgrammer 和@kleopatra,我通过一个后续问题(Java Comparator 总是将值读取为字符串)解决了这个问题。

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

在我看来,这并不值钱,这不是太 hackish 并且确实解决了我的问题,所以我很满意,即使其他人不满意。

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

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

    }
}

在我原来的帖子中,我正在创建一个 custom Comparator,但它无法访问getSortKeys(). 因此,我覆盖了中的getComparator()方法,TableRowSorter以便可以访问getSortKeys(). 有用。

于 2013-09-08T13:25:50.037 回答
0

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

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

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

  1. 排序顺序(升序、降序、无序)

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

    getSortKeys().get(0).getColumn()
    
于 2014-12-10T22:37:31.033 回答