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

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

Текстовые компоненты

515

Создать свой собственный рисующий объект для прорисовки фона за текстом очень просто — интерфейс HighlightPainter предусматривает всего лишь один метод paint(), в который вам передается объект для рисования Graphics и область, в который вы должны прорисовать фон. Используя механизм рисования фона для текстовых компонентов, вы можете создавать весьма удобные для пользователя режимы работы, подсказывая ему с помощью визуальных эффектов что-то, в чем он, скорее всего, в данный момент наиболее заинтересован, или разделяя на экране информацию различной структуры и предназначения.

Резюме

Текстовые компоненты Swing позволят организовать в своем приложении ввод и редактирование текста самыми разными способами: начиная от редактирования простого текста в одну строку и заканчивая составлением и отображением документов в известных форматах RTF и HTML. В данной главе мы разобрали базовые возможности текстовых компонентов Swing, на их основе вы сможете реализовать большую часть требуемых в приложениях операций. Если же вашей целью является мощный текстовый редактор с огромным спектром возможностей, то к вашим услугам пакет javax.swing.text: он содержит все, чтобы ваши фантазии можно было воплотить в жизнь.

С другой стороны, если речь заходит о мощных текстовых возможностях, вы можете начать с платформы NetBeans, основной целью которой является удобное редактирование текста, в том числе и структурированного. Скорее всего, если ваши цели и способности NetBeans совпадут, вы сэкономите на разработке очень много времени — реализация качественных текстовых компонентов требует усилий.

Глава 17. Таблицы

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

Впрочем, за все приходится платить. Это правило действует и в случае с таблицами. Чтобы полностью овладеть всей мощью класса JTable, придется изучить довольно много вспомогательных классов, узнать способы их взаимодействия, понять, как реализованы модели и почему они так реализованы, в каких ситуациях таблица ведет себя определенным образом, и многое другое. Вспомогательным классам таблицы JTable посвящен целый пакет (впечатляющего размера) javax.swing.table. Но пугаться не стоит, создать таблицу с некоторой информацией, полученной из любого источника, довольно просто и не требует особенного напряжения. Как всегда, Swing подстраивается под уровень пользователя: для получения простой таблицы потребуются простые действия, а все более сложные таблицы будут требовать от вас все больше и больше усердия. Начнем с самого простого.

Простые таблицы

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

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

Таблица JTable, как и большинство сложных компонентов библиотеки Swing, реализует интерфейс Scrollable, так что вы смело можете добавлять ее в панель прокрутки JScrollPane, не заботясь о правильности прокрутки. При прокрутке полностью появля-

Таблицы

517

ются следующий столбец или следующая строка таблицы, это удобно и интуитивно понятно пользователю. Интересно, что заголовок таблицы (специального вида надписи с названиями столбцов, реализованных классом JTableHeader) будет виден пользователю только при помещении таблицы в панель прокрутки, потому что таблица размещает компонент JTableHeader в виде заголовка панели прокрутки (как мы отмечали в главе 13, заголовок панели прокрутки хранится в ее свойстве rowHeaderView). Так что если вам нужно увидеть заголовок таблицы, придется включить таблицу в панель прокрутки или вручную разместить около верхней границы таблицы компонент JTableHeader. Чуть позже мы обсудим подробнее заголовок таблицы.

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

//SimpleTables.java

//Простые таблицы с помощью удобных конструкторов import javax.swing.*;

import java.util.*; import java.awt.*;

public class SimpleTables extends JFrame { // данные для таблиц

private Object[][] colors = new String[][] {

{"Красный", "Зеленый", "Синий" },

{"Желтый", "Оранжевый", "Белый" },

}; // названия заголовков столбцов

private Object[] colorsHeader = new String[] { "Цвет", "Еще цвет", "Тоже цвет"

};

public SimpleTables() { super("SimpleTables"); setDefaultCloseOperation(EXIT_ON_CLOSE); // несколько простых таблиц

JTable table1 = new JTable(colors, colorsHeader); JTable table2 = new JTable(5, 5);

//таблица на основе вектора, состоящего из векторов

Vector<Vector<String>> data =

new Vector<Vector<String>>(); Vector<String> row1 = new Vector<String>(); Vector<String> row2 = new Vector<String>();

//вектор с заголовками столбцов

Vector<String> columnNames = new Vector<String>(); // наполнение данными

for (int i=0; i<3; i++) { row1.add("Ячейка 1." + i); row2.add("Ячейка 2." + i);

518

ГЛАВА 17

columnNames.add("Столбец #" + i);

}

data.add(row1);

data.add(row2);

JTable table3 = new JTable(data, columnNames);

//добавляем таблицы в панель с тремя рядами setLayout(new GridLayout(3, 1));

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

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

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

}

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

new Runnable() {

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

}

}

В примере мы наследуем от окна JFrame, указываем, что при закрытии окна нужно будет закончить работу приложения, и размещаем в панели содержимого несколько таблиц JTable, созданных с помощью удобных конструкторов. Первая таблица (table1) создается конструктором, принимающим два массива с данными. Первый массив должен быть двухмерным и хранить строки таблицы с данными некоторого типа. Мы использовали в качестве данных самое простое из всего возможного — строки String. Остается только вспомнить, как записываются в Java двухмерные массивы, довольно редкие гости обычных программ. Вы видите, что данные для первой таблицы (две строки с названиями цветов) описаны в двухмерном массиве colors. Второй передаваемый в конструктор массив одномерный и хранит названия столбцов таблицы, с ним все проще. Вторая таблица (table2) создается с помощью, пожалуй, самого простого конструктора, которому требуется указать лишь количество строк и столбцов в таблице. Все ячейки будут пустыми, а в качестве названий столбцов использованы латинские буквы, как во всех электронных таблицах. Такой конструктор требуется редко, но он может быть полезен там, где с помощью таблиц нужно получать информацию от пользователя или имитировать вид электронной таблицы. Ну и, наконец, третий конструктор работает с вектором (динамическим массивом) Vector из пакета java.util. Ему требуется передать два вектора. Первый должен хранить в себе такие же векторы, в которых, в свою очередь, должны храниться данные строк таблицы. Каждый вектор отвечает за свою строку таблицы. Второй вектор хранит обычные объекты — названия столбцов таблицы. В примере мы наполняем векторы строк и названий столбцов в цикле. Затем векторы строк добавляются в вектор, который будет хранить все данные таблицы (data), после чего таблицу table3 можно создавать.

Созданные три таблицы добавляются в окно, в котором мы установили табличное расположение GridLayout из трех рядов и одного столбца. Как нам известно, табличное расположение выделяет своим ячейкам одинаковое пространство. Последовательное расположение FlowLayout и вообще любое расположение, предоставляющее компонен-

Таблицы

519

там все затребованное ими «предпочтительное» пространство, нам не подойдут, потому что таблицы, помещенные в панель прокрутки JScrollPane, очень требовательны к пространству, даже если в них хранится совсем немного данных. Учитывайте этот факт при создании пользовательского интерфейса и подбирайте такой менеджер расположения, который не позволит таблицам в панели прокрутки «отнять» у контейнера слишком много места. С другой стороны, таблицы без панелей прокрутки занимают ровно столько места, сколько им требуется для отображения своих данных. Заметьте, что мы используем панель прокрутки только для первых двух таблиц, а третью добавляем в панель напрямую. После запуска программы с примером вы увидите, что в такой таблице не отображается заголовок. Для вывода заголовка нужно либо добавить таблицу в панель прокрутки (в заголовке которой и окажется заголовок таблицы), либо ввести его в контейнер вручную. Как работать с заголовками таблиц, мы узнаем немного позже.

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

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