JTable продолжает сортировать числа как строки

Я хочу правильно отсортировать таблицу, сравнивая правильные классы, а не строки. Я использую TableRowSorter:

TableRowSorter sorter = new TableRowSorter<CustomModelTable>(modelData);
tablaEJ.setRowSorter(sorter);

Я переопределил метод getColumnClass в CustomModelTable, чтобы получить правильный класс в зависимости от имени столбца (это было сделано, потому что типы определяются программно):

@Override
    public Class getColumnClass(int columnIndex)
    {
        try {
            if (columnIndex < this.getColumnCount()) {
                String name = getColumnName(columnIndex); //This just gets the header of the column
                name = name.toLowerCase();
                switch (name) {
                    case "int":
                    case "int[]":
                    case "núm.":
                    case "int[][]": return Integer.class; //Or Class.forName("java.lang.Integer");
                    case "byte":
                    case "byte[]":
                    case "byte[][]": return Class.forName("java.lang.Byte");
                    case "long":
                    case "long[]":
                    case "long[][]": return Class.forName("java.lang.Long");
                    case "float":
                    case "float[]":
                    case "float[][]": return Class.forName("java.lang.Float");
                    case "double":
                    case "double[]":
                    case "double[][]": return Class.forName("java.lang.Double");
                    case "boolean":
                    case "boolean[]":
                    case "boolean[][]": return Class.forName("java.lang.Boolean");
                    case "char":
                    case "char[]":
                    case "char[][]": return Class.forName("java.lang.Character");
                    case "string":
                    case "string[]":
                    case "string[][]": return Class.forName("java.lang.String");
                    default: return Class.forName("java.lang.String");
                }
            }
        } catch (Exception e){

        }
        return null;
    }

Вот скриншот: Таблица отсортирована неправильно

Самое любопытное, что я печатаю типы:

for (int i = 0; i < tablaEJ.getModel().getColumnCount(); i++) {
     System.out.println(tablaEJ.getModel().getColumnClass(i));
}

И он возвращает ожидаемый результат (печать приведенной выше таблицы):

class java.lang.Integer
class java.lang.Integer
class java.lang.Integer
class java.lang.Integer

Честно говоря, я не знаю, что я делаю неправильно.


person Ángel Díaz de Vivar    schedule 14.08.2020    source источник
comment
Извините, но ничего, ни заголовка, ни всего поста, говорящего о том, чего вы хотите достичь. Пожалуйста, предоставьте эту информацию.   -  person noname    schedule 14.08.2020


Ответы (2)


Безопасный способ - объявить, какие индексы столбцов являются числами:

public static class CustomTableModel extends DefaultTableModel {
        private final List<Integer> columnIndicesWithNumbers = Arrays.asList(0);

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            if (columnIndicesWithNumbers.contains(columnIndex))
                return Double.class;
            return super.getColumnClass(columnIndex);
        }
    }

Вот полный пример, чтобы проверить себя:

public class SorterTest {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            DefaultTableModel dm = new CustomTableModel();
            dm.addColumn("Integers");
            dm.addColumn("Strings");
            //@formatter:off 
            Object[][] data = { 
                    { 1, "Something" }, { 102, "Something Else" }, 
                    { 55, "Something" }, { 66, "Something" },
                    { 1000, "Something" }, { 1524, "Something" }, 
                    { 5801, "Something" }, { -55, "Something" },};
            //@formatter:on
            for (Object[] row : data) {
                dm.addRow(row);
            }
            JTable table = new JTable(dm);
            table.setAutoCreateRowSorter(true);

            JOptionPane.showMessageDialog(null, new JScrollPane(table));
        });
    }

    public static class CustomTableModel extends DefaultTableModel {
        private final List<Integer> columnIndicesWithNumbers = Arrays.asList(0);

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            if (columnIndicesWithNumbers.contains(columnIndex))
                return Double.class;
            return super.getColumnClass(columnIndex);
        }
    }
}

Предварительный просмотр:

предварительный просмотр

После ваших разъяснений в разделе комментариев:

Вы можете использовать метод @Override getValueAt, чтобы возвращать целые числа вместо строк.

Полный пример:

public class SorterTest {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            DefaultTableModel dm = new CustomTableModel();
            dm.addColumn("Integers");
            dm.addColumn("Strings");
            //@formatter:off 
            Object[][] data = { 
                    { "1", "Something" }, { "102", "Something Else" }, 
                    { "55", "Something" }, { "66", "Something" },
                    { "1000", "Something" }, { "1524", "Something" }, 
                    { "5801", "Something" }, { "-55", "Something" },};
            //@formatter:on
            for (Object[] row : data) {
                dm.addRow(row);
            }
            JTable table = new JTable(dm);
            table.setAutoCreateRowSorter(true);

            JOptionPane.showMessageDialog(null, new JScrollPane(table));
        });
    }

    public static class CustomTableModel extends DefaultTableModel {
        private final List<Integer> columnIndicesWithNumbers = Arrays.asList(0);

        @Override
        public Object getValueAt(int row, int column) {
            Object value = super.getValueAt(row, column);
            if (columnIndicesWithNumbers.contains(column)) {
                return Double.parseDouble(String.valueOf(value));
            }
            return value;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            if (columnIndicesWithNumbers.contains(columnIndex))
                return Double.class;
            return super.getColumnClass(columnIndex);
        }
    }
}
person George Z.    schedule 14.08.2020
comment
В моем коде я устанавливаю данные как строки. Следуя вашему примеру, это будет что-то вроде: Object[][] data = {{ "1", "Something" }, { "102", "Something Else" }}; Возможно ли, что это вызывает проблему? Я действительно не знаю, преобразует ли внутренне Swing все ячейки в строки (в этом случае проблема будет в чем-то другом). Прямо сейчас мой код возвращает правильный класс для каждого столбца, но нужно ли ему, чтобы содержимое ячейки было преобразовано в его класс? Редактировать: я забыл сказать большое спасибо за ваше время!!!! - person Ángel Díaz de Vivar; 14.08.2020
comment
@ÁngelDíazdeVivar Почему бы вам не установить целые числа данных в виде строк? Используйте Integer.parseInt(string) и установите данные как целые числа. - person George Z.; 14.08.2020
comment
Да, это то, что я определенно сделал бы для себя, но это унаследованный код, и он полностью основан на том, что эти данные являются строками. Если нет другого решения, мне придется переписать много кода, поэтому я ищу другое решение. - person Ángel Díaz de Vivar; 14.08.2020
comment
ОМГ я люблю тебя! я попробую это - person Ángel Díaz de Vivar; 14.08.2020

Я думаю, что вы не должны бросать типы, которые делают это. При определении столбцов вы должны создать экземпляр типа столбца, прежде чем что-либо устанавливать.

person Maestro Galletero    schedule 14.08.2020
comment
Спасибо за быстрый ответ!! Но я не уверен, понимаю ли я, что вы говорите ^^' Не могли бы вы уточнить немного больше, пожалуйста? - person Ángel Díaz de Vivar; 14.08.2020