Графические интерфейсы пользователя Java - Тимур Сергеевич Машнин Страница 21
Графические интерфейсы пользователя Java - Тимур Сергеевич Машнин читать онлайн бесплатно
Модель столбца TableColumnModel отвечает за добавление или удаление столбцов, их перестановку, и выделение столбцов.
Отслеживание выделения отдельной ячейки таблицы будет более точным одновременно с помощью модели выбора строки и модели выбора столбца, так как при выделенной строке или столбце вы не отследите выбор других ячеек в той же строке или столбце.
Чтобы отделить данные от таблицы, используется модель данных TableModel.
Модель хранения содержимого ячеек таблицы описана интерфейсом TableModel, который частично реализован абстрактным классом AbstractTableModel и полностью реализован его подклассом DefaultTableModel.
Если программист не предоставляет объект модели таблицы, компонент JTable автоматически создает экземпляр DefaultTableModel.
Поэтому использование модели DefaultTableModel по сути ничем не отличается от использования простых конструкторов класса JTable.
DefaultTableModel – это реализация интерфейса TableModel, которая использует вектор векторов для хранения объектов значений ячейки.
Предположим, мы хотим отобразить в таблице не просто строки, а произвольные объекты, например, экземпляры класса User.
Тогда при использовании простого конструктора или модели DefaultTableModel, мы должны создать массив данных, в котором явно извлекаем из объекта строку как значение ячейки.
Или объект должен быть совсем простым, с одним полем и методом toString, который возвращает значение этого поля.
Чтобы оперировать произвольными объектами, и даже иметь возможность размещать объекты разных типов в разных ячейках таблицы, нам нужно создать свою модель.
Java Reflection API
Давайте немного отвлечемся и рассмотрим такую концепцию, как рефлексия.
Рефлексия – это механизм исследования данных о программе во время её выполнения.
Рефлексия позволяет исследовать информацию о полях, методах и конструкторах классов.
Можно также выполнять операции над полями и методами, которые исследуются.
Рефлексия в Java осуществляется с помощью программного интерфейса Java Reflection API.
Этот интерфейс API состоит из классов пакетов java.lang и java.lang.reflect.
С помощью интерфейса Java Reflection API можно определить класс объекта.
Получить информацию о модификаторах класса, полях, методах, конструкторах и суперклассах.
Выяснить, какие константы и методы принадлежат интерфейсу.
Создать экземпляр класса, имя которого неизвестно до момента выполнения программы.
Получить и установить значение свойства объекта.
Вызвать метод объекта.
Создать новый массив, размер и тип компонентов которого неизвестны до момента выполнения программы.
Итак, для каждого типа объектов, во время выполнения виртуальная машина Java создает экземпляр класса java.lang.Class, который предоставляет методы для исследования свойств объекта, включая его поля и информацию о типе.
Этот класс также предоставляет возможность создавать новые классы и объекты.
Получить объект типа Class можно методом getClass из объекта любого класса.
Если у нас есть экземпляр объекта Class, мы можем получить всевозможную информацию об этом классе и даже осуществлять операции над ним.
Метод getClass часто полезен тогда, когда есть экземпляр объекта, но не известно какого класса этот экземпляр.
После получения объекта Class, мы можем получить имя класса с помощью метода getName.
Объект типа String, возвращаемый методом getName, будет содержать полностью уточненное имя класса, включая пакет, то есть, например, для Integer – это будет java.lang.Integer.
Чтобы узнать, какие модификаторы были применены к классу, сначала нужно с помощью метода getClass получить объект типа Class, представляющий данный класс.
Затем нужно вызвать метод getModifiers для объекта типа Class, чтобы определить значение типа int, биты которого представляют модификаторы класса.
После этого можно использовать статические методы класса java.lang.reflect.Modifier, чтобы определить, какие именно модификаторы были применены к классу.
Метод getTypeParameters позволяет получить дженерик параметры класса.
Метод getGenericInterfaces позволяет получить реализованные интерфейсы класса.
Метод getSuperclass позволяет получить объект суперкласса.
Чтобы исследовать поля, принадлежащие классу, можно воспользоваться методом getFields для объекта типа Class.
Метод getFields возвращает массив объектов типа java.lang.reflect.Field, соответствующих всем публичным полям объекта.
С помощью класса Field можно получить имя поля, тип и модификаторы.
Эти публичные поля необязательно должны содержаться непосредственно внутри класса, они также могут содержатся в суперклассе, интерфейсе или интерфейсе, представляющем собой расширение интерфейса, реализованного классом.
Если вы хотите получить поля без наследования, включая приватные и защищенные поля класса, можно использовать метод getDeclaredFields.
Чтобы получить значение поля, нужно сначала получить для этого поля объект типа Field затем использовать метод get.
Метод принимает входным параметром ссылку на объект класса.
Для установки значения поля, используется метод set.
Чтобы получить информацию о публичных конструкторах класса, нужно вызвать метод getConstructors для объекта Class.
Этот метод возвращает массив объектов типа java.lang.reflect.Constructor.
С помощью объекта Constructor можно затем получить имя конструктора, модификаторы, типы параметров и генерируемые исключения.
Если требуется получить все конструкторы класса, включая закрытые можно использовать метод getDeclaredConstructors.
Чтобы получить информацию о публичных методах класса, нужно вызвать метод getMethods для объекта Class.
Этот метод возвращает массив объектов типа java.lang.reflect.Method.
Затем с помощью объекта Method можно получить имя метода, тип возвращаемого им значения, типы параметров, модификаторы и генерируемые исключения.
Для того чтобы получить все методы класса не зависимо от типа доступа, нужно использовать метод getDeclaredMethods.
Java Reflection Api позволяет динамически вызвать метод, даже если во время компиляции имя этого метода неизвестно.
Если метод имеет модификатор доступа private, тогда для получения доступа к методу нужно вызвать для него метод setAccessible (true).
С помощью метода newInstance объекта Class можно динамически загружать и создавать экземпляры класса.
AbstractTableModel
Вернемся теперь к таблицам.
Как правило, вы реализуете свою модель таблицы как подкласс класса AbstractTableModel.
При этом необходимо определить три метода – getRowCount, getColumnCount, и getValueAt.
Для редактируемой таблицы, дополнительно нужно определить методы isEditable и setValueAt.
В этом примере мы создаем модель таблицы с использованием Java Reflection Api.
Модель принимает в качестве входных данных список объектов.
В методе getColumnCount, который возвращает количество столбцов, мы возвращаем количество столбцов по числу полей класса объектов списка.
В методе getValueAt, мы получаем методы класса объектов списка и вызываем метод get класса, который соответствует нужному столбцу таблицы или по-другому – полю класса.
После создания модели таблицы, мы создаем список объектов класса User, и создаем таблицу на основе модели и этого списка объектов.
При всяком изменении модели или ее содержимого в ней происходит событие класса TableModelEvent.
Это событие имеет три типа – INSERT, DELETE и UPDATE.
Значения этих констант 1, -1 и 0 соответственно.
Тип события получается методом getType.
Событие TableModelEvent позволяет отследить диапазон строк, в которых произошло событие, и столбец.
Для этого есть методы getFirstRow, getLastRow и getColumn.
Если метод getColumn возвращает константу ALL_COLUMNS, это означает, что событие затронуло все столбцы.
Слушатель события TableModelEvent может быть присоединен к модели методом addTableModelListener.
Сочетание констант UPDATE, ALL_COLUMNS и MAX_VALUE в качестве значения метода getLastRow говорит о том, что была изменена вся Модель и Вид должен переписать на экране всю таблицу.
Сочетание констант UPDATE, ALL_COLUMNS
Жалоба
Напишите нам, и мы в срочном порядке примем меры.