Материал: Портянкин И. Swing

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Таблицы

545

же интерфейсом ListSelectionModel) отвечает за выделение столбцов таблицы, но хранится она немного в другом месте: в модели столбцов таблицы TableColumnModel, которую мы недавно изучали. Как вы помните, модель выделения списка позволяет проводить выделение в одном из трех режимов: в режиме выделения одиночных элементов (SINGLE_ SELECTION), в режиме выделения непрерывными интервалами (SINGLE_INTERVAL_ SELECTION), а также в наиболее гибком режиме выделения произвольного набора элементов MULTIPLE_INTERVAL_SELECTION (в случае таблицы элементами для выделения являются строки или столбцы). Таким образом, для строк и для столбцов имеется по три режима выделения, так что всего таблица предоставляет нам девять комбинаций — впечатляющая гибкость, способная удовлетворить даже самым взыскательным нуждам.

Нетрудно догадаться, что по умолчанию в таблице и для строк, и для столбцов используется стандартная реализация интерфейса ListSelectionModel — класс DefaultListSelectionModel. Когда мы обсуждали выделение в списках, то пришли к выводу, что чаще всего писать собственную модель выделения нет особого смысла, стандартная реализация прекрасно подходит в подавляющем большинстве ситуаций. Она поддерживает списки слушателей ListSelectionListener, которые оповещаются об изменениях в выделенных строках и столбцах таблицы, и все три режима выделения. Только при реализации нетривиального поведения таблицы вам может понадобиться создание собственной модели выделения (как правило, путем наследования ее от класса DefaultListSelectionModel, как это делается, рассказано в главе 11).

Разберем теперь небольшой пример, в котором взглянем на некоторые способы управления выделением строк и столбцов в таблице JTable:

//TableSelection.java

//Режимы выделения ячеек таблицы import javax.swing.*;

import javax.swing.table.*; import java.awt.*;

public class TableSelection extends JFrame {

//названия столбцов таблицы private String[] columnNames = {

"Название", "Вкус", "Цвет"

};

//данные для таблицы

private String[][] data = {

{"Апельсин", "Кисло-сладкий", "Оранжевый"},

{"Арбуз", "Сладкий", "Темно-зеленый"},

{"Лимон", "Кислый", "Желтый"}

};

public TableSelection() { super("TableSelection"); setDefaultCloseOperation(EXIT_ON_CLOSE);

//создаем пару таблиц с одинаковыми данными

//первая таблица — выделение по строкам

JTable table1 = new JTable(data, columnNames); table1.getSelectionModel().setSelectionMode(

ListSelectionModel.SINGLE_INTERVAL_SELECTION);

546

ГЛАВА 17

//вторая таблица — выделение по столбцам

JTable table2 = new JTable(data, columnNames); table2.setRowSelectionAllowed(false); TableColumnModel cm = table2.getColumnModel(); cm.setColumnSelectionAllowed(true); cm.getSelectionModel().setSelectionMode(

ListSelectionModel.SINGLE_SELECTION);

//добавляем таблицы и выводим окно на экран setLayout(new GridLayout(1, 2));

add(new JScrollPane(table1)); add(new JScrollPane(table2)); pack();

setVisible(true);

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new TableSelection(); } });

}

}

Здесь мы создаем две таблицы с одинаковыми данными, но с разными режимами выделения. Первая таблица будет разрешать выделение только по строкам (это поведение по умолчанию, столбцы таблицы не выделяются, пока вы явно не укажете, что вам это необходимо). Строки таблицы будут выделяться непрерывными интервалами, посмотрите, как выбирается этот режим: сначала мы получаем модель выделения строк методом getSelectionModel() класса JTable, а затем меняем режим работы полученной модели методом setSelectionMode(). Во второй таблице работает выделение по столбцам. Чтобы добиться этого, понадобилось несколько шагов: сначала мы отключили выделение по строкам с помощью свойства rowSelectionAllowed класса JTable, затем получили модель столбцов таблицы TableColumnModel, именно она отвечает за выделение столбцов, и с ее помощью настроили нужное нам поведение. Свойство columnSelectionAllowed позволяет включить выделение столбцов, а модель выделения столбцов, возвращаемая все тем же методом getSelectionModel(), определенным на этот раз в классе TableColumnModel, позволяет выбрать для столбцов любой из трех режимов выделения (в примере мы выбираем режим выделения одного столбца). Напоследок в окно добавляются обе таблицы. Запустив программу и выделяя строки первой таблицы и столбцы второй, вы увидите, как подействовали на таблицу сделанные нами изменения.

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

Таблицы

547

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

Таблица 17.7. Основные методы и свойства для работы с выделением в таблице

Методы или свойства

Описание

selectionModel (класс JTable и модель

Данное свойство хранит модель выделения, в классе

TableColumnModel)

JTable — это модель выделения строк, в модели столб-

 

цов TableColumnModel — модель выделения столбцов.

 

По умолчанию используется стандартная реализация

 

DefaultListSelectionModel

rowSelectionAllowed (JTable), columnSelectionAllowed (модель TableColumnModel и класс JTable)

Первое свойство позволяет включить или отключить выделение строк (определено только в классе JTable), второе включает или отключает выделение столбцов (имеется и в модели выделения столбцов и в классе JTable). По

умолчанию выделение по столбцам отключено

selectionMode (свойство моделей

Данное свойство позволяет задать режим выделения,

выделения и таблицы JTable)

используемый моделью выделения строк или столбцов.

 

Свойство с тем же названием, определенное в классе

 

JTable, задает одинаковый режим выделения сразу для

 

обеих моделей

selectAll(), clearSelection()

Методы класса JTable, первый из них позволяет «одним

(класс JTable)

махом» выбрать все ячейки таблицы, второй дает возмож-

 

ность быстро снять все имеющееся на данный момент вы-

 

деление

cellSelectionAllowed (класс JTable)

Удобное свойство класса JTable, если вы приравняете его

 

значению true, то пользователь сможет выделять отдель-

 

ные ячейки таблицы (тот же эффект получается, когда

 

разрешено выделение и по строкам, и по столбцам)

rowSelectionInterval, columnSelection-

Весьма полезные свойства таблицы JTable, задают выде-

Interval, (методы add, set и remove,

ленные строки или столбцы (четыре метода для установ-

класс JTable)

ки новых значений). Методы, начинающиеся с префикса

 

«add», присоединяют к уже имеющемуся выделению но-

 

вые строки и столбцы, методы с префиксом «set» заме-

 

няют имеющееся выделение новым, методы с префиксом

 

«remove» удаляют из выделения указанные строки или

 

столбцы

Теперь, когда мы умеем управлять режимами выделения таблицы и настраивать выделенные ячейки, неплохо посмотреть на все с другой стороны и узнать, как таблица

548

ГЛАВА 17

и ее модели выделения позволяют узнавать, какие строки и столбцы выделяет пользователь. В табл. 17.8 собраны воедино основные методы, служащие этой цели.

Таблица 17.8. Методы для получения информации о выделенных ячейках

Методы

Описание

isSelectedIndex() (метод

Метод позволяет узнать, выделен ли элемент на некоторой позиции.

модели выделения)

Именно данным методом модели выделения пользуются все осталь-

 

ные, более удобные в работе, методы

isRowSelected(),

Методы класса JTable, позволяющие быстро узнать, выделена ли

isColumnSelected(),

строка (или столбец) с некоторым индексом. Третий метод дает воз-

isCellSelected()

можность определить, выделена ли ячейка, заданная строкой или

 

столбцом

getSelectedRows(),

Также методы класса JTable, позволяющие получить массивы индек-

getSelectedColumns()

сов выделенных на данный момент строк и столбцов

Модели выделения и изученные нами методы и свойства таблицы JTable позволяют полностью управлять работой механизмов выделения ячеек таблицы и получать исчерпывающую информацию о выделенных элементах таблицы. Не забывайте только, что модели выделения строк и столбцов действуют независимо друг от друга, как бы это не выглядело на экране. К примеру, если в вашей таблице действует режим выделения строк, и вы щелкаете на некоторой ячейке, выделяется вся строка, которой принадлежит выделенная ячейка, то есть все ячейки в данной строке выглядят как выделенные. Однако выделенными будут считаться только та строка и тот столбец, которым принадлежит ячейка, на которой вы щелкнули. Работу с выделением лучше всего проводить посредством моделей, и только изредка прибегать к методам класса JTable. Это сделает код более элегантным, упростит его поддержку и развитие, а модели вы при случае сможете разделить между видами, во многом сократив объем требуемой работы.

Сортировка и фильтрация

Таблица JTable позволяет не только отображать те данные, которые вы ей предоставляете посредством модели TableModel, но и обладает встроенными функциями их сортировки и фильтрации с минимальными усилиями с вашей стороны. Учитывая, что табличные данные очень часты в приложениях и, как правило, требуют сортировки (особенно если их много и их не охватить взглядом), наличие такой встроенной возможности, позволяющей не беспокоиться об этом в своей модели данных, приходится очень кстати.

Создатели Swing подошли к проблеме сортировки данных со всей возможной серьезностью. В пакет javax.swing был добавлен абстрактный класс RowSorter, способный проводить сортировку строк в любой модели, коль скоро она способна предоставить свои данные в виде строк и дает узнать общее количество этих строк. В принципе, данный класс можно было бы встроить во все компоненты библиотеки Swing, предоставляющие свои данные в виде строк, хотя бы в хорошо известные нам списки JList, однако на данный момент поддержка класса RowSorter имеется только в таблицах. Как и всегда в Swing, библиотека любезно предоставляет некую реализацию по умолчанию класса RowSorter под названием DefaultRowSorter. Однако, несмотря на название класса, он все еще абстрактный, так как все еще не знает точный тип модели, данные которой надо сортировать. Ну а конкретный класс для сортировки таблиц называется TableRowSorter.

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

Таблицы

549

//SimpleSorting.java

//Сортировка таблицы по умолчанию import javax.swing.*;

import javax.swing.table.DefaultTableModel; import java.awt.*;

public class SimpleSorting extends JFrame { public SimpleSorting() {

super("SimpleSorting"); setDefaultCloseOperation(EXIT_ON_CLOSE);

// создаем таблицу на основе модели по умолчанию

SortModel sm = new SortModel(); sm.setColumnCount(4);

//добавляем сто строк случайных чисел for ( int i = 0; i < 100; i++ ) {

sm.addRow(new Integer[] { i, (int)(5*Math.random()), (int)(5*Math.random()), (int)(5*Math.random())} );

}

JTable table = new JTable();

//автоматическое включение сортировки table.setAutoCreateRowSorter(true);

//ограничение по количеству столбцов

((TableRowSorter)table.getRowSorter()).setMaxSortKeys(2); table.setModel(sm);

add(new JScrollPane(table));

//выводим окно на экран

setSize(400, 300); setVisible(true);

}

// модель для демонстрации сортировки и фильтрации static class SortModel extends DefaultTableModel {

// тип данных, хранимых в столбце

public Class getColumnClass(int column) { return Integer.class;

}

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

Источник: https://studfile.net/preview/15935977/