我试图让我的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;
}
}
}
答案 0 :(得分:0)
我通过@MadProgrammer和@kleopatra通过后续问题(Java Comparator always reading values as Strings)解决了这个问题。
答案是创建一个自定义Comparator
,可以确定表的排序方式,然后相应地返回正确的值(如果排序为ASCENDING
则需要o1
从1
返回,反之亦然-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个键执行多列排序)。此排序键将具有两个属性:
排序顺序(ASCENDING,DESCENDING,UNORDERED)
getSortKeys().get(0).getSortOrder()
列索引(例如12或7)
getSortKeys().get(0).getColumn()