сортировка JTable не в реальном времени/не в реальном времени

Когда таблица находится в режиме сортировки (с использованием RowSorter), кажется, что большую часть времени таблица сортируется в реальном времени. Например, всякий раз, когда я добавляю новые строки, таблица сортируется автоматически (кроме ячейки редактирования). Мне интересно, есть ли способ отключить это поведение сортировки в реальном времени.

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

@trashgod: спасибо за ответ. На самом деле мне нравится собственный метод сортировки строк, так как я могу обвести состояние столбца в трех состояниях (по возрастанию, по убыванию и без сортировки). При использовании Collections.sort мне придется создать переменную для сохранения исходного порядка строк, прежде чем сортировать его каждый раз.


person user1429552    schedule 31.05.2012    source источник


Ответы (2)


Вы можете упорядочить строки вашего TableModel независимо от RowSorter, используя Collections.sort() и пользовательский Comparator, например показанный здесь, который может принимать параметр, определяющий направление сортировки.

enum Sort { ASCENDING, DESCENDING; }
class RecordComparator implements Comparator<Record> {
    public RecordComparator(Sort sort, ...) { ... }
}
person trashgod    schedule 31.05.2012
comment
спасибо за Ваш ответ. На самом деле мне нравится собственный метод сортировки строк, так как я могу обвести состояние столбца в трех состояниях (по возрастанию, по убыванию и без сортировки). При использовании Collections.sort мне придется создать переменную для сохранения исходного порядка строк, прежде чем сортировать его каждый раз. - person user1429552; 01.06.2012
comment
Используйте setSortKeys(null), чтобы указать, что представление не должно быть отсортировано; это не зависит от заказа вашей модели. - person trashgod; 01.06.2012
comment
Это то, что я использую, чтобы обвести состояния заказа. Но в режиме по возрастанию и по убыванию (без сортировки все в порядке) перестановка строк будет переопределена сортировщиком. Как я уже упоминал, использование Collection.sort() изменит порядок реальной модели таблицы, поэтому, если я хочу вернуться к исходному порядку, мне в первую очередь понадобится что-то для его хранения. не уверен, что есть лучшее решение для этого. - person user1429552; 01.06.2012
comment
Требование, чтобы новые строки могли добавляться внизу, подразумевает некоторый порядок, который зависит от того, как реализован ваш TableModel. - person trashgod; 01.06.2012

Кажется, что вы хотите иметь возможность сортировать таблицу, но затем иметь возможность добавлять больше строк без изменения порядка сортировки таблицы. Даже если это возможно, вам придется переписать DefaultRowSorter и TableRowSorter (исходный код доступен для обоих). Причина в том, что текущая реализация предназначена для сохранения постоянного порядка сортировки (без учета времени добавления строк). Вы, вероятно, не сможете расширить TableRowSorter, чтобы решить эту проблему, так как его родительский класс имеет множество частных функций, связанных с только что описанным дизайном.

То, что я описал выше, является чистым способом. Вот еще один способ сделать это, делайте это каждый раз, когда хотите вставить новую строку:

  1. Сохраните текущий порядок сортировки представления на карте. Я использовал хэш-карту (postion), чтобы сопоставить каждый объект в строке i столбца сортировки с его позицией в представлении. position.put(tableModel.getValueAt(i, column), sorter.convertRowIndexToView(i));

  2. Создайте компаратор, который будет использовать карту, созданную выше, для сортировки входящих данных. Установите компаратор столбцов TableRowSorter на вновь созданный компаратор. Затем вызовите sorter.sort(), что необходимо, потому что DefaultRowSorter нужно кэшировать компаратор. Компаратор поместит существующие объекты в их текущую позицию и поместит новые объекты (созданные во время вставки) в конец.

  3. Выполните вставку строки в табличную модель. В моем коде я добавляю 3 случайных значения Integer, Boolean и Double к 3 столбцам в моей таблице.

  4. Удалите компаратор, добавленный в #3, установив значение null, sorter.setComparator(sortKeys.get(0).getColumn(), null); Таким образом, при следующем переключении сортировки столбца будет использоваться компаратор по умолчанию вместо фиктивного.

Полный код ниже. Он предназначен для добавления строки в таблицу при каждом нажатии кнопки. Обратите внимание, что я не тестировал это с ключами сортировки> 1 или фильтрами (я оставлю это вам). Дайте мне знать, что вы думаете об этом хаке.

private void insertRowButtonActionPerformed(java.awt.event.ActionEvent evt) {
    TableRowSorter<TableModel> sorter = (TableRowSorter<TableModel>)jTable1.getRowSorter();
    final HashMap<Object, Integer> position = new HashMap<Object, Integer>();
    List<? extends SortKey> sortKeys = sorter.getSortKeys();

    if(!sortKeys.isEmpty()){
        SortKey sortKey = sortKeys.get(0);
        int column = sortKey.getColumn();
        TableModel tableModel = sorter.getModel();
        int n = sorter.getModelRowCount();
        final SortOrder sortOrder = sortKey.getSortOrder();
        for(int i=0;i<n;i++){
            position.put(tableModel.getValueAt(i, column), sorter.convertRowIndexToView(i));
        }
        //add dummy comparator
        sorter.setComparator(column, new Comparator<Object>(){
            public int compare(Object o1, Object o2) {
                int obj1Position = position.containsKey(o1) ? position.get(o1):position.size();
                int obj2Position = position.containsKey(o2) ? position.get(o2):position.size();
                return sortOrder == SortOrder.DESCENDING ? obj2Position - obj1Position:obj1Position - obj2Position;
            }
        });
        sorter.sort();
    }

    /////////////insert row///////////////////
    DefaultTableModel tableModel = (DefaultTableModel)jTable1.getModel();
    tableModel.addRow(new Object[]{rand.nextInt(), rand.nextBoolean(), rand.nextDouble()});
    /////////////end insert row///////////////

    //remove dummy comparator
    if(!sortKeys.isEmpty()){
        sorter.setComparator(sortKeys.get(0).getColumn(), null);
    }
}
person user845279    schedule 01.06.2012