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

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

Основные концепции

5

Итак, мы плавно подошли к самой библиотеке Swing. Уже понятно, что компоненты этой библиотеки, будучи основаны на AWT, являются легковесными. Давайте обсудим столпы Swing немного поподробнее.

Компоненты Swing — это легковесные компоненты AWT

Как вы уже поняли, создатели новой библиотеки пользовательского интерфейса Swing не стали «изобретать велосипед» и в качестве основы для своей библиотеки выбрали AWT. Хоть порка AWT и стала очень популярным занятием с момента выхода самой первой версии Java (и не безосновательно), определенные достоинства у этой библиотеки все же были. Вспомогательная иерархия помощников позволяла без особых усилий переносить AWT практически на любую платформу, а это весьма достойное качество.

Конечно, речь не шла об использовании конкретных тяжеловесных компонентов AWT (представленных классами Button, Label и им подобными). Они уже достаточно скомпрометировали себя близкой связью с операционной системой, которая не позволяла Java-приложениям и библиотекам в полной мере управлять этими компонентами. Нужную степень гибкости и управляемости обеспечивали только легковесные компоненты.

Коротко обсудив библиотеку AWT, мы с вами выяснили, что же такое легковесные компоненты и чем они хороши. Создать легковесный компонент в AWT можно двумя способами: унаследовать класс своего компонента от абстрактного класса Component (и получить обычный легковесный компонент) или унаследовать свой компонент от уже существующего наследника класса Component, другого абстрактного класса Container (и получить контейнер, тоже легковесный). По диаграмме наследования, представленной на рис. 1.2, видно, какой путь избрали создатели Swing.

Component

java.awt

Container

javax.swing

JComponent

Компоненты Swing

Рис. 1.2. Диаграмма наследования компонентов библиотеки Swing

Легко видеть, что библиотека Swing обзавелась новым базовым классом, который стал называться JComponent и который был унаследован от абстрактного класса Container, определяющего поведение контейнеров AWT. Таким образом, все знания разработчиков о компонентах и контейнерах AWT автоматически переходили в Swing, что значи-

6

ГЛАВА 1

тельно облегчало знакомство с новой библиотекой, особенно для тех разработчиков, которые уже пытались создавать Java-приложения с помощью старых библиотек. Создатели Swing постарались максимально облегчить переход от AWT к новой библиотеке, практически полностью сохранив в ней имена классов AWT и их методов. Все компоненты AWT имеют своих наследников в Swing, и имена классов этих компонентов отличаются лишь префиксом «J» (например, тяжеловесная кнопка Button имеет в Swing свой легковесный аналог — кнопку JButton). Новые классы Swing также имели полный набор методов старых классов AWT5, что делало процесс перехода с AWT на Swing простым и безболезненным (достаточно было импортировать пакет javax.swing и добавить к именам классов букву «J»). Все это обусловило молниеносное распространение новой библиотеки и еще сильнее подогрело интерес к ней.

После знакомства с иерархией классов AWT может показаться странным, что в иерархии Swing класс JComponent унаследован непосредственно от базового класса контейнеров Container. Почему разработчики Swing не создали два разных подкласса: один для обычных компонентов, с названием JComponent, и второй для контейнеров, с названием JContainer? Возможно, так было бы проще понимать разницу между ними, к тому же это позволило бы сократить число ненужных методов в обычных компонентах и предотвратить ошибки, связанные с добавлением компонентов туда, куда ничего не следует добавлять (например, в надпись или флажок). Как оказывается, ответ на этот вопрос, как и на многие другие вопросы в Swing, во многом кроется в принципе работы легковесных компонентов.

Как вы помните, легковесный компонент — это просто область в пространстве окна вашего Java-приложения, полностью находящаяся в вашей власти и не воспринимаемая операционной системой как нечто самостоятельное (это верно и для простых компонентов, и для легковесных контейнеров). Помимо тех преимуществ, что мы уже обсуждали (прозрачность, быстродействие, переносимость), это к тому же означает, что все легковесные компоненты, какими бы сложными они ни были, в любом случае не смогут «сбежать» с пространства, занимаемого окном вашего приложения. А это дает возможность заранее подготовить и оптимизировать их вывод на экран (прорисовать их во внеэкранном буфере, проверить, какие из компонентов видны на экране, какие из них «повреждены»6, и только потом обновить нужную область на экране). Подобный процесс (двойная буферизация) одинаков как для компонентов, так и для контейнеров, поэтому естественно было включить его в какой-то один базовый класс.

Нетрудно догадаться, что описанная работа выполняется в базовом классе JComponent, и то, что он представляет собой одновременно и компоненты, и контейнеры Swing, оказывается на самом деле очень удобным (не приходится «раскидывать» один и тот же код по двум классам и координировать их действия). Эффективная прорисовка компонентов Swing на экране — одна из самых важных обязанностей класса JComponent, и выполняет он ее очень качественно. Включив в базовый класс Swing двойную буферизацию, разработчики библиотеки избавили эту библиотеку от проблем, связанных с мерцанием и медленной скоростью вывода на экран.

Помимо того что базовый класс JComponent обеспечивает механизм эффективной прорисовки компонентов на экране, он обеспечивает поддержку наиболее важных свойств Swing, характерных для всех компонентов этой библиотеки. В класс JComponent

5 Конечно, компоненты Swing не ограничивались набором методов из AWT — они имели просто гигантские возможности и соответственно в несколько раз больше методов. Названия методов AWT были сохранены для облегчения перехода с AWT на Swing, но вот перейти со Swing на AWT практически невозможно (слишком велики возможности Swing по сравнению с минималистским прикладным программным интерфейсом библиотеки AWT, да и компонентов в Swing гораздо больше).

6 Поврежденная область (damaged area) — это термин компьютерной графики, обозначающий область экрана, нуждающуюся в обновлении. Аналогом может быть dirty area — загрязненная область.

Основные концепции

7

встроена поддержка всплывающих подсказок (tool tips), рамок (borders), средств для пользователей с ограниченными возможностями (accessibility), клавиатурных действий (keyboard actions) и многого другого. Все это мы подробно обсудим немного позднее в соответствующих главах.

Таким образом, можно смело сказать, что класс JComponent является настоящим ядром библиотеки Swing, и львиная доля возможностей последней обеспечивается этим классом, который можно назвать настоящей «рабочей лошадкой» библиотеки. При создании обычных приложений вам вряд ли придется глубоко вникать в механизмы работы этого класса, однако чтобы «выжать» из своего приложения максимум возможностей, необходимо выяснить, что происходит за кулисами библиотеки. В главе 5 мы подробно исследуем внутреннюю работу этого базового класса Swing (пожалуй, самого важного класса библиотеки).

Не все компоненты Swing унаследованы от класса JComponent. Когда мы обсуждали легковесные компоненты, то выяснили, что должен иметься тяжеловесный контейнер, который будет отвечать за прорисовку всех содержащихся в нем легковесных компонентов. В AWT такими контейнерами чаще всего служили окна Frame и Dialog, а также класс апплетов Applet. Можно пытаться добавлять компоненты Swing в эти контейнеры, однако работать все будет не очень хорошо (особенно это касается меню Swing, которые представляют собой обычные компоненты, и места в контейнерах AWT для них не предусмотрено). Поэтому Swing предоставляет свои, слегка измененные тяжеловесные контейнеры высшего уровня: окна JWindow, JDialog и JFrame, а также апплет JApplet. Перечисленные классы имеют всю необходимую поддержку для компонентов Swing, которую обеспечивает так называемая корневая панель (root pane) — особый контейнер Swing (мы подробно обсудим его в главе 6).

Подводя предварительный итог, мы можем сказать, что, хотя Swing и основана на AWT, разница между двумя этими библиотеками велика. Возможности Swing гораздо обширней возможностей AWT, и поначалу с трудом верится в то, что первая появилась в результате доработки второй. Единственная их связь — базовые классы Component

иContainer, позволяющие Swing абстрагироваться от связей с операционной системой

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

илишь в особых случаях обращаться к AWT.

Совместное использование компонентов AWT и Swing

Начиная с выпуска Java 2, стандартными библиотеками языка Java являются как библиотека AWT (которая считается устаревшей), так и основанная на ней библиотека Swing. Поэтому никаких препятствий для совместного использования графических компонентов этих двух библиотек нет. Вы можете спокойно добавлять компоненты AWT и Swing в свой контейнер, потому что в основе их (как и в основе любой библиотеки пользовательского интерфейса, даже от стороннего производителя) лежат базовые классы Component и Container. Вопрос в том, будет ли подобная конструкция правильно работать.

Долгое время компоненты AWT и Swing не могли находиться вместе в одном контейнере, если их области перекрывались. Особенно болезненно это было для многодокументных интерфейсов (Multi-Document Interface, MDI) Swing и вспомогательных компонентов, таких как панели прокрутки. Страдали и легковесные всплывающие меню. Проблема состояла в том, что легковесные компоненты ни при каких обстоятельствах не могли находиться на экране выше тяжеловесных, даже если это было явно указано.

8

ГЛАВА 1

Только в версии JDK 1.6 (малой версии 10) и во всех последующих версиях, конечно включая Java 7, проблема была решена, и тяжеловесные компоненты теперь могут находиться «под» легковесными. Надеемся, что вам не придется использовать старые выпуски JDK по причинам совместимости, в противном случае лучше всего избегать совместного использования легковесных и тяжеловесных компонентов (Swing позволяет создать любой интерфейс, не прибегая к AWT). Если вы работаете со старой версией и совместить компоненты все же необходимо, следует следить за тем, чтобы они не размещались в легковесных контейнерах (типа панели прокрутки JScrollPane или внутреннего окна JInternalFrame) и не перекрывали легковесные меню. Но при малейшей возможности следует обновить версию JDK, и все проблемы решатся сами собой.

Архитектура JavaBeans

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

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

внем служат классы и объекты. В данный момент компонентное программирование выходит на новый уровень: такие технологии как SOAP (Simple Object Access Protocol), UDDI (Universal Description, Discovery, and Integration) и WSDL (Web Services Description Language) позволяют создавать компоненты (веб-службы) в глобальном масштабе (получить доступ к ним можно будет из любой точки, имеющей выход в Интернет).

Мы говорим о создании пользовательского интерфейса, где компоненты чаще всего представляют собой разнообразные элементы этого интерфейса (кнопки, списки и т. п.). Так как компоненты эти графические, ими удобно манипулировать визуально, так чтобы постоянно наблюдать, что получается в результате. Первопроходцем визуального программирования пользовательских интерфейсов стал язык Visual Basic (VB). Программирование для Windows никогда не было «приятной прогулкой», но с введением в VB графических компонентов и возможности визуально располагать эти компоненты на форме все изменилось. Разработка графических приложений стала требовать гораздо меньше времени и усилий, и визуальное программирование мгновенно вознеслось на вершину популярности. Проблемой VB было то, что компоненты представляли собой элементы ActiveX, и написать на VB собственный компонент было непросто (приходилось обращаться к более мощным, но и более сложным языкам). Как следствие стали появляться средства быстрой разработки приложений (RAD) следующего поколения, и самым ярким их представителем является среда Delphi. В ней процесс создания компонента практически не отличается от процесса написания обычной программы, благодаря чему было создано множество разнообразных компонентов для этой среды. Более того, само понятие компонента в Delphi не является синонимом графического элемента, компонент в этой среде может предоставлять и другие услуги (например, сетевые соединения).

Основные концепции

9

Программист может настраивать поведение компонента, изменяя его свойства и обрабатывая события. Свойства (properties) компонента определяют его внешний вид

иповедение. События (events) позволяют узнавать о действиях пользователя, изменении свойств, а также обеспечивают взаимодействие с другими компонентами. В визуальном средстве, таком как Delphi, список свойств постоянно находится у вас под рукой,

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

Базовой архитектурой всех, графических, вычислительных или любых иных компонентов Java является схема JavaBeans. Компоненты, написанные в соответствии с этой архитектурой, являются обычными классами языка Java, легко переносятся и следуют единому стандарту, позволяющему определить, какими свойствами обладает компонент

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

Соглашение об именах

Прежде чем включить компонент в средство быстрой разработки приложений, необходимо предоставить какой-то способ, позволяющий распознавать его свойства и события. В различных средах и системах используются разные подходы: среди наиболее распространенных можно назвать специальные записи в общедоступном системном реестре (компонент регистрирует себя при установке, после чего средство разработки находит его и добавляет в палитру инструментов) и специальные сопровождающие библиотеки типов (type library), содержащие описание свойств, методов и событий компонента. Эти подходы не идеальны — нет гарантии того, что ваше средство RAD совместимо с компонентом, сами компоненты компилируются в обычные двоичные файлы и перенести их на другую платформу почти невозможно.

Однако Java является платформенно-переносимым языком, и поэтому ваши программы не компилируются под конкретную платформу, а записываются в специальный байт-код, который затем выполняется виртуальной машиной Java. Благодаря этому программы сохраняют изначальную структуру классов, в том числе сохраняются имена переменных и методов (вы можете полностью исследовать содержимое класса с помощью общеизвестного любому программисту на Java механизма отражения из пакета java. lang.reflection). Создатели JavaBeans решили использовать это уникальное в своем роде свойство Java для того, чтобы максимально упростить создание компонентов. Действительно, достаточно сигнализировать о наличии свойств и событий особыми именами методов и переменных.

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

исобытий.

1.Каждому свойству с именем xxx необходимо предоставить метод для считывания значения этого свойства со стандартным именем getXxx() и метод для записи нового значения этого свойства с именем setXxx(). Например, если вы создаете графический компонент и хотите, чтобы у него было свойство color (цвет), необходимо сначала объявить закрытую переменную нужного типа (в нашем случае переменная имеет тип Color):

7 В спецификации JavaBeans эти соглашения об именах почему-то названы шаблонами проектирования (design patterns), с чем вряд ли можно согласиться.

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