2

別のスレッドで、整数、文字列、またはその両方で構成される可能性のある JTable 列をソートするためのこのコンパレーター (投稿の下部) を見つけました。それを JTable に適用する方法がわかりません。私のテーブルは、以前は自動作成された行ソーターを使用していました。私はそれをfalseに設定し、現在使用しています:

TableRowSorter<MyTableModel> rowSorter = new TableRowSorter<MyTableModel>();
jtable.setRowSorter(rowSorter);
rowSorter.setComparator(0, c1);

無効な範囲を提供しているというインデックス範囲外の例外が発生します。ただし、私のテーブルには複数の列があります。これはコンパレータを適用する正しい方法ですか? こういうやり方はいけないと思います。

Comparator c1 = new java.util.Comparator() {
    /**
     * Custom compare to sort numbers as numbers.
     * Strings as strings, with numbers ordered before strings.
     * 
     * @param o1
     * @param o2
     * @return
     */
@Override
            public int compare(Object oo1, Object oo2) {
                boolean isFirstNumeric, isSecondNumeric;
                String o1 = oo1.toString(), o2 = oo2.toString();


        isFirstNumeric = o1.matches("\\d+");
        isSecondNumeric = o2.matches("\\d+");

        if (isFirstNumeric) {
            if (isSecondNumeric) {
                return Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
            } else {
                return -1; // numbers always smaller than letters
            }
        } else {
            if (isSecondNumeric) {
                return 1; // numbers always smaller than letters
            } else {
                isFirstNumeric = o1.split("[^0-9]")[0].matches("\\d+");
                isSecondNumeric = o2.split("[^0-9]")[0].matches("\\d+");

                if (isFirstNumeric) {
                    if (isSecondNumeric) {
                        int intCompare = Integer.valueOf(o1.split("[^0-9]")[0]).compareTo(Integer.valueOf(o2.split("[^0-9]")[0]));
                        if (intCompare == 0) {
                            return o1.compareToIgnoreCase(o2);
                        }
                        return intCompare;
                    } else {
                        return -1; // numbers always smaller than letters
                    }
                } else {
                    if (isSecondNumeric) {
                        return 1; // numbers always smaller than letters
                    } else {
                        return o1.compareToIgnoreCase(o2);
                    }
                }
            }
        }
    }
};
4

2 に答える 2

8

RowSorter を手動で設定するときは、モデルとの同期を自分で維持する必要があります。

 TableRowSorter sorter = new TableRowSorter();
 table.setRowSorter(sorter);
 sorter.setModel(table.getModel());
 sorter.setComparator(myComparator);
于 2013-03-01T16:41:04.007 に答える
0

@kleopatra、.csvなどの生のテキストファイルからデータを取得する場合、モデルがない場合があります。したがって、正当な数値が含まれている間はすべての列が文字列であるため、それらの列を文字列ではなく数値としてソートする必要があります (したがって、有名な 1<11<10000<2<200... を避けます)。

この別のスレッドを見つけてくれた user1202394 に感謝します。リンクを教えてもらえますか?

3 つの新しいコード部分を使用して、期待どおりに動作させることができました。

Comparator myComparator = new java.util.Comparator() {
    /**
     * Custom compare to sort numbers as numbers.
     * Strings as strings, with numbers ordered before strings.
     * 
     * @param o1
     * @param o2
     * @return
     */
    @Override
    public int compare(Object oo1, Object oo2) {
        boolean isFirstNumeric, isSecondNumeric;
        String o1 = oo1.toString(), o2 = oo2.toString();

        isFirstNumeric = o1.matches("\\d+");
        isSecondNumeric = o2.matches("\\d+");

        if (isFirstNumeric) {
            if (isSecondNumeric) {
                return Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
            } else {
                return -1; // numbers always smaller than letters
            }
        } else {
            if (isSecondNumeric) {
                return 1; // numbers always smaller than letters
            } else {
                // Those lines throw ArrayIndexOutOfBoundsException
                //                        isFirstNumeric = o1.split("[^0-9]")[0].matches("\\d+");
                //                        isSecondNumeric = o2.split("[^0-9]")[0].matches("\\d+");

                // Trying to parse String to Integer.
                // If there is no Exception then Object is numeric, else it's not.
                try{
                    Integer.parseInt(o1);
                    isFirstNumeric = true;
                }catch(NumberFormatException e){
                    isFirstNumeric = false;
                }
                try{
                    Integer.parseInt(o2);
                    isSecondNumeric = true;
                }catch(NumberFormatException e){
                    isSecondNumeric = false;
                }

                if (isFirstNumeric) {
                    if (isSecondNumeric) {
                        int intCompare = Integer.valueOf(o1.split("[^0-9]")[0]).compareTo(Integer.valueOf(o2.split("[^0-9]")[0]));
                        if (intCompare == 0) {
                            return o1.compareToIgnoreCase(o2);
                        }
                        return intCompare;
                    } else {
                        return -1; // numbers always smaller than letters
                    }
                } else {
                    if (isSecondNumeric) {
                        return 1; // numbers always smaller than letters
                    } else {
                        return o1.compareToIgnoreCase(o2);
                    }
                }
            }
        }
    }
};

TableRowSorter sorter = new TableRowSorter();
table.setRowSorter(sorter);
sorter.setModel(table.getModel());
sorter.setComparator(myComparator);

// Apply Comparator to all columns
for(int i = 0 ; i < table.getColumnCount() ; i++)
    rowSorter.setComparator(i, c1);
于 2013-09-04T21:00:09.650 に答える