Я использую JTable, который отображает несколько сортируемых столбцов. Мне нужно, чтобы все строки, содержащие определенный статус, были заморожены в верхней части списка независимо от того, как пользователь отсортировал остальную часть списка. Например, используя следующий несортированный список: Несортированная таблица
Когда пользователь щелкает заголовок Размер файла, все строки со статусом «Загрузка» должны закрепляться вверху, а затем сортироваться по столбцу Размер файла, как показано здесь: Отсортированная таблица
Это можно решить, просто используя два JTable, но это выглядит некрасиво и создает свои проблемы:
- Изменение размера столбца требует, чтобы какой-то прослушиватель менял размер столбца второй таблицы, когда изменяется размер столбца в первой.
- Для сортировки требуется какой-то прослушиватель для сортировки второй таблицы при сортировке первой.
- Необходимо постоянно перемещать строки данных между таблицами при изменении значения состояния.
Я решил, что этот подход неприемлем, и придумал другой подход: добавить скрытый столбец «Позиция» со значением «1» для любых строк, которые я хочу закрепить вверху, и «2» для всех других статусов и постоянно держать этот столбец отсортированным. в порядке возрастания. Я смог использовать TableRowSorter с несколькими SortKeys для сортировки данных таким образом при начальной загрузке; однако я не могу сохранить сортировку столбца Position до сортировки столбца, выбранного пользователем, поскольку нет механизма для добавления SortKey. Попытка добавить еще один ключ сортировки всегда добавляет его ПОСЛЕ существующих ключей сортировки.
Сначала я попытался добавить 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
Я был в тупике на этом для лучшего парка недели и был бы очень признателен за любую помощь или руководство.
Спасибо, Сид
Field field = DefaultRowSorter.class.getDeclaredField( "sortKeys" );
потерпит неудачу из-за модульной инкапсуляции Java 9+, это всегда был сомнительный взлом, обреченный на окончательную неудачу. Частное состояние является частным по той причине, что будущие версии Java могут свободно изменять частную реализацию в любое время. - person VGR   schedule 08.06.2018