Использование пакета Java Foundation Classes (Swing) для разработки пользовательских приложений на различных платформах

(ознакомительный курс)

Игнатьев А.А.
С.Петербург, 2001

1. Введение.
2. Концепция и основные особенности пакета Swing.

3. Описание и использование основных компонент. 4. Элементы управления форматированной информацией. 5. Обработка реакций элементов управления с помощью специальных классов

6. Работа с графикой. 7. Заключение


1.Введение.

В настоящее время одной из самых передовых технологий в области программирования является Java технология, начало которой было положено компанией Sun Microsystems в июне 1995 г. Кроме того, что Java это мощный современный объектно-ориентированный язык, это еще, главным образом, новая концепция создания программ, позволяющая обеспечивать простой и быстрый перенос программ на различные платформы. Девиз Java "write once - run everywhere" (напиши один раз - выполни где угодно) является главным преимуществом этой технологии.

Как работает Java? Начальным этапом является написание программы на языке высокого уровня (на языке Java). Далее, с помощью компилятора Java создается промежуточный код, или так называемый байт-код (bytecodes) для некой абстрактной виртуальной машины Java (Java Virtual Machine - JVM). Реальная же виртуальная машина устанавливается на той платформе, на которой предполагается выполнение написанной программы. Так, компания Sun совместно с рядом независимых разработчиков создала программную версию JVM для большинства известных платформ: Solaris, Linux, Mac OS, Windows (подробности см. http://java.sun.com). Когда на компьютер загружается файл, содержащий байт-коды (так называемый файл класса - class file), он интерпретируется виртуальной машиной Java на данном компьютере, которая считывает файл класса и выполняет команды, написанные на языке Java. Поскольку ядро виртуальной машины легко переносится с одного типа компьютера на другой, можно ожидать, что для каждого нового типа процессора и для каждой новой операционной системы вскоре появится своя реализация JVM. Поэтому Java-программа сможет работать на любой известной платформе, для которой существует реализация JVM.

Кроме отмеченного главного преимущества Java (переносимость), следует привести еще ряд достоинств этой технологии:

Как известно, за все надо платить, поэтому технология Java имеет также и недостатки. Основным недостатком обычно считают невысокую (по сравнению с машинно-зависимым кодом) скорость работы виртуальной машины. Однако нужно отметить, что этот недостаток за последние годы становится все менее и менее значимым вследствие постоянного усовершенствования виртуальной машины, в которой часто используемые интерпретирующие функции заменяются машинно-зависимыми. Как показали исследования, число таких функций в типовых приложениях часто превышает 50 %. Поэтому такая замена заметно увеличивает скорость работы JVM. Стремительность прогресса вычислительной техники также уменьшает значимость этого недостатка.

А если учесть тот факт, что за последние годы появились программные средства, позволяющие конвертировать байт-код непосредственно в машинно-зависимый, то отмеченный недостаток просто тает на глазах (см., например, http://www.excelsior-usa.com).

Данный курс не претендует на какую-либо полноту по Java и имеет целью лишь познакомить читателя с возможностями пакета (библиотеки) JFC (Java Foundation Classes), известного еще под названием "Swing", позволяющего довольно быстро разрабатывать очень приличные GUI-приложения. При изложении курса предполагается, что читатель знаком с основами языка Java. При написании данного курса были использованы учебные материалы и документация по пакету JFC компании Sun Microsystems(см. http://java.sun.com/docs/books/tutorial/).

Для заинтересованного читателя ниже приведены также некоторые ссылки на литературу по Java на русском языке.

Ниже, в качестве примера Java приложения, использующего Swing пакет, показан два скриншота программы JFilin (графический постпроцессор для визуализации и анализа результатов расчетов гидродинамических течений).


2.Концепция и основные особенности пакета Swing.

JFC (JavaTM Foundation Classes) представляет собой своего рода библиотеку или пакет классов, позволяющих пользователю программировать развитый GUI-интерфейс на современном уровне. Впервые JFC пакет был представлен общественности на "JavaOne developer" конференции в 1997 году и включал в себя следующие возможности:

Swing API доступен в двух вариантах: 1) как центральная часть Java 2 (Standard Edition) (включая версии 1.2 и 1.3) и 2) как отдельный пакет JFC 1.1 (для использования с JDK версии 1.1) Sun рекомендует всегда использовать последнюю версию Java 2 (SDK 1.3). Отметим, что аббревиатуры JDK и SDK являются по смыслу тождественными, поэтому, например, JDK 1.3 и SDK 1.3 обозначают одно и то же.

Swing API мощный, гибкий, но и достаточно объемный. Например, версия 1.1 имеет 15 пакетов: javax.accessibility, javax.swing, javax.swing.border, javax.swing.colorchooser, javax.swing.event, javax.swing.filechooser, javax.swing.plaf, javax.swing.plaf.basic, javax.swing.plaf.metal, javax.swing.plaf.multi, javax.swing.table, javax.swing.text, javax.swing.text.html, javax.swing.tree и javax.swing.undo.

К счастью большинство программ используют лишь небольшую часть всего API. Нужные пакеты подключатся к приложению с помощью оператора import по мере необходимости.

Надо отметить, что в первых версиях Java версий 1.0 и 1.1 (когда Swing еще не было) GUI интерфейс мог быть реализован с помощью базового пакета AWT (Abstact Windowing Toolkit), который не мог удовлетворить всех запросов программистов (в отличие от Swing). Хотя Java 2 продолжает поддерживать этот пакет, но Sun настоятельно рекомендует использовать только Swing. Для облегчения работы программистов названия Swing элементов начинаются с буквы J в отличие от названий в AWT (например, Button в AWT и JButton в Swing).


3. Описание и использование основных компонент.

3.1 Фреймы.

Фрейм, как экземпляр класса JFrame, является полноценным окном или контейнером, в котором происходит строительство всего GUI интерфейса. Фрейм имеет некоторые прибамбасы, такие как рамка, заголовок, кнопки закрытия, раскрытия и сворачивания окна. Все приложения с GUI, как правило, используют по крайней мере один фрейм, но и апплеты могут также использовать фреймы. Для создания зависимого окна, например, какого-нибудь диалога внутри главного фрейма, следует использовать JDialog класс, который имеет того же родителя, что JFrame - класс Window. Ниже показан пример простого фрейма и исходный текст программы для него.

Исходный текст программы:

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

public class FrameDemo {
public static void main(String s[]) {

JFrame frame = new JFrame("FrameDemo");

frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});

frame.setSize(175,100);
frame.setVisible(true);
}
}

В этой небольшой программе (Java-приложении) вначале создается экземпляр класса JFrame. Сам класс JFrame имеет множество методов, как своих собственных, так и унаследованных от своих родительских классов, но здесь мы используем только три из них: методы addWindowListener(), setSize() и setVisible(). Два последних самоочевидны, а вот о первом нужно сказать несколько слов. Начиная с версии JDK 1.1 введена новая идеология организации реакций на действия пользователя (манипуляции мышью и нажатие клавиш). Именно это средство и реализуется с помощью метода addWindowListener(), который сообщает данному фрейму, что ему (фрейму) нужно делать, когда пользователь щелкнет мышью на кнопку закрытия окна (маленький квадратик в правом верхнем углу с буквой "х"). В данном случае просто вызывается метод exit() статического класса System для закрытия окна и прекращения работы программы.

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


3.2 Диалоги.

В Swing имеется несколько классов поддерживающих диалоги. Диалоги - это окна, которые несколько ограничены по функциям по сравнению с фреймами и имеют некоторое специфичное назначение. Для создания самого простого информационного диалога следует использовать статический класс JOptionPane. Класс ProgressMonitor может сформировать диалог, показывающий индикатор полноты выполнения некого процесса. Два других класса JColorChooser и JFileChooser также представляют стандартные часто используемые диалоги, смысл которых ясен из названия и которые более подробно будут описаны ниже. Для диалога печати можно либо использовать метод getPrintJob статического класса Toolkit или Printing API в Java 2. Для создания произвольного диалога используется класс JDialog.

Код простейшего информационного диалога минимален. Ниже показан такой диалог и соответствующий ему исходный текст.

Исходный текст:

JOptionPane.showMessageDialog(frame, "Frame is closing.");

Первый параметр frame определяет родительский фрейм, в котором появляется данный диалог. Ниже показан ряд возможных вариантов использования метода showMessageDialog():

Как и большинство классов, класс JOptionPane имеет еще множество других методов, дающих большую гибкость при программировании, среди которых можно еще отметить метод showOptionDialog(), позволяющий пользователю программировать в диалоге до 3-х кнопок (обычно Yes,No,Cencel) и определять реакцию на них.

3.3 Панели и менеджеры расположения.

Класс JPanel пакета Swing представляет собой в чистом виде контейнер, предназначенный для размещения внутри себя других элементов, в том числе и других панелей. Все, что помещено в панель, можно рассматривать как группу никогда не расстающихся друзей. Если панель переместить или удалить, то та же участь постигнет и всех ее жителей. Панели - очень удобное средство для организации сложных GUI-интерфейсов, содержащих большое количество управляющих элементов, которые можно объединять в функциональные группы и потом размещать в удобном месте приложения.

По умолчанию сами панели визуально никак не проявляют себя на экране, кроме цвета непрозрачного по умолчанию фона (background). Однако к ним можно добавить видимую рамку (с заголовком или без). Класс JPanel имеет метод paint(), который позволяет рисовать в поле панели все, что пожелает пользователь. Панель можно сделать прозрачной, вызвав ее метод setOpaque(false). Для добавления компонентов в панель используется метод add().

С панелями (и другими контейнерами) тесно связано использование специальных классов, так называемых менеджеров расположения (layout managers), которые позволяют автоматически определять местоположение и размеры компонентов внутри панели. Существует несколько типов менеджеров расположения, каждый из которых растягивает (сжимает) и раскидывает добавляемые в панель элементы по определенному правилу. В Java используются следующие типы менеджеров расположения:

В Swing введено еще несколько специальных типов контейнеров, аналогичных JPanel, но предназначенных для узкоспециальных целей.

Ниже показано приложение, использующее класс ScrollPane.

По умолчанию для всякой вновь создаваемой панели устанавливается менеджер FlowLayout, но пользователь может назначить любой другой с помощью метода панели setLayout(). Существуют ситуации, когда использование менеджеров расположения нежелательно, например, когда требуется задать конкретный размер элемента и его конкретное положение внутри панели. Для этого следует применить детерминированный подход и отменить менеджер путем вызова setLayout(null), затем использовать методы setSize() и setLocation() для каждого из добавляемых компонентов. При этом смешивать в рамках одной панели детерминированный подход с использованием менеджеров расположения нельзя, нужно использовать какой-либо один способ.


3.4 Расщепленные окна.

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

Ниже показан пример программы, использующей расщепленное окно. В левой части показан список имен графических файлов, а справа - выбранная картинка.

Исходные тексты этой и другой программ здесь и далее не приводятся, так как они доступны в учебных материалах компании Sun (http://java.sun.com).


3.5 Окна с закладками.

Контейнерный класс JTabbedPane (окно с закладками) может иметь несколько дочерних элементов (обычно панелей), которые занимают одно и тоже пространство на экране. Пользователь выбирает желаемый компонент с помощью закладки. Похожий эффект можно получить и без использования этого класса, например, используя обычную панель с менеджером расположения CardLayout. Но тогда уже придется вручную программировать элементы управления для выбора компонента.

Для создания окна с закладками нужно просто создать экземпляр класса JTabbedPane, создать компоненты, которые пользователь хочет видеть в окне и затем добавить их в окно, используя метод addTab()

Ниже показано приложение, использующее окно с 4-мя закладками.

Закладки могут иметь всплывающие подсказки, а также содержать, как текст, так и значки.


3.6 Панель с управляющими кнопками.

Класс JToolBar (панель с управляющими кнопками) является контейнером, который группирует несколько компонент (обычно кнопки со значками) в строку или столбец. Часто JToolBar обеспечивает легкое и удобное управление интерфейсом аналогично меню. Ниже показано приложение, содержащее панель с управляющими кнопками над текстовым полем.

По умолчанию пользователь может мышью перетаскивать панель с управляющими кнопками в другое место фрейма, например, из положения "север" в положение "восток", как показано на следующем рисунке:

Можно вообще перетащить панель за пределы главного фрейма. В этом случае генерируется новый фрейм (отдельное окно), в котором появляется наша панель:

Если закрыть этот вновь появившийся фрейм, то панель автоматически возвращается в свое начальное положение. Для правильной работы перетаскивания панели с управляющими элементами необходимо, чтобы ее родительский контейнер (в нашем случае главный фрейм) использовал менеджер расположения BorderLayout. Причем важно, что панель при этом не следует помещать в центр, а только по боковым сторонам ("запад", "восток", "север", "юг"). Перетаскивание панели в центр эквивалентно вытаскиванию его за пределы фрейма, т.е. панель появится тогда в новом окне.


3.7 Кнопки.

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

Ниже приведены некоторые примеры кнопок с исходными текстами создания соответствующих экземпляров классов.

Кнопка Вид Код
JButton JButton b1 = new JButton("Top button", leftButtonIcon);
JButton b2 = new JButton("Middle button", middleButtonIcon);
JButton b3 = new JButton("Bottom button", rightButtonIcon);
JCheckBox JCheckBox b1 = new JCheckBox("Dollar");
JCheckBox b2 = new JCheckBox("Ruble");
JCheckBox b2 = new JCheckBox("Yuan");
JCheckBox b2 = new JCheckBox("Euro");
JRadioButton JRadioButton b1 = new JRadioButton("Bird");
JRadioButton b2 = new JRadioButton("Cat");
JRadioButton b3 = new JRadioButton("Dog");
JRadioButton b4 = new JRadioButton("Rabbit");
JRadioButton b5 = new JRadioButton("Pig");

Кнопки меню будут более подробно описаны ниже.


3.8 Раскрывающиеся и простые списки.

Класс JList (простой список) позволяет пользователю объединять в группу ряд элементов, представляемых на экране в виде списка-столбца. Пользователь может выбирать любой элемент с помощью мыши, при этом селектор передвигается на выбранный пункт. Количество пунктов в списке не ограничивается и может быть достаточно велико, поэтому список, как правило, помещают в окно с прокруткой. С помощью метода setSelectionMode() пользователь может назначить для списка режим одиночного или множественного способа выбора пунктов одновременно. Кроме простого списка аналогичные функции (выбор из множества) могут обеспечивать и другие объекты пакета Swing, а именно: JComboBox (раскрывающийся список), JMenu (меню), JTable (таблицы) и группы кнопок JCheckBox или JRadioButton. Причем только простые списки, таблицы и группы кнопок JCheckBox могут обеспечивать множественный выбор элементов одновременно. Ниже показан пример простого списка в окне с прокруткой.

Класс JComboBox (раскрывающийся список) имеется в двух существенно разных видах: редактируемый и нередактируемый. По умолчанию раскрывающийся список нередактируемый. Нередактируемый список внешне похож на простую кнопку, пока пользователь не щелкнет по нему мышью. После щелчка список раскрывается и показывает содержащийся в нем список элементов для выбора. Для решения задачи выбора из множества разработчики Sun рекомендуют использовать именно нередактируемый список когда множество элементов велико, а пространство ограничено, или когда список может меняться в процессе выполнения программы. Ниже показаны примеры нередактируемого раскрывающегося списка в двух состояниях - нераскрытом и раскрытом.

Редактируемый раскрывающийся список похож на текстовое поле с маленькой кнопочкой по соседству. Пользователь может вводить текст в поле или щелкать мышью на кнопочку для выбора пункта из списка. Редактируемый раскрывающийся список может запоминать вводимые данные для обеспечения подсказок для часто вводимых величин. Ниже показаны примеры редактируемого раскрывающегося списка в двух состояниях - нераскрытом и раскрытом.


3.9 Меню.

Как уже было отмечено выше, меню относится к классу кнопок, но в этом разделе меню будет описано более подробно. Меню - очень распространенный, удобный и занимающий очень мало места способ осуществлять процедуру выбора из некоторого множества в GUI-интерфейсах. Меню уникальны в том отношении, что они не размещаются вместе с другими компонентами в пользовательском интерфейсе. Вместо этого меню обычно или встроены в верхнюю часть главного фрейма в виде линейки кнопочек (menu bar) или появляются как всплывающие меню. Всплывающее меню - это меню, которое невидимо до тех пор, пока пользователь не сделает определенное действие мышью, например, пока не щелкнет правой кнопкой мыши или пока не щелкнет по определенному месту интерфейса. Меню при этом сразу появляется под курсором. В пункты меню, кроме текста, можно добавлять значок, подсказку для "горячей" клавиши и разделитель.

В Swing используются следующие классы для создания различных меню:

Класс JMenu имеет метод add() , с помощью которого в него можно добавлять пункты меню JMenuItem . Если в качестве пункта меню добавлен сам класс JMenu , то в этом случае формируется подменю, в которое уже можно добавлять свои пункты. Степень вложения меню не ограничивается. Ниже показаны два примера меню: раскрытой линейки меню (menu bar) и всплывающего меню (popup menu).


3.10 Ползунковый регулятор.

Использование класса JSlider (ползунковый регулятор) дает возможность пользователю вводить численную величину, ограниченную заданными минимальным и максимальным значением. Используя JSlider вместо ввода в текстовое поле, пользователь гарантируется от ошибок. Кроме того, операция передвижения ползунка с помощью мыши осуществляется быстрее, чем набивка руками на клавиатуре. Класс JSlider имеет множество методов, позволяющих пользователю формировать подходящий вид регулятора, включая размеры, шкалу и оцифровку. Ниже показан пример типичного ползункового регулятора.


3.11 Поля текстового ввода.

Поле текстового ввода (класс JTextField ) является основным управляющим элементом, позволяющим пользователю вводить небольшой текст. После ввода текста и указания об окончании ввода (обычно нажатием клавиши Enter) объект класс JTextField формирует событие ввода. Если нужно ввести секретную информацию, например, пароль, то следует использовать другой аналогичный класс JPasswordField , который не показывает вводимые символы на экране. Если пользователь желает использовать типовые подсказки или шаблоны при вводе какой-либо информации, то в этом случае следует использовать раскрывающийся редактируемый список JComboBox .

В случае необходимости ввода более чем одной строчки, следует применить другой более общий класс ввода текстовой информации JTextArea . Этот класс позволяет пользователю отображать и редактировать текст, состоящий из более, чем одной строки. Разработчики рекомендуют использовать этот класс для ввода неформатированной информации любой длины, не содержащий кусков текста с разными фонтами и без встроенных значков и других объектов (нестилевой текст). Хотя JTextArea может использовать любой фонт, но только один и тот же для всего текста.

К полям текстового ввода относится также классы JEditorPane и класс JTextPane , являющиеся стилевыми текстовыми полями. Они позволяют использовать больше, чем один фонт и другие встроенные компоненты (картинки, кнопки и т.д.). Эти стилевые текстовые классы представляют собой мощное, многогранное средство, подходящее для разработки "high-end" программ и предоставляют больше возможностей для дизайна, чем другие текстовые классы. Из-за такой их "крутизны" они, как правило, требуют много усилий при программировании и доводки программных продуктов до "high-end" состояния. Исключение составляет лишь то, что класс JTextPane может быть легко загружен по сети (с определенного URL) с форматированным текстом, что делает его очень полезными для отображения нередактируемой help-информации.

Ниже показан пример приложения, включающего все виды текстовых полей.


3.12 Метки.

Класс JLabel (метка) позволяет пользователю отображать небольшой текст и/или значок (картинку). Текст при этом не может быть выделен мышью. Если необходимо создать компонент, который отображает строчку и/или картинку с более сложными функциями, то следует создать новый класс, расширяющий JLabel , и наделить его данными и методами, которые необходимы. Иногда бывает удобнее просто использовать, какую-нибудь кнопку, которая может также включать в себя текст и картинки. Класс JLabel имеет ряд методов, позволяющих пользователю располагать и выравнивать текст и значок относительно друг друга и относительно границ самой метки. Ниже показано небольшое приложение с тремя метками: с текстом и значком, только с текстом и только со значком. Здесь окно разделено на три горизонтальные полосы равной высоты, в каждую из которых помещена метка, имеющая максимально возможную ширину.

Все содержимое метки по умолчанию имеет вертикальное выравнивание по центру. Но можно задать и другое выравнивание. Так, на приведенном рисунке для верхней метки, содержащей и текст и значок, задано горизонтальное выравнивание по центру. Для второй метки, содержащей только текст, задано выравнивание к левому краю (по умолчанию для меток только с текстом). Для третьей метки, содержащей только значок, задано горизонтальное выравнивание по центру (по умолчанию для меток только со значком).

Замечательным свойством класса JLabel , начиная с версии Swing 1.1.1 Beta 1, является возможность загружать в метку HTML текст. Это значит, что метка может поддерживать форматированный текст, содержащий теги HTML документа. Если текст, загружаемый в метку, начинается с тега <html>, то он воспринимается как HTML, в противном случае как обычный неформатированный текст. Есть, правда, некоторые ограничения. Так, разработчики Sun рекомендуют не использовать тег <br> (новая строка) для корректного определения предпочтительного размера метки, а вместо него использовать тег нового параграфа <p>.

Кроме метки, начиная с версии Swing 1.1.1 Beta 1, HTML можно использовать также и в кнопках. В ближайшем будущем Sun планирует расширить круг компонент, поддерживающих HTML, и включить туда всплывающие подсказки, окна с закладками и пункты меню.

Ниже показано приложение, использующее метку с HTML текстом. В левой части приложения показан текст HTML, загружаемый в метку, а справа сама метка.


3.13 Указатель полноты выполнения процесса.

Некоторые задачи, запускаемые приложением, могут занимать какое-то время. Дружественный интерфейс предоставляет пользователю индикатор, информирующий его о том, какая часть работы уже сделана и сколько еще осталось. В пакете Swing имеется три класса, обеспечивающие подобные функции.

Ниже показано приложение, использующее класс JProgressBar.


3.14 Всплывающая подсказка.

Все классы Swing, наследующие класс JComponent, могут использовать вплывающую подсказку, представляющую собой маленькое окно с некоторым поясняющим текстом, которое появляется всякий раз, когда пользователь удерживает курсор мыши некоторое малое время на данном компоненте. Создать всплывающую подсказку очень легко. Нужно просто использовать метод setToolTipText(String s) с аргументом, содержащим нужный поясняющий текст.

Ниже показано приложение, использующее всплывающую подсказку для кнопки JButton.


4. Элементы управления форматированной информацией.

4.1 Цветовой селектор.

Хорошо известно, что в системах графических пользовательских интерфейсов часто используются различные стандартные диалоги. Пакет Swing не является в этом отношении исключением и также имеет определенный набор таких диалогов. В этом разделе мы познакомимся с первым из них - цветовым селектором, реализованным с помощью класса JColorChooser . Цветовой селектор представляет собой окно с тремя закладками и позволяет пользователю выбрать желаемый цвет либо из фиксированной палитры цветов, либо назначать его в числовом виде в системах HSB и RGB, соответственно. Класс JColorChooser обеспечивает три уровня API:

Ниже показан пример приложения, использующего класс JColorChooser :


4.2 Файловый селектор.

Редкое приложение может обойтись без этого важного диалога. Также и Swing имеет такой диалог, реализуемый с помощью класса JFileChooser . Файловый селектор дает возможность пользователю осуществлять навигацию по файловой системе той платформы, на которой работает приложение. Пользователь может либо выбирать файл или каталог из списка, либо вводить его имя непосредственно в окно ввода. Для запуска файлового селектора пользователь может либо добавить экземпляр класса JFileChooser в контейнер, либо использовать специальное API для отображения модального диалога, содержащего файловый селектор. Файловый селектор обычно отображается внутри именно модального диалога, так как файловые операции чувствительны к изменениям внутри программы

. Отметим несколько важных методов класса JFileChooser .

Ниже показан пример приложения, использующего класс JFileChooser :


4.3 Таблицы.

Таблицы - распространенный способ представления структурированных данных. Реляционные базы данных, например, представляют собой, как известно, таблицы. Swing предоставляет пользователям класс JTable , который дает возможность отображать различные таблицы. Сразу нужно отметить, данный класс не содержит непосредственно в себе данные, а только отображает их. Данные же могут содержаться в массивах, векторах, хеш-таблицах или во внешних источниках, таких как базы данных. Они могут даже генерироваться во время выполнения программы.

Для задания структуры таблицы и ее свойств используется специальные интерфейсы TableModel, TableColumnModel, ListSelectionModel и абстрактный класс AbstractTableModel . Применяя (расширяя) их и создавая экземпляры соответствующих классов, пользователь может задавать желаемые свойства таблицы: количество столбцов, заголовки, типы ячеек (редактируемые или нередактируемые) и т.д. Таблицы могут содержать различные данные: текст, числа, а также булевские переменные (false, true). Если соответствующим образом определить метод getColumnClass() при расширении AbstractTableModel , то все типы данных будут отображаться в более удобном виде. Так, например, булевские переменные будут отображаться не в виде текстовых строчек "false" и "true", а в виде кнопочек JCheckBox , которые, если данные ячейки редактируемые, можно переключать с помощью мыши.

Для корректного представления таблицу обычно добавляют в контейнер с прокруткой ScrollPane . Причем, если этого не сделать, то заголовки столбцов не будут видны. Ширину столбцов пользователь может также изменять с помощью мыши, передвигая разделительную линию между столбцами в заголовке. Технология "drag and drop" действует по отношению к столбцам, поэтому их можно перетаскивать и менять местами.

Ниже показан пример приложения, использующего таблицу.


4.4 Деревья.

Класс Swing JTree предназначен для отображения структурированных данных, иерархически организованных в виде дерева. Так же как и JTable класс дерева JTree не содержит данные непосредственно в себе, а только отображает их. Само дерево состоит из множества узлов, организованных в многоуровневую древовидную структуру. Узел представлен специальным классом DefaultMutableTreeNode . Всегда существует единственный корневой узел (нулевой уровень). Корневой узел может непосредственно порождать дочерние узлы первого уровня. Затем каждый дочерний узел в свою очередь может порождать свои дочерние узлы уже второго уровня, являющиеся внуками по отношению к корню и т.д. Количество уровней не ограничивается. Условно принято называть узлы, которые имеют детей, ветвями (branches), а узлы, не имеющие детей, листьями (leaves). Каждый узел связан с определенными объектом (любого типа), который является аргументом конструктора класса DefaultMutableTreeNode(Object obj) . Множество всех этих объектов для всех узлов и представляет собой, собственно, данные. Ниже показан пример простого дерева.

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

Программно процесс создания дерева очень прост и состоит из следующих шагов:

Когда дерево построено, пользователь может мышью выбрать любой узел. Процесс выбора трактуется как событие и может быть обработано программно. По умолчанию визуальное представление дерева (значки корня, ветвей, листьев и линий их соединяющих) зависит от стиля представления элементов (Look & Feel). Однако пользователь сам может задавать значки этих элементов с помощью специального класса DefaultTreeCellRenderer . Ниже показан пример приложения, использующего дерево.


5. Обработка реакций элементов управления с помощью специальных классов

В предыдущих разделах уже упоминалось вскользь о том, что реакция элементов управления обрабатывается программно специальным образом. Как это делается в Java, описывается более подробно в данном разделе.

Всякий раз, когда пользователь нажимает на клавиши или делает какие-либо манипуляции с мышью, происходит событие. Любой объект может быть оповещен об этом событии. Все что надо сделать для такого оповещения, это наследовать соответствующий интерфейс к объекту и зарегистрироваться как "слушатель события" (event listener). Swing компоненты могут генерировать много видов событий. Вот некоторые из них:

Действие, генерирующее событие Интерфейс "слушателя"
Пользователь нажимает на кнопку, нажимает клавишу Enter после ввода текста или выбирает пункт меню. ActionListener
Пользователь закрывает фрейм (главное окно) WindowListener
Пользователь нажимает кнопки мыши, когда курсор находится поверх объекта. MouseListener
Пользователь движет мышь поверх компонента MouseMotionListener
Компонент становится видимым ComponentListener
Компонент получает фокус ввода от клавиатуры FocusListener
Изменяется выбор в таблице или списке. ListSelectionListener

Каждое событие представляется объектом, который дает информацию об этом событии и идентифицирует источник события. Источники событий - это компоненты, однако и другие виды объектов могут быть источниками событий. Каждый источник события может иметь много зарегистрированных у него "слушателей". И напротив, один "слушатель" может регистрировать много разных событий.

Пусть, например, пользователю необходимо обработать определенное событие (например, нажатие на кнопку) в некотором пользовательском классе MyClass . Для этого необходимо реализовать следующие три шага:

Как альтернативу описанной процедуры (для сокращения кода) можно использовать т.н. адаптеры и внутренние классы. Дело в том, что большинство интерфейсов "слушателей" имеет больше, чем один метод. Например, MouseListener интерфейс содержит пять методов: mousePressed(), mouseReleased(), mouseEntered(), mouseExited(), mouseClicked() . Даже если пользователю необходимо использовать только один метод, он все равно должен определить (пустыми) все остальные. К сожалению, это загромождает программу лишними операторами и делает ее плохо читаемой. Это принципиальное правило языка Java (определение всех функций) для интерфейсов не относится, однако, к классам. Поэтому для устранения отмеченного недостатка в API введены классы-адаптеры для каждого интерфейса "слушателя", имеющих более одного метода. Например, MouseAdapter класс наследует интерфейс MouseListener и определяет все методы пустыми. Теперь вместо наследования интерфейса, пользователь может наследовать его класс-адаптер и переопределить только те методы, которые нужны.

Как известно, в Java запрещено множественное наследование от классов, в отличие от интерфейсов. Что же делать, если пользователь хочет наследовать класс-адаптер и какой-то другой класс одновременно, например, Applet ? Решение этой проблемы состоит в применении внутреннего класса, расширяющего адаптер. Ниже приведен фрагмент кода с внутренним классом:

public class MyClass extends Applet {
...
// Конструктор
MyClass() { addMouseListener(new MyAdapter()); }
...
// Внутренний класс, расширяющий адаптер.
class MyAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
...//Код обработки события.
}
}
}

Можно еще больше сократить код, если использовать анонимное (без имени) определение внутреннего класса следующим образом.

public class MyClass extends Applet {
...
// Конструктор
MyClass()
{
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
...//Код обработки события
}
});
}
...
}


6. Работа с графикой.

6.1 Графика 2D.

Начиная с версии JDK 1.2 компания Sun включила в состав пакета разработчика более мощный графический пакет java.awt.Graphics2D. Это достаточно полный и гибкий набор инструментов для графического вывода, поддерживающий дизайн различных линий, текста, картинок, имеющий более богатый и полнофункциональный интерфейс для пользователя.

В состав API пакета входит:

Основной механизм рисования в java.awt.Graphics2D такой же, как в предыдущих версиях JDK - графическая система управляет тем, когда и что программа должна рисовать. Когда некоторый компонент должен отобразить себя на экране, его метод paint() или update() автоматически вызывается с соответствующим ему контекстом Graphics. В новой версии JDK в API введен новый тип графического контекста - класс Graphics2D, который расширяет класс Graphics, обеспечивая улучшенную графику и свойства рисования.

Использование графики 2D в методах paint() осуществляется теперь следующим образом:

public void paint (Graphics g) {
Graphics2D g2 = (Graphics2D) g;
...
}


6.2 Пространства координат.

Одним из осложняющих моментов при работе с графическими объектами является тот факт, что не все графические устройства имеют одну и ту же систему координат или разрешающую способность. Эта проблема особенно остро ощутима в языке Java, претендующем на девиз "напиши один раз - выполни где угодно". Для поддержки подобной репутации язык Java нуждается в таком способе представления графических объектов, благодаря которому будет обеспечено приемлемое качество изображения независимо от характеристик используемых устройств.

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

В связи с этим обстоятельством в Java 2D поддерживаются два координатных пространства:

Пространство пользователя - это независимая от устройства локальная система координат, используемая программой пользователя. Все геометрические объекты, рисуемые методами Java 2D, определены именно в пространстве пользователя.

Если используется преобразование координат, пространство пользователя - пространство устройства, заданное по умолчанию, то начало координат принимается находящимся в верхнем левом углу области рисования. Координата x возрастает слева направо, а координата y - сверху вниз.

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


6.3 Формы.

Следующие классы пакета java.awt.geom определяют общие графические примитивы (формы), такие как точки, прямые и кривые линии, дуги, прямоугольники и эллипсы:

Кроме классов Point2D и Dimension2D, каждый из этих классов (геометрических форм) наследует интерфейс Shape, в котором объявлена система методов для описания и инспектирования 2D геометрических объектов.

С помощью этих классов пользователь может создавать практически любую геометрическую форму и рисовать ее посредством вызова методов draw() или fill() контекста Graphics2D. Ниже показано приложение, использующее описанные формы.


7.Заключение.

Рамки данного курса, к сожалению, не позволяют рассказать еще много интересного. Автор надеется, что изложенный выше материал поможет многим понять и почувствовать всю красоту технологии Java. Заинтересованному читателю настоятельно рекомендуется почаще посещать официальный сайт компании Sum Microsystems, где нововведения в Java постоянно появляются, как грибы после дождя.
Успехов.