pbi*_*ble 4 java swing jtable comparator tablerowsorter
嗨,我试图在JTable中只为一个列使用自定义比较器.我用以下代码完成了这个.问题是这样做会破坏Integer的适当排序.
我有一个JTable,列类是:String | 整数| 整数| 布尔| 布尔
我正在使用的比较器就是这些.第一个使用如何拆分字母和数字之间(或数字和字母之间)的字符串?.
//compare strings being aware of numbers embedded in the string
private static Comparator<String> numberAwareCompare = new Comparator<String>() {
public int compare(String s1, String s2) {
String[] s1Parts = s1.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
String[] s2Parts = s2.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
int i = 0;
while(i < s1Parts.length && i < s2Parts.length){
//if parts are the same
if(s1Parts[i].compareTo(s2Parts[i]) == 0){
++i;
}else{
try{
int intS1 = Integer.parseInt(s1Parts[i]);
int intS2 = Integer.parseInt(s2Parts[i]);
//if the parse works
int diff = intS1 - intS2;
if(diff == 0){
++i;
}else{
return diff;
}
}catch(Exception ex){
return s1.compareTo(s2);
}
}//end else
}//end while
//Handle if one string is a prefix of the other.
if(s1.length() < s2.length()){
return -1;
}else if(s1.length() > s2.length()){
return 1;
}else{
return 0;
}
return 0;
}
};
Run Code Online (Sandbox Code Playgroud)
我将TableRowSorter扩展如下:
public class FeatureRowSorter extends TableRowSorter<TableModel>{
public FeatureRowSorter(TableModel tableModel) {
super(tableModel);
//setComparator(0, numberAwareCompare);
//setComparator(1,intCompare);
//setComparator(2,intCompare);
}
@Override
public Comparator<?> getComparator(int column){
if(column == 0){
return numberAwareCompare;
}else{
return super.getComparator(column);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这会导致以下不希望的排序行为:
这可以通过创建整数排序来克服.这是问题所在.我不应该为Integer创建一个排序.如果默认的TableRowSorter知道类是Integer,为什么不能创建它呢?
所以我创建了一个简单的整数排序器,如下所示:
//Integer compare, need this to use the custom TableRowSorter
public static Comparator<Integer> intCompare = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
};
Run Code Online (Sandbox Code Playgroud)
现在我删除上面的getComparator方法,并明确地将比较器添加到正确的列.(上面注释掉的代码).这具有正确的排序行为.
我使用以下代码将行分类器添加到表中.我的模型创建了一个新的自定义行分类器,并将其发送到控制器对象中的视图JTable.
//In the model, FeatureTableModel extends DefaultTableModel,getClass method implemented correctly
public FeatureRowSorter getFeatureRowSorter(){
return new FeatureRowSorter(getFeatureTableModel());
}
Run Code Online (Sandbox Code Playgroud)
然后将分拣机添加到表中,如下所示:
view.getFeatureTable().setRowSorter(model.getFeatureRowSorter());
Run Code Online (Sandbox Code Playgroud)
所以问题是,如何在不必实现整数分拣机的情况下这样做呢?这看起来像是一个黑客,而且我正在实现一个整数比较器的事实看起来很可疑.由于FeatureTableModel的getClass方法正确实现,TableRowSorter知道这些列是Integer.(没关系,其中一个布尔列不是复选框.我正在覆盖该渲染器).
任何建议将不胜感激.
更新:
在阅读了Duncan的回答之后,我发现我没有正确地使用了getClass.我有:
@Override
public Class<?> getColumnClass(int column){
if(column == 4){
return Boolean.class;
}else if(column == 2){
return Integer.class;
}else{
return Object.class;
}
}
Run Code Online (Sandbox Code Playgroud)
我改为:
@Override
public Class<?> getColumnClass(int column){
if(column == 4){
return Boolean.class;
}else if(column == 1 || column == 2){
return Integer.class;
}else{
return Object.class;
}
}
Run Code Online (Sandbox Code Playgroud)
基于快速测试,我通过调用实例setComparator
上的方法实现了预期的结果TableRowSorter
.也就是说,我没有创建自己的扩展类TableRowSorter
.
JTable table = new JTable(model);
TableRowSorter<TableModel> rowSorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(rowSorter);
rowSorter.setComparator(0, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// etc.
}
});
Run Code Online (Sandbox Code Playgroud)
在我的测试中,这种方法对在同一个表中对整数列进行排序的能力没有负面影响.
我很欣赏这不是你遇到问题的原因的解释 ,但是作为一种可能更简单的解决办法,它值得一试.