Java JTable фиксирует строки наверх, всегда сортируя фиксированный столбец и позволяя пользователю сортировать любой дополнительный столбец - PullRequest
0 голосов
/ 08 июня 2018

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

Когда пользователь нажимает на заголовок для размера файла, он должен заморозить все строки со статусом «Загрузка» вверх, а затемсортировка по столбцу «Размер файла», как показано здесь: Сортированная таблица

Это можно решить, просто используя две JTables, но это выглядит уродливо и создает свои собственные проблемы:

  1. Для изменения размера столбца требуется некоторый вид слушателя, чтобы изменить размер столбца второй таблицы при изменении размера столбца в первой
  2. Для сортировки требуется некоторый вид слушателя для сортировки второй таблицы, когда первыйсортируется
  3. Необходимо постоянно перемещать строки данных назад и вперед между таблицами при изменении значения статуса

Я решил, что этот подход неприемлем, и придумал другой подход: добавить скрытыйСтолбец позиции, который имеет значение «1» для любых строк, которые я хочу заморозить наверх и «2» для всех других статусов и навсегдасохраняйте этот столбец в порядке возрастания.Мне удалось использовать TableRowSorter с несколькими SortKeys для сортировки данных таким образом при начальной загрузке;Однако я не могу сохранить сортировку столбца Положение до сортировки по выбору пользователя, так как нет механизма для добавления SortKey.Попытка добавить еще один SortKey всегда добавляет его ПОСЛЕ существующих SortKey (s).

Сначала я попытался добавить RowSorterListener в TableRowSorter и заново отсортировать таблицу сначала в столбце Position, а затем в столбце, выбранном пользователем.для события sorterChanged (), но это не сработало, потому что оно создавало бесконечный цикл, потому что событие sorterChanged () срабатывало каждый раз, когда что-либо путалось с порядком сортировки.

Затем я попытался добавить MouseListener в TableHeader исортировка таблицы вручную в зависимости от того, по какому столбцу щелкнул пользователь.Эта половина работала, но в конечном итоге потерпела неудачу, потому что встроенный код сортировщика JTable все еще срабатывает.Поэтому, когда пользователь нажимает на заголовок, он сортирует его один раз с помощью моего кода, а затем сортирует его в обратном направлении с помощью внутреннего кода сортировки JTable.Таким образом, в результате ничего не происходит.Я не мог придумать способ использовать или предотвратить это внутреннее событие, кроме как полностью отключить TableHeader.Однако это было неприемлемо, поскольку оно также отключало возможность изменения размера столбцов, и стрелки направления больше не отображались.

При поиске в Интернете я наткнулся на решение, которое отлично работает (https://stackoverflow.com/a/37721594/6143124)но, в конечном счете, его нельзя использовать, потому что он не будет поддерживаться в будущих версиях Java и печатает предупреждение, подробно описывающее Java 9: ​​

WARNING: An illegal reflective access operation has occurred 
WARNING: Illegal reflective access by pkg.PredefinedRowSorter to field javax.swing.DefaultRowSorter.sortKeys WARNING: Please consider reporting this to the maintainers of pkg.PredefinedRowSorter 
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Я остановился на этом из-за лучшего парка неделии был бы очень признателен за любую помощь или руководство.

Спасибо, Сид

1 Ответ

0 голосов
/ 03 августа 2018

Мне удалось достичь желаемого результата, создав собственный TableRowSorter и переопределив метод toggleSortOrder ().

import java.util.ArrayList;
import java.util.List;

import javax.swing.SortOrder;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class PredefinedTableRowSorter<M extends TableModel> extends TableRowSorter<TableModel>
{
    public PredefinedTableRowSorter (TableModel model)
    {
        super(model);
    }

    @Override
    public void toggleSortOrder (int column)
    {
        List<SortKey> newSortKeys = new ArrayList<>();
        newSortKeys.add(new SortKey(0, SortOrder.ASCENDING));

        SortKey currentKey = getSortKey(column);
        SortOrder sortOrder = SortOrder.ASCENDING;

        if (currentKey != null) {
            sortOrder = currentKey.getSortOrder() == SortOrder.ASCENDING ? SortOrder.DESCENDING : SortOrder.ASCENDING;
        }

        currentKey = new SortKey(column, sortOrder);
        newSortKeys.add(currentKey);

        super.setSortKeys(newSortKeys);

        super.sort();
    }

    private SortKey getSortKey (int column)
    {
        for (SortKey key : super.getSortKeys()) {
            if (key.getColumn() == column) {
                return key;
            }
        }

        return null;
    }
}

В этом решении появилась новая проблема: значок стрелки сортировки появился только в первом отсортированном столбце.Я преодолел это, написав собственный DefaultTableCellRenderer и применив его к заголовкам таблицы по мере необходимости, но он не соответствует внешнему виду системы (Windows 10 обычно показывает стрелки сортировки в верхней середине заголовка, тогда как он помещается послетекст в моем пользовательском рендерере).

...