Для сортировки строк таблицы сделано его расширение-класс TableRowSorter TableModel>. Объект этого класса осуществляет связь View и Model таблицы, которую можно записать следующим образом: FileTableModel model = new FileTableModel(); JTable table = new JTable(model); table.setRowSorter(new TableRowSorter(model)); Разумеется, тип элементов столбца, по которому ведется сортировка, должен допускать сравнение элементов по величине, реализовав интерфейс Comparator setComparator(int column, Comparator comparator); того же класса. Если же и это не сделано, то сортируются строки, полученные из элементов столбца их методами toString ( ). В тех случаях, когда надо отсортировать строки сразу по нескольким столбцам, следует задать очередность сортировки столбцов. Для этого создается список типа List, содержащий объекты вложенного класса RowSorter.SortKey. При создании этих объектов указывается номер столбца и порядок его сортировки. Порядок сортировки, прямой или обратный, определяется константой ASCENDING или DESCENDING перечисления SortOrder. Очередность столбцов при сортировке соответствует порядку объектов в списке. Все это вместе выглядит так: List TableRowSorter sorter = new TableRowSorter(model)); sorter.setSortKeys(keys); Как уже говорилось ранее, перестановка строк при сортировке происходит только при выводе их из Model на экран, точнее говоря, во View. Методами int modelRowIndex = table.convertRowIndexToModel(viewRowIndex); int viewRowIndex = table.convertRowIndexToView(modelRowIndex); можно отследить соответствие порядкового номера строки viewRowIndex во View и ее порядкового номера modelRowIndex в Model. Фильтрация строк таблицы Кроме сортировки, класс RowSorter позволяет выбрать строки таблицы из Model по какому-нибудь критерию для вывода их во View. Для этого надо создать фильтр, отбирающий строки — объект абстрактного настраиваемого класса RowFilter TableRowSorter sorter = new TableRowSorter(model)); RowFilter filter = RowFilter.regexFilter(MjavaM, 0); sorter.setRowFilter(filter); В этом примере отбираются строки таблицы, содержащие в нулевом столбце строку символов, в которой встречается подстрока "java". Для создания фильтра в классе RowFilter есть несколько статических методов. Кроме использованного ранее метода public static фильтрующего строки регулярным выражением regex, полезны еще два метода: public static numberFilter(RowFilter.ComparisionType type, Number number, int... indices); public static dateFilter(RowFilter.ComparisionType type, Date date, int... indices); Параметр type этих методов — одна из констант after, before, equal или not_equal вложенного перечисления RowFilter.ComparisionType. Эти константы показывают, что надо передать во View только строки со значением большим, меньшим, равным или не равным значению number или date, служащему вторым параметром методов. Последние параметры indices всех трех методов перечисляют индексы столбцов, значения которых сравниваются со вторым аргументом. Отсутствие параметров indices означает просмотр всех столбцов таблицы. В более сложных случаях, например, когда задан один или несколько диапазонов значений, можно связать несколько фильтров методами public static public static andFilter(Iterable extends RowFilter super M, ? super I >> filters); public static orFilter(Iterable extends RowFilter super M, ? super I >> filters); Первый из этих трех методов, notFilter(), создает фильтр, пропускающий те и только те строки таблицы, которые были бы отвергнуты его аргументом. Второй метод, andFilter (), дает фильтр, пропускающий те и только те строки, которые проходят через все фильтры коллекции filters. Третий метод, orFilter(), пропускает строки, удовлетворяющие хотя бы одному фильтру из коллекции filters. Для более сложной фильтрации строк таблицы нужно расширить класс RowFilter. При этом достаточно переопределить только один метод public boolean include(RowFilter.Entry extends M, ? extends I > row); Объект класса DefaultRowSorter обращается к этому методу при просмотре Model, передавая ему каждую строку таблицы. Метод возвращает true, если строка отвечает фильтру и ее надо передать во View. Параметр этого метода — ссылка на строку таблицы, представленную в виде объекта вложенного настраиваемого класса RowFilter.Entry. Класс RowFilter.Entry предоставляет информацию о строке следующими методами: □ I getIdentifier () — возвращает идентификатор строки в модели; □ m getModel () — возвращает ссылку на модель; □ String getStringValue (int index) — возвращает значение столбца с индексом index в виде строки; □ Object getValue (int index) - возвращает значение столбца с индексом index в виде ссылки; □ int getValueCount () — возвращает количество столбцов в данной строке. Эту информацию можно использовать в методе include (), чтобы принять решение об отборе строки. В следующем примере создан фильтр для отбора тех строк таблицы, у которых в первом столбце записан заданный текст, а сумма числовых значений остальных столбцов больше заданного целого числа class SumRowFilter extends RowFilter{ private String text; private int limit; public SumRowFilter(String text, int limit){ this.text = text; this.limit = limit; } public boolean include(Entry entry){ int sum = 0; if (entry.getStringValue(0).equals(text)){ for (int i = 1; i < entry.getValueCount() — 1; i++){ sum += ((Number)entry.getValue(i)).intValue(); } if ( sum > limit) return true; } return false; } } Печать таблицы Несколько логических методов print () вызывают на экран стандартное диалоговое окно печати, позволяющее выбрать принтер и распечатать содержимое таблицы. Методы возвращают false, если пользователь отменил печать, щелкнув мышью по кнопке Cancel в диалоговом окне, и true в противном случае. □ print (JTable. PrintMode mode) - печать без колонтитулов с выбором сжатия столбцов. Столбцы таблицы при печати будут сжиматься под ширину листа бумаги, если за- □ print(JTable.PrintMode mode, MessageFormat header, MessageFormat footer) — добавляется печать верхнего header и нижнего footer колонтитулов, оформленных как объекты класса MessageFormat из пакета java.text. Вопросы для самопроверки 1. Как конструктивная схема MVC использована для создания классов таблиц? 2. Можно ли хранить в таблицах класса JTable образцы цвета? 3. Можно ли хранить в ячейках таблицы раскрывающиеся списки? 4. Можно ли сделать таблицу с ячейками-кнопками? 5. Можно ли сделать отдельные ячейки таблицы не редактируемыми? 6. Можно ли делать вычисления в таблице класса JTable, как это делается в электронных таблицах? 7. Можно ли сортировать строки таблиц класса JTable? 8. Можно ли сделать электронную таблицу средствами класса JTable? ГЛАВА 14