WWW.DISS.SELUK.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА
(Авторефераты, диссертации, методички, учебные программы, монографии)

 

Pages:     || 2 | 3 | 4 | 5 |

«Swing ЭФФЕКТНЫЕ ПОЛЬЗОВАТЕЛЬСКИЕ ИНТЕРФЕЙСЫ Java Foundation Classes Москва • Санкт-Петербург • Нижний Новгород • Воронеж • Новосибирск • Ростов-на-Дону • Екатеринбург • Самара • Киев • Харьков • ...»

-- [ Страница 1 ] --

Иван Портянкин

Библиотека Программиста

Swing

ЭФФЕКТНЫЕ

ПОЛЬЗОВАТЕЛЬСКИЕ

ИНТЕРФЕЙСЫ

Java Foundation Classes

http://all-ebooks.com

Москва • Санкт-Петербург • Нижний Новгород • Воронеж • Новосибирск •

Ростов-на-Дону • Екатеринбург • Самара • Киев • Харьков • Минск 2005 2 Введение Появление в мире программирования платформы Java наделало много шума и изменило все вокруг.

«Чистокровный» объектно-ориентированный язык с прекрасным набором библиотек, изначально переносимый между различными платформами и практически независящий от конкретного производителя, быстро завоевал сердца разработчиков и признание крупнейших производителей программного обеспечения. Java развивается стремительно и охватывает практически все области, в которых применяется программирование: платформа J2ME (Java 2 Micro Edition) предназначена для создания приложений для мобильных устройств с ограниченными ресурсами, платформа J2EE (Java Enterprise Edition) позволяет создавать распределенные системы самого высокого качества и любого уровня сложности, платформу J2SE (Java 2 Standard Edition) без сомнения можно назвать ядром Java — именно с нее все начиналось, и по-прежнему эта часть Java является центральной. С помощью J2SE вы сможете создавать приложения для самых разнообразных нужд пользователей, это могут быть текстовые редакторы, электронные таблицы, клиенты для распределенных систем, созданных по технологии J2EE, апплеты, работающие в браузере как части HTML-страниц, удобные интерфейсы к базам данных JDBC и т.д.

Важнейшую часть любой программы составляет ее пользовательский интерфейс. Собственно говоря, пользователя мало интересуют те сложные алгоритмы обработки данных и удачные находки, реализованные внутри программы, также мало его занимают и технологии, примененные для создания самого приложения и его пользовательского интерфейса. Пользователь видит только то, что видит, и, отталкиваясь от этого факта, нам следует решать все задачи по проектированию и созданию пользовательского интерфейса. Интерфейс должен быть максимально удобным для пользователя и максимально быстрым; само собой, не последнее место занимает эстетическое удовлетворение, получаемое от работы с вашей программой. Долгое время, особенно до выхода платформы Java (пакета разработки JDK 1.2), считалось, что создать на Java качественный пользовательский интерфейс практически невозможно. Необходимость работать на разных платформах и учитывать все их различия привели к тому, что интерфейсы программ, написанных на Java, особенно ранних версий, представляли собой весьма отталкивающее зрелище.

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

Java Foundation Classes Одной из самых больших и самых важных частей платформы J2SE является набор библиотек под общим названием Java Foundation Classes (JFC). Именно эти библиотеки предназначены для создания эффектных и отточенных пользовательских интерфейсов. Ниже перечислены библиотеки, входящие в набор Java Foundation Classes.

Swing. Важнейшая часть JFC; содержит компоненты для создания пользовательского интерфейса, такие как таблицы и текстовые поля, и инструменты для работы с этими компонентами. Библиотека Swing, как мы вскоре увидим, великолепно спланирована и реализована и способна дать вам все, что только может пожелать разработчик пользовательского интерфейса. Если вы создаете лаконичный «деловой» интерфейс, вам понадобится всего пара строк кода. Если же вы раскрашиваете ваше приложение всеми красками радуги и создаете для него сложный нестандартный интерфейс, вам понадобится немного больше усилий. Но ничего невозможного для Swing нет.

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

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

';

Drag'n'Drop. Дополнение, позволяющее вашему приложению взаимодействовать с приложениями операционной системы пользователя или другими Java-приложениями с помощью технологии перетаскивания (drag and drop). Подобная возможность очень удобна для пользователя и позволяет ему сразу же забыть о том, что приложение написано на Java и не имеет практически никаких связей с его операционной системой.

Ядром Java Foundation Classes без всяких сомнений является библиотека Swing —все остальные части набора классов так или иначе встроены в нее или предоставляют для компонентов этой библиотеки дополнительные возможности. Создавать пользовательский интерфейс своих приложений вы будете именно с помощью Swing, и именно эту библиотеку мы будем изучать в этой книге. Для начала мы познакомимся с основными свойствами Swing, ее общей структурой, а затем перейдем к компонентам библиотеки. Они позволят вам создавать фантастические пользовательские интерфейсы всего одним мановением руки.

Структура книги Ниже приведено краткое описание составляющих книгу глав. Большая часть из них посвящена описанию компонентов Swing и примерам их использования. Ну а начнем мы с исследования основных механизмов библиотеки, тех «винтиков», на которых работают все компоненты Swing. Как только мы их изучим, секреты библиотеки больше не будут для нас загадкой.

Глава 1. Основные концепции. В этой главе мы взглянем на Swing «с высоты птичьего полета» и раскроем для себя главные замыслы разработчиков библиотеки, которые оказали наибольшее влияние на ее архитектуру. Для начала мы увидим, что в основе Swing лежит библиотека AWT, узнаем, как это влияет на библиотеку Swing и ее компоненты, рассмотрим архитектуру JavaBeans и механизмы разделения модели, вида и контроллера. Не ускользнут от нашего внимания и подключаемые внешний вид и поведение компонентов Swing, а также поддержка пользователей с ограниченными возможностями.

Глава 2. Модель событий. Здесь мы узнаем, как в Swing обрабатываются события. Сначала мы рассмотрим простые примеры, а затем перейдем к скрупулезному исследованию «начинки» системы обработки событий. Будут рассмотрены вопросы написания слушателей, низкоуровневые события, техника обработки событий, поток рассылки событий EventDispatchThread и очередь событий EventQueue. В конце главы мы узнаем «золотое правило» системы обработки событий Swing; оно совсем несложно, но позволяет писать по-настоящему быстро действующие программы, невзирая на все доводы скептиков о не слишком высокой производительности пользовательских интерфейсов, созданных с помощью Swing.

Глава 3. В глубинах Swing. Система рисования Swing и остальные механизмы, реализованные в базовом классе JComponent, незаметно работают «за кулисами» библиотеки, освобождая вас от рутинной работы. Знать, как и что происходит во внутренних механизмах библиотеки, требуется нечасто, но в сложных ситуациях без этого не обойтись. Здесь мы исследуем самые сложные части Swing, реализация которых во многом объясняет работу всех компонентов библиотеки.

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

Глава 5. Искусство расположения. Менеджер расположения — это ассоциированный с контейнером алгоритм, который определяет, как компоненты должны располагаться в контейнере.

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

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

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

Глава 8. Меню и панели инструментов. В меню собраны все команды, необходимые для работы с приложением. С их помощью ознакомление с возможностями приложения проходит быстрее, и начать работу, имея под рукой хорошо организованную и интуитивно понятную систему команд, гораздо проще. Создание самого сложного меню в Swing после прочтения данной главы перестанет быть для вас проблемой. Панели инструментов также находятся на «переднем краю» приложения и содержат набор элементов управления для выполнения наиболее употребительных действий. В этой главе мы разберем компонент JToolBar, применяемый в Swing для создания панелей инструментов.

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

Глава 10. Диапазоны значений. Эта глава посвящена компонентам, обеспечивающим возможность регулировки (плавной или ступенчатой) данных в некотором диапазоне или наглядно представляющим на экране данные из некоторого диапазона. Ползунки JSLider позволяют выбрать значение в некотором ограниченном диапазоне числовых данных. Индикаторы процесса JProgressBar в наглядной форме показывают, какая часть ограниченной задачи уже завершена. Наконец, новинка пакета JDK 1.4, счетчики JSpinner, дают возможность выбора произвольного значения среди некоторого набора альтернатив, который может быть и неограниченным. Как мы увидим, все эти компоненты Swing обладают завидной гибкостью и способны на многое.

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

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

Компоненты JFileChooser и JColorChooser незаменимы для выбора файлов и цветов.

Глава 13. Уход за деревьями. Иерархические отношения данных принято отображать в специальных компонентах пользовательского интерфейса, называемых деревьями. Деревья в Swing, реализованные компонентом JTree, обладают впечатляющими возможностями, и данная глава полностью посвящена им. Мы изучим далеко не самый простой процесс создания модели дерева, овладеем всеми тайнами стандартных узлов и стандартной модели деревьев Swing — эти модели чаще всего и применяются при создании интерфейсов. Далее нас ждет подробное изучение модели выделения дерева и настройка всех аспектов отображения и редактирования узлов деревьев Swing.

Глава 14. Текстовые компоненты. Одной из самых впечатляющих частей библиотеки Swing является пакет javax.swing.text, обеспечивающий ее средствами для работы с текстом. Благодаря этому пакету в вашем арсенале появляются несколько текстовых компонентов, реализующих любые механизмы для ввода и редактирования текста, от самых простых до чрезвычайно изощренных. В этой главе мы познакомимся со всеми текстовыми компонентами и их основными возможностями.

Кроме того, мы затронем вопросы, относящиеся к внутренней реализации текстовых компонентов Swing: изучим основные свойства модели текстовых компонентов Document и многое другое.

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

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

Для кого предназначена книга Эта книга — не для новичков в программировании. Подразумевается, что вы имеете некоторый опыт программирования на Java, скорее всего, уже пробовали создавать на этом языке первые пользовательские интерфейсы с помощью AWT, Swing или средств быстрой разработки (Rapid Application Development, RAD), так что представленные в книге конструкции языка Java, а также термины, применяемые при программировании и создании пользовательских интерфейсов, не введут вас в заблуждение. Замечательно, если вы владеете навыками объектно-ориентированного проектирования и анализа, — в этом случае понимание архитектуры библиотеки придет гораздо быстрее и работа с ней станет для вас истинным удовольствием. Отсутствие подобных навыков не помешает вам в полной мере изучить Swing, но только некоторый опыт в объектно-ориентированном проектировании даст вам возможность оценить всю элегантность библиотеки.

Интерактивная документация Материал книги ни в коем случае не повторяет и не копирует информацию, которая содержится в интерактивной документации JDK для библиотеки Swing (описание всех классов, методов и полей библиотеки, как правило, довольно краткое). Вместо этого мы изучаем основы Swing, рассматриваем главные механизмы библиотеки, а затем, разрабатывая небольшие и понятные примеры, овладеваем всеми тайнами компонентов Swing. Так вы составляете для себя полную картину возможностей Swing, а интерактивная документация становится вашим верным компаньоном, способным подсказать правильное название метода и список его параметров. На самом деле при работе с библиотекой Swing документация требуется не так уж и часто — настолько удачно спроектирована библиотека и выбраны названия свойств и методов (чему не мало способствует архитектура JavaBeans, которую мы рассмотрим в главе 1). При чтении глав, посвященных конкретным компонентам Swing, лучше всего иметь интерактивную документацию «под рукой» — с ее помощью вы узнаете все возможности компонента еще быстрее.

Язык шаблонов проектирования Везде, где возможно, архитектура библиотеки Swing и ее компонентов описывается с помощью языка шаблонов проектирования (design patterns), нового прекрасного средства описания любого (обобщенного или подробного) объектно-ориентированного решения. Шаблоны проектирования представляют собой набор наиболее удачных и проверенных временем схем объектноориентированного проектирования и анализа, позволяющих быстро, элегантно и максимально гибко решать часто возникающие задачи. Библиотека Swing буквально вдоль и поперек «прошита»

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

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

открыв страницу с нужным примером, вы мгновенно поймете, как работать с тем или иным компонентом Swing.

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

Специально для вашего удобства в состав исходных текстов книги входит архив в формате JAR (booktools.jar) со всеми инструментами, созданными в данной книге. Вы сможете включить этот архив в список своих классов и легко применять созданные нами в книге инструменты в своих программах. Найти этот архив также можно на сайте www.IPSoftware.ru.

Отзывы и комментарии Свои отзывы о материале книги, предложения о дополнениях, комментарии, информацию о найденных ошибках вы сможете разместить на сайте www.IPSoftware.ru. Там же вы сможете задать свои вопросы автору книги, получить необходимые консультации, найти все исходные тексты данной книги, вспомогательные инструменты для работы с компонентами Swing, а также узнать о будущих планах и новых разработках в области Swing и Java Foundation Classes.

От издательства Ваши замечания, предложения, вопросы отправляйте по адресу электронной почты [email protected] (издательство «Питер», компьютерная редакция). Мы будем рады узнать ваше мнение!

Подробную информацию о наших книгах вы найдете на сайте издательства http://www.piter.com.

Глава 1 Основные концепции С этой главы мы начнем свое путешествие по библиотеке Swing, которая является самой большой и самой важной частью набора классов Java Foundation Classes, составляя ядро этого набора. Мы узнаем, чем руководствовались разработчики библиотеки, какие цели они преследовали, как эти цели были ими достигнуты. Сначала мы обсудим внутреннее устройство библиотеки и наиболее важные моменты ее реализации, не останавливаясь на деталях — так нам будет проще оценить масштабы и возможности Swing, которые поистине безграничны и вызывают искреннее восхищение. Затем, в последующих главах, мы подробнее остановимся на компонентах Swing.

Итак, что же такое Swing? Если говорить кратко, то это набор графических компонентов для создания пользовательских интерфейсов приложений и апплетов, а также вспомогательные классы и инструменты для работы с этими компонентами. В принципе, это лаконичное заявление довольно точно описывает библиотеку Swing, но оно не должно вводить вас в заблуждение. Легкость программирования, мощь тогда, когда она нужна, и возможность настроить все по своему вкусу — все это относится к Swing как к никакой другой библиотеке.

Обычно, если кто-то заявляет о безграничных возможностях новой библиотеки, это значит, что ее изучение, освоение и последующая работа будут непростыми. Это правило не срабатывает в случае с библиотекой Swing — работать с ней можно, не зная ровным счетом ничего о том, как она устроена, а ведь внутри нее скрыты совсем непростые механизмы. Например, внешний вид компонентов Swing можно легко изменить одной строчкой кода, и для этого не нужно знать подробностей. Только если вы соберетесь придать компонентам некий особенный (нестандартный) внешний вид, вам потребуются детали. Можно годы работать с библиотекой Swing, просто создавая компоненты, добавляя их в окна и обрабатывая события, и ничего не знать о скрытом в ней мощном механизме программирования моделей. Одним словом, Swing соответствует уровню каждого: и новичку, и опытному программисту будет казаться, что эта библиотека создана специально для него.

Последовательно читать все то, что написано в этой и двух следующих главах, вовсе не обязательно.

Это особенно верно для тех, кто начал программировать на Java не так давно. Можно просто выбирать тот материал, который в данный момент интересует вас больше всего, читать и тут же применять новые знания в своих приложениях. Однако при достижении некоторого уровня знаний лучше остановиться и попытаться осмыслить библиотеку в целом. Именно этим мы сейчас и займемся.

Поначалу библиотеки Swing в Java вообще не было. Вместо нее использовалась библиотека AWT, общая идея которой была относительно неплохой. Но вот реализовать эту идею толком не удалось, что очень сильно вредило Java как языку создания настольных приложений (desktop applications).

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

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

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

В начале было... AWT Основой библиотеки Swing, тем тонким слоем, что лежит между ней и зависящим от платформы кодом, является библиотека AWT (

Abstract

Window Toolkit — инструментарий для работы с различными оконными средами). В отличие от библиотеки Swing, которая появилась в Java версии 1.1 как нестандартное дополнение и стала частью платформы только с выходом Java 2, пакет java.awt входил в Java с самого первого выпуска. Поначалу именно он предназначался для создания пользовательских интерфейсов. Исходное назначение AWT — предоставить набор графических компонентов, который вобрал бы в себя наиболее характерные черты современных элементов управления и позволил бы однократно создавать пользовательские интерфейсы, подходящие для любой платформы. Компоненты AWT на самом деле не выполняли никакой работы и были очень простыми — это были просто «Java-оболочки» для элементов управления той операционной системы, на которой работал пользователь. Все запросы к этим компонентам незаметно перенаправлялись к операционной системе, которая и выполняла всю работу. Чтобы сделать классы AWT независимыми от конкретной платформы, каждому из них был сопоставлен своеобразный помощник 1 (peer), который и работал с этой платформой. Для того чтобы встроить в AWT поддержку новой платформы, нужно было просто переписать код этих помощников, а интерфейс основных классов оставался неизменным 2. На рис. 1.1 показана исходная иерархия классов AWT. Диаграмма следует формату унифицированного языка моделирования (Unified Modeling Language, UML): сверху располагаются базовые классы, а ниже классы, унаследованные от базовых.

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

Одним из самых необычных свойств AWT стала способность контейнеров располагать компоненты по определенному алгоритму, определяемому менеджером расположения (layout manager) 3.

Контейнерами высшего уровня, то есть контейнерами, содержащими все остальные элементы пользовательского интерфейса, служили окна с рамкой, диалоговые окна, а также апплеты, запускаемые из браузера. Они были представлены классами Frame, Dialog и Applet. Классы AWT, представляющие собой компоненты пользовательского интерфейса, такие как кнопки (Button) и надписи (Label), получились очень небольшими и простыми в использовании, как того и хотели создатели AWT. Вы могли смело работать с ними, зная, что на любой платформе компоненты вашего пользовательского интерфейса будут выглядеть должным образом. Как мы уже знаем, об этом Дословный перевод слова «peer» — «равный, имеющий те же права», и так оно и есть — классы AWT и их помощники поровну разделяют обязанности: первые предоставляют услуги программистам-клиентам Java, а вторые незаметно связывают эти услуги с операционной системой. Но с точки зрения программиста-клиента (а мы стоим именно на такой позиции) удобнее использовать слово «помощник».

Эту концепцию, использованную в AWT, можно описать и языком шаблонов проектирования. Это не что иное, как мост (bridge) — программист взаимодействует с одной иерархией классов, а работ; фактически выполняется в другой, параллельной иерархии.

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

Менеджер расположения — это особая служба, мы подробно обсудим, как и почему она используется в Java, в главе 5, которая полностью посвящена этому вопросу.

заботились помощники компонентов. Их обязанности были описаны в соответствующих интерфейсах (имя каждого можно было получить, добавив к имени компонента слово «Peer», например ButtonPeer). Для поддержки библиотекой AWT новой платформы оставалось только написать реализующие эти интерфейсы классы, работающие с данной платформой (например, в пакете JDK для Windows кнопки создавались с помощью класса WButtonPeer, реализующего интерфейс ButtonPeer). Такой механизм позволял обеспечить переносимость графических приложений, написанных на Java.

Однако неплохая на первый взгляд идея AWT провалилась. Этому способствовало множество причин. Ниже перечислены только некоторые из них.

• Чрезвычайно плохо была реализована схема обработки событий, благодаря чему пакет AWT надолго стал объектом нападок и насмешек. Создатели AWT не смогли придумать ничего лучшего, как сообщать обо всех событиях в метод handleEvent() из базового класса Component, и чтобы обработать эти события, приходилось наследовать от класса компонента (обычно от класса окна) и использовать огромный оператор switch (или if), распределяя их по обработчикам. Программисты, которые уже надеялись на избавление от этой адской процедуры, порядком поднадоевшей им еще со времен программирования для Windows, были сильно разочарованы. Более того, если в Windows они могли хотя бы быстро сопоставить пришедшее событие и адрес его обработчика, то в Java, из-за отсутствия в этом языке указателей, сделать даже это было невозможно. Все это делало заявления Sun о лучшем в мире языке программирования просто смешными. Вдобавок создание собственных типов событий оказывалось практически невозможным.

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

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

• Еще одной проблемой, пусть и не самой острой, стало отсутствие в AWT четкого механизма, позволяющего программистам создавать собственные компоненты и использовать их в средах визуального построения (builders) графического пользовательского интерфейса (Graphical User Interface, GUI). Хотя такие средства и не замедлили появиться с выходом первой версии Java, возможности их оставляли желать много лучшего. Обычно все заканчивалось десятком компонентов AWT и в лучшем случае несколькими дополнительными компонентами. Добавить же в свою палитру компонентов новый элемент от стороннего производителя было почти невозможно, так как отсутствовал стандарт, способный обеспечить взаимодействие компонентов и средств от разных производителей. С другой стороны, создавать пользовательский интерфейс вручную было очень тяжело — задание для компонентов абсолютных экранных позиций противоречило концепции переносимости приложений, а имеющиеся в выпуске JDK 1.0 менеджеры расположения были либо очень простыми, либо чрезмерно сложными. Из-за этого процесс создания интерфейса AWT-приложений требовал слишком много времени и усилий.

• Множество неудобств доставляла также низкая скорость выполнения программ, написанных с помощью AWT, особенно программ, использующих графику и анимацию. Это было неудивительно — для выполнения любого действия над графическим компонентом виртуальной машине Java приходилось обращаться к операционной системе, то есть несколько раз переключаться в режим ядра и обратно. Учитывая дороговизну такой операции (сотни процессорных тактов), можно было сказать, что добиться нормальной скорости выполнения от Java-приложения могли только кудесники оптимизации.

Первый выпуск пакета разработки Java-программ (JDK 1.0) наделал много шума в компьютерном мире. Простой объектно-ориентированный и надежный язык, обеспечивавший переносимость между любыми платформами, обещал решить львиную долю проблем в программировании. Это относилось и к разработке настольных приложений, перенос которых с одной платформы на другую всегда был «головной болью» для разработчиков. Более того, полная поддержка нового стандарта кодировки символов Unicode обещала навсегда избавить разработчиков от проблем, связанных с локализацией приложений. Одним словом, ожидания были самые радужные.

Однако после первого знакомства с Java мнение о возможностях этого языка в области создания приложений изменилось. Если апплеты заняли достойное место в мире web-программирования и благодаря их новизне и уникальности разработчики мирились с ограничениями AWT, то в области приложений все недостатки сразу же «вылезли наружу». Недоработки AWT, перечисленные нами чуть выше, делали почти невозможным создание качественных современных приложений на Java.

Программисты вернулись к старым способам разработки приложений, а о Java-приложениях было составлено примерно такое мнение: «Крайне ограничены в функциональности и управляемости.

Стоит использовать только там, где жизненно важным фактором является переносимость между платформами». К сожалению, мнение это было справедливо, и винить в этом создатели Java могли только себя.

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

Тем временем фирма Sun начала готовить выпуск следующей версии Java (1.1). Одной из самых приоритетных целей команды создателей Java была полная переработка AWT и устранение всех недостатков этой библиотеки. Уже тогда было ясно, что даже при условии их устранения модель AWT не сможет служить основой для создания качественных приложений — слишком уж ограничены были ее компоненты. Нужно было кардинально новое решение, которое привнесло бы в Java всю мощь современных подходов к созданию компонентов пользовательского интерфейса. Как мы сейчас увидим, решения были найдены. Итак, что же предложила новая версия Java для решения проблем AWT? Давайте рассмотрим все по порядку.

• Важнейшим стало понятие уже упоминавшегося легковесного компонента. В предыдущей версии AWT у каждого компонента была связь с операционной системой, на которой работало ваше приложение. Даже если вы создавали собственный компонент, наследуя от класса Component (или от любого другого класса AWT), вы все равно оставались в жестких рамках этих взаимоотношений, потому что ваш компонент представлял собой маленькое окно, полностью принадлежащее операционной системе. Как мы уже знаем, это влекло за собой массу проблем, прежде всего, в плане быстродействия ваших программ и гибкости ваших компонентов. Однако Java — полноценный и весьма мощный язык программирования, и для создания чего-либо на нем вовсе не обязательно обращаться к ресурсам операционной системы. С таким же успехом можно создать это самое что-то без помощи со стороны, используя исключительно Java. Эта простая мысль стала отправной точкой в процессе разработки легковесных компонентов. Итак, легковесный компонент — это просто область в пространстве экрана, занимаемом вашим Java-приложением. Главные его атрибуты — это координаты в окне и размер. Для операционной системы легковесный компонент вообще не существует, потому что представляет собой всего лишь часть какого-то окна. Всю работу по поддержке легковесных компонентов взяли на себя библиотека AWT и виртуальная машина Java. Для программиста не существует никакого отличия между легковесными и обычными компонентами, которые по аналогии стали называть тяжеловесными (heavyweight), то есть имеющими связь с операционной системой и представленными в своем собственном окне.

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

• Вторую половину проблем AWT была призвана решить новая архитектура проектирования программных компонентов под названием JavaBeans. Она провозгласила набор простых правил, которые делали возможным создание на Java легко настраиваемых, расширяемых и переносимых компонентов пользовательского интерфейса. Благодаря новой архитектуре становилось возможным не только использовать в разработке программ любые доступные компоненты (причем, имея единый и простой стандарт, они поддерживались в любой среде создания Java-программ), но и самому участвовать в создании таких компонентов, что оказывалось максимально простым делом. Самым большим достижением создателей архитектуры JavaBeans стало то, что они смогли оставить компоненты обычными классами языка Java, поэтому фактически никаких новых знаний и сверхусилий для их разработки не требовалось 4. Для компонентов JavaBeans также была разработана новая система обработки событий, одна из самых элегантных объектно-ориентированных систем такого рода. Она быстро заставила забыть кошмар обработки событий прежней версии AWT и моментально привлекла новых сторонников. Все компоненты библиотеки Swing являются компонентами JavaBeans, поэтому чуть позже мы подробнее обсудим эту архитектуру.

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

Удивительно, но казавшаяся всем почти безнадежной библиотека AWT вдруг оказалась способной помочь в создании компонентов, намного опережающих по своим возможностям компоненты «родной» операционной системы. Чем же были так хороши эти новые легковесные компоненты?

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

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

Практически безграничные возможности легковесных компонентов убедили всех в том, что если и стоит создавать приложения на Java, то только с использованием легковесных компонентов — лишь в этом случае можно будет гарантировать стабильность работы и внешнего вида приложения независимо от прихотей операционной системы и различных виртуальных машин. Тяжеловесные компоненты AWT — компоненты типа кнопок (Button) и окон (Window) — остались в Java, потому что уже было написано много кода с их использованием (особенно апплетов). Они к тому же должны были составить основу для новой библиотеки пользовательского интерфейса, необходимость разработки которой была несомненна. Вопрос был лишь в том, когда эта библиотека появится.

В момент выпуска новой версии Java и соответствующего ей пакета разработки JDK 1.1 уже было известно, что в недрах компании Sun полным ходом идут работы по созданию новой библиотеки пользовательского интерфейса, полностью составленной из легковесных компонентов и обладающей большими возможностями. Однако на этот раз в Sun решили не спешить, подгоняя выпуск новой библиотеки к выпуску JDK 1.1. (Хорошо, что создатели Java учли горький опыт библиотеки AWT, которая была создана буквально за несколько месяцев. Что из этого получилось, мы с вами уже знаем.) Вместо этого разработчики вместе с библиотекой пользовательского интерфейса (создание которой было первоочередной задачей) начали готовить еще несколько библиотек, призванных дать приложениям Java максимальную гибкость и самые современные возможности. В будущем эти несколько библиотек станут называться набором классов Java Foundation Classes.

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

Ну а пока Sun готовила новые библиотеки, в мире Java-программирования, происходил буквально «бум» компонентов пользовательского интерфейса. Завидные возможности легковесных компонентов и особенно технология JavaBeans способствовали появлению невероятного количества самых разных компонентов. Разрабатывались также весьма хорошие библиотеки, позволявшие создавать отличные приложения. Собственные решения предлагали такие гиганты индустрии, как Borland и Symantec, и даже корпорация Microsoft не устояла перед соблазном и создала собственную библиотеку компонентов. Появлялись прекрасные средства быстрой разработки приложений (Rapid Application Development, RAD), благодаря все той же технологии JavaBeans плотно напичканные компонентами от самых разных производителей. Одним словом, рынок «бурлил и пенился». Однако в глубине души все понимали, что последнее слово останется за создателями Java — фирмой Sun. Именно новые выпуски JDK знаменовали новые ступени развития Java, и именно на новые библиотеки от Sun ориентировались как партнеры Sun, так и независимые производители, поскольку библиотека, которая будет присутствовать в новом выпуске JDK, не потребует дополнительных усилий по установке и распространению и определит лицо Java-приложений.

Когда прошло некоторое время после выпуска пакета JDK 1.1, начали появляться первые бета-версии новой библиотеки, получившей кодовое название «Swing». И даже эти первые версии, полные ошибок и недоработок, произвели ошеломляющее впечатление. Ничего подобного до сих пор в мире Java-приложений не было.

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

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

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

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

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

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

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

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

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

Помимо того, что базовый класс JComponent обеспечивает механизм эффективной прорисовки компонентов на экране, он обеспечивает поддержку наиболее важных свойств Swing, характерных для всех компонентов этой библиотеки. (Появление многих из указанных свойств было вызвано отзывами разработчиков, измученных «битвами» с AWT.) В класс JComponent встроена поддержка всплывающих подсказок (tooltips), рамок (borders), средств для пользователей с ограниченными возможностями (accessibility), клавиатурных действий (keyboard actions) и многого другого. Все это мы подробно обсудим немного позднее в соответствующих главах.

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

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

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

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

Перечисленные классы имеют всю необходимую поддержку для компонентов Swing, которую обеспечивает так называемая корневая панель (root pane) — особый контейнер Swing (мы подробно обсудим его в главе 4).

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

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

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

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

Объяснение снова лежит в концепции легковесных компонентов. Давайте вспомним, что легковесные компоненты — это области окна вашего приложения, никак не связанные с операционной системой.

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

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

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

Даже если легковесные компоненты (компоненты Swing) внутри контейнера находятся в стопке выше тяжеловесных компонентов (компонентов AWT) и перекрывают их, при выводе на экран тяжеловесные компоненты все равно закроют легковесные.

Впрочем, на практике ситуация, когда обычные компоненты перекрывают друг друга (к примеру, зачем кнопке перекрывать текстовое поле или другую кнопку), встречается не очень часто. Поэтому, если компоненты Swing и AWT находятся в одном контейнере и занимают каждый свое место, работать все будет нормально. Но и здесь есть свои «подводные камни». Дело в том, что меню в Swing также является легковесным компонентом, так что система меню и компоненты, его использующие (раскрывающиеся списки), при наличии в приложении тяжеловесных компонентов могут работать неверно (выпадающие меню будут закрыты тяжеловесными компонентами при попадании в их область). То же самое можно сказать и о легковесных контейнерах Swing, таких как внутренние окна (JInternalFrame). В них по тем же самым причинам ни в коем случае не следует помещать тяжеловесные компоненты: если у вас приложение с многодокументным интерфейсом (Multi-Document Interface, MDI) и открыто несколько внутренних окон, то окно с тяжеловесным компонентом в любом случае «вылезет» наверх, даже если оно не является активным. Если с проблемой меню еще как-то можно справиться (создатели Swing специально добавили в класс всплывающих меню возможность использования для них тяжеловесных компонентов), то проблема с легковесными контейнерами остается нерешенной.

При создании приложений лучше всего избегать совместного использования легковесных и тяжеловесных компонентов (Swing позволяет создать любой интерфейс, не прибегая к AWT). Если совместить компоненты все же необходимо, следует следить за тем, чтобы они не размещались в легковесных контейнерах (типа панели прокрутки JScrollPane или внутреннего окна JInternalFrame) и не перекрывали легковесных меню.

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

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

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

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

Более того, само понятие компонента в Delphi не является синонимом графического элемента, компонент в этой среде может предоставлять и другие услуги (например, сетевые соединения).

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

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

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

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

Благодаря этому программы сохраняют изначальную структуру классов, в том числе сохраняются имена переменных и методов (вы можете полностью исследовать содержимое класса с помощью механизма отражения 7 из пакета Java.lang.reflection).

Создатели JavaBeans решили использовать это уникальное в своем роде свойство Java для того, чтобы максимально упростить создание компонентов. Действительно, достаточно сигнализировать о наличии свойств и событий особыми именами методов и переменных.

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

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

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

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

private Color color;

Затем нужно написать два метода для считывания и записи этого свойства:

public Color getColor() { /*... */ } public void setColor(Color c) { /*... */ } Когда средство разработки программ при анализе вашего класса обнаружит пару этих методов, оно добавит в список свойств вашего компонента свойство color, и разработчик, использующий ваш компонент, сможет менять это свойство. Можно даже предоставлять только метод для считывания (getXxx()) и таким образом помечать свойство компонента как предназначенное только для чтения. Заметьте, что имена методов должны следовать рекомендациям Sun, поэтому после слов get или set наличие прописной буквы обязательно.

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

Например, рассмотрим свойство вида:

private boolean enabled:

Методы для этого свойства могут иметь следующие названия:

public boolean isEnabled() { / *... * / } public void setEnabled(boolean b) { / *... * / } To есть, метод для записи нового значения не меняется, в методе для получения значения вместо приставки get используется is. Это сделано исключительно для того, чтобы людям было проще читать названия таких методов.

3. Методы компонента, которые не предназначены для считывания и записи свойств, но служащие для выполнения каких-то важных действий, должны быть объявлены открытыми 4. Для каждого события, которое способен генерировать компонент, необходимо предоставить пару методов для добавления и удаления объектов, заинтересованных в этом событии (эти объекты называют слушателями). Мы подробнее разберемся с событиями чуть 5. Класс компонента необходимо объявить открытым (public) и определить в нем конструктор без параметров. Тогда средство разработки программ сможет создать экземпляр такого класса, не обладая дополнительной информацией о типе и предназначении параметров, передающихся в конструкторе. Если вашему компоненту все же нужны параметры для корректной работы, всегда можно сделать их свойствами и предоставить в классе методы для считывания и записи значений этих свойств.

В результате мы получим класс, единственное отличие которого от других классов состоит в том, что его методы следуют стандартной схеме именования JavaBeans. Этого будет вполне достаточно для того, чтобы средство визуальной разработки приложений смогло распознать в нем компонент и вывести список его свойств и событий. Только вдумайтесь, как просто звучит такое утверждение и какие потрясающие последствия оно имеет. Вы создаете обычный класс, называя методы по незамысловатым правилам, компилируете его, после чего класс становится доступным для всего мира, причем использовать его можно как угодно — достаточно просто создать объект в своей программе и настроить в визуальном средстве или в распределенном окружении так, как вам нужно.

Архитектура JavaBeans стала настоящим открытием в компонентном программировании и придала ему новый импульс. С ее появлением отпала необходимость изучать дополнительные библиотеки и разрабатывать сопровождающие программы только для того, чтобы построить компонент. Вы строите компоненты, просто создавая классы, что вместе с переносимостью Java дает программисту очень большие возможности. Неудивительно, что после выхода пакета JDK 1.1 и появления в нем спецификации JavaBeans началось настоящее «извержение» компонентов от разных производителей.

Более того, создатели Java переделали многие классы стандартных библиотек так, чтобы они удовлетворяли требованиям новой архитектуры. Сейчас представить себе Java без JavaBeans уже невозможно: даже серверные технологии, такие как JSP (Java Server Pages) и сервлеты, используют JavaBeans.

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

Если создатели компонента удачно подбирают названия его свойств, знакомство программиста с таким компонентом проходит быстро и безболезненно (компоненты библиотеки Swing — прекрасный пример).

Расширенные возможности Архитектура Java Beans не ограничивается соглашением об именах и новой системой событий и предоставляет программисту дополнительные способы настройки и расширения своих компонентов.

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

Привязанные свойства Привязанные (bound) свойства используются в тех случаях, когда о смене значения свойства необходимо сообщить другому компоненту или объекту. В пакете Java.beans имеются несколько вспомогательных классов, позволяющих реализовать привязанные свойства без особых усилий. Все сводится к тому, что в классе компонента появляется еще одна пара методов для добавления и удаления слушателей события типа PropertyChangeEvent, однако событие это не относится к работе компонента, а возникает при смене значения некоего свойства. Заинтересованным в смене значения свойства объектам нужно лишь следить за этим событием. При обработке события можно узнать, какое свойство изменилось, каким стало новое значение этого свойства, каким было его старое значение. Свойства почти всегда делают привязанными, потому что визуальные средства разработки часто используют этот механизм, чтобы контролировать, когда следует обновлять внешний вид компонентов и список свойств.

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

Индексированные свойства Бывают ситуации, когда использовать обычные свойства и методы для работы с ними не совсем удобно, например, если компонент хранит множество однотипной информации (список). В JavaBeans специально для этого предусмотрены индексированные (indexed) свойства. Отличие их от обычных свойств заключается в том, что вместо одного объекта в методах set/get передается массив объектов, и в дополнение к этим двум методам предоставляются методы, изменяющие одну из позиций в этом массиве. Выглядеть это может так:

public Color[] getColors();

public void setColors(Color[] с);

public Color getColors(int index);

public void setColors(int index, Color c);

Здесь имя индексированного свойства — colors, и для него предоставлено по два метода get/set.

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

Редакторы свойств По умолчанию считается, что визуальное средство разработки способно обеспечить правильное редактирование свойств. Для наиболее часто встречающихся свойств так оно и есть (любое средство справится со свойствами, заданными в виде строк, чисел или цветов). Однако если ваш компонент обладает свойством неизвестного и довольно сложного типа, визуальное средство не сможет помочь программисту, и ему придется настраивать ваш компонент вручную, что вообще-то противоречит принципу визуального программирования. Архитектура JavaBeans решает эту проблему с помощью редакторов свойств (property editors). Редактор свойств — это дополнительный компонент, позволяющий настраивать свойства определенного типа, он чаще всего поставляется вместе с компонентом. Создать его довольно просто — надо расширить класс PropertyEditorSupport, написать на его основе редактор свойств и зарегистрировать его. Проще всего зарегистрировать редактор с помощью класса PropertyEditorManager из пакета Java.beans. Статический метод registerEditor() этого класса позволяет сопоставить тип свойства и класс его редактора.

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

Для того чтобы создать описание компонента, необходимо определить класс со специальным именем:

имя класса компонента плюс слово «BeanInfo». Этот класс должен либо реализовывать интерфейс Beanlnfo, либо расширять класс SimpleBeanInfo (который также реализует интерфейс BeanInfo и служит для упрощения реализации этого интерфейса). Реализуя методы интерфейса BeanInfo, программист может весьма подробно описать свой компонент. Затем полученный класс упаковывается в архив вместе с компонентом, и средство разработки, загружая этот архив, извлекает дополнительную информацию о компоненте.

Постоянство При работе с компонентом программист меняет его свойства и пишет код, обрабатывающий события.

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

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

Только с появлением JDK 1.4 нашлось более приемлемое решение. В этом пакете разработки состояние компонента стало возможным хранить в файле формата XML. К очевидным преимуществам нового подхода следует отнести то, что сохраняется не детализированная информация о компоненте, а лишь минимальная последовательность действий, необходимая для приведения компонента в нужное состояние. Ожидается, что это решение наконец-то обеспечит необходимую степень совместимости, простоты и переносимости. Учитывая все большую популярность XML (Extension Markup Language — расширенный язык разметки) и появление все новых средств для работы с этим универсальным языком, можно сказать, что компоненты JavaBeans обзавелись приличным механизмом обеспечения постоянства. Новый механизм поддерживается классами XMLEncoder и XMLDecoder из пакета Java.beans.

Компоненты Swing — это компоненты JavaBeans Теперь, когда мы увидели, как много привнесла в Java спецификация JavaBeans, нетрудно догадаться, что библиотека Swing проектировалась в полном соответствии с ней. Классы библиотеки Swing, представляющие собой компоненты, созданы в соответствии с соглашением об именах. Все возможности компонентов Swing представлены в виде свойств и имеют соответствующий набор методов get/set. События компонентов также используют схему JavaBeans. Поддерживается и механизм постоянства (в том числе новый, на основе XML).

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

То, что компоненты Swing являются компонентами JavaBeans, важно, скорее, для средств RAD, для любого из которых сейчас характерна полная поддержка Swing. В этой книге мы не рассматриваем вопросы и проблемы визуального программирования, однако знание JavaBeans иногда оказывается очень удобным. Создателям Swing удалось удачно подобрать названия свойств компонентов, и при написании программы зачастую удается просто угадывать названия нужных методов. Например, довольно очевидно, что у текстового поля (JTextField) должны быть свойства «текст» (text), имея в виду весь напечатанный текст, и «выделенный текст» (selected text). Для получения значения этих свойств можно попытаться вызвать методы getText() и getSelectedText(). Как оказывается, методы именно с такими именами присутствуют в классе JTextField. Зная методы для получения значений свойств, легко понять, какие методы используются для изменения свойств: setText() и setSelectedText(). Вы будете приятно удивлены тем, как часто срабатывает в Swing такой трюк и как это ускоряет работу. Конечно, это не рецепт на все случаи жизни, но, по крайней мере, методы с такими понятными названиями и запоминать гораздо проще.

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

При переходе на другую платформу Java-приложения приобретали совсем уже отталкивающий вид (если вы создавали приложение из AWT-компонентов на платформе Mac, а затем переносили его на Windows, оно работало, однако изначально спроектированный пользовательский интерфейс тестировался в расчете на внешний вид Mac, и в Windows он был уже не тот). Приходилось либо тестировать приложение на каждой платформе и при переходе специально настраивать его, либо мириться с тем, что ваше приложение выглядит плохо. Когда стало окончательно ясно, что компоненты AWT хоть и работают, но обеспечить более или менее приличный интерфейс не могут, взоры обратились в сторону легковесных компонентов. Мы уже знаем, что легковесные компоненты не зависят от платформы и полностью находятся во власти Java-приложения. Это прекрасно, но здесь есть ловушка. Кто-то должен обеспечить им нужный внешний вид и взаимодействие с пользователем.

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

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

Они так выглядели и на Unix, и на Mac, и работать с ними пользователям этих систем было крайне неудобно.

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

Архитектура MVC В далеком (по меркам компьютерной индустрии) 1980 году появилась очередная версия объектноориентированного языка Smalltalk, названная Smalltalk-80. В этой версии возникла архитектура, предназначенная для создания легко расширяемых и настраиваемых пользовательских интерфейсов.

Эту архитектуру назвали модель — вид — контроллер (Model/View/Controller, MVC). По сути дела, появление в Smalltalk данной архитектуры привело к возникновению пользовательского интерфейса таким, каким мы его знаем сегодня, ведь именно тогда родились основные концепции и внешний вид большинства известных компонентов. Идея этих компонентов затем была использована в Macintosh, после чего перешла к многочисленным последователям Macintosh. Несмотря на то что с момента появления MVC прошло уже немало времени, эта архитектура остается одним из самых удачных объектно-ориентированных решений и поэтому часто используется и сегодня. Как нетрудно догадаться по названию, MVC состоит из трех частей.

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

Вид (view) выводит данные на экран для представления их пользователю. Отделение вида от данных позволяет представлять одни и те же данные совершенно разными способами.

Например, текст формата HTML (Hypertext Markup Language — гипертекстовый язык разметки) можно вывести в разном виде: можно провести разметку документа, разместить изображения и ссылки, использовать различные шрифты, а можно показать HTML-документ как код, который состоит из набора тегов и текста среди них. Между тем данные для этих разных видов требуются одни и те же (текст формата HTML). Вспоминая пример с раскрывающимся списком, можно сказать, что он является видом, представляющим на экране набор элементов. Данные раскрывающегося списка можно было бы представить и в другом виде, например в таблице.

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

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

Рисунок 1.3. Взаимодействия между моделью, видом и контроллером Пользователь взаимодействует с программой, совершая различные действия (нажимая клавиши, перемещая мышь, щелкая ее кнопками и т. п.); информация о его действиях поступает в контроллер.

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

Не удивляйтесь, контроллер может взаимодействовать и с моделью, и с видом, и сразу с обоими. Как мы увидим далее, контроллер — на самом деле довольно запутанная часть MVC и поэтому от него зачастую просто-напросто избавляются.

Механизм оповещения, использованный в MVC, — это не что иное, как шаблон проектирования под названием «наблюдатель»

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

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

Очень сильной стороной архитектуры MVC является также ее динамичность: никто не запрещает вам менять виды, контроллеры и модели прямо во время работы программы. Одним словом, архитектура MVC совсем не тривиальна, и возможности ее действительно велики.



Pages:     || 2 | 3 | 4 | 5 |
Похожие работы:

«Программа дисциплины Компьютерные технологии в биогеографии и экологии Автор: с.н.с. В.Ю.Румянцев Цель освоения дисциплины: формирование у магистрантов знаний, навыков и умений, необходимых и достаточных для картографического анализа и представления биогеографических и экологических данных (БЭД) – с использованием современных геоинформационных (и других компьютерных) технологий. Задачи - Формирование представлений о возможных способах организации и анализа БЭД для целей картографирования...»

«\ql Приказ Минобрнауки России от 23.01.2014 N 36 Об утверждении Порядка приема на обучение по образовательным программам среднего профессионального образования (Зарегистрировано в Минюсте России 06.03.2014 N 31529) Документ предоставлен КонсультантПлюс www.consultant.ru Дата сохранения: 23.05.2014 Приказ Минобрнауки России от 23.01.2014 N 36 Документ предоставлен КонсультантПлюс Об утверждении Порядка приема на обучение по образовательным программам среднего профессионального образования Дата...»

«Штрафы за превышение коэффициента независимости судей более чем на 45 % Азбука танца.Зима-2014 02.02.2014 - 02.02.2014, Кемерово, ДЮЦ-ОКСДЮСШОР №2 Место Процент штрафов Штрафов Пар Судья % М. Пара Город / Клуб Группа Мамалыга Татьяна 1 0% 0 13 Кемерово, Вторая Якимов Павел 1 0% 0 17 Новокузнецк, Всероссийская Никульникова Ольга 3 2,44% 3 123 Новосибирск, Всероссийская Созвездие, Новокузнецк Юниоры-2 + Юниоры-1 (Европейская программа) (E + D к 56,8 15 Ляховец - Казанина Миллениум Денс-ОКСДЮСШОР...»

«Министерство образования и науки Астраханской области Г АОУ АО В ПО А с т р а х а н с к и й и н ж е н е р н о - с т р о и т е л ь н ы й и н с т и т у т УТВЕРЖДАЮ Первый проректор Золина Т.В._ _ _201 г. РАБОЧАЯ ПРОГРАММА Наименование дисциплины Религиоведение и культовые сооружения По направлению подготовки 270300 Дизайн архитектурной среды По профилю подготовки Проектирование городской среды, Кафедра ДРР Квалификация (степень) выпускника бакалавр Астрахань — Разработчики: Доцент Бондарева...»

«Муниципальное общеобразовательное учреждение средняя общеобразовательная школа с углубленным изучением отдельных предметов №68 г. Липецка РАССМОТРЕНО УТВЕРЖДАЮ: На заседании МО Директор МБОУ СОШ № Протокол № А.А. Асютина от _20 13_г. Приказ №_ _20_г. Рабочая программа учебного курса Биология 9 В класс Учитель Фетисова О.А. Липецк Пояснительная записка Рабочая программа составлена на основе Федерального Государственного стандарта. Программа основного общего образования по биологии для 9 класса...»

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

«Министерство образования и науки Российской Федерации Федеральное государственное автономное образовательное учреждение высшего профессионального образования СИБИРСКИЙ ФЕДЕРАЛЬНЫЙ УНИВЕРСИТЕТ УТВЕРЖДАЮ Председатель приёмной комиссии Е.А.Ваганов 31 января 2014 г. ПРОГРАММА вступительного испытания в магистратуру в форме письменного экзамена Направление 38.04.01 Экономика Красноярск 20 Содержание программы (по дисциплине Экономическая теория) 1. микроэкономика 2. макроэкономика 3. национальная...»

«1 ПОЯСНИТЕЛЬНАЯ ЗАПИСКА Рабочая программа по химии составлена в соответствии с федеральным компонентом государственного стандарта среднего (полного) общего образования (базовый уровень), одобренным совместным решением коллегии Минобразования России и Президиума РАО от 23.12.2003 г. № 21/12 и утвержденным приказом Минобрнауки РФ от 05.03.2004 г. № 1089 и примерной программы среднего (полного) общего образования (базовый уровень) (письмо Департамента государственной политики в образовании...»

«МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ федеральное государственное бюджетное образовательное учреждение высшего профессионального образования Уральский государственный горный университет Утверждаю: Проректор по УМК С.Г.Фролов __ 20_ г. ОСНОВНАЯ ОБРАЗОВАТЕЛЬНАЯ ПРОГРАММА ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ ПО НАПРАВЛЕНИЮ ПОДГОТОВКИ 130101.65 Прикладная геология Специализация: Геология нефти и газа Квалификация (степень) выпускника: специалист Нормативный срок обучения: 5 лет...»

«Приложение Б21 Межрегиональный отраслевой ресурсный центр Интеграл Северо-Кавказского федерального округа Государственное бюджетное образовательное учреждение среднего профессионального образования Региональный многопрофильный колледж г. Ставрополь ПРОГРАММА ПРОФЕССИОНАЛЬНОГО МОДУЛЯ Подготовка и осуществление процесса контроля состояния электроустановок с использованием современных аппаратов и приборов по профессии начального профессионального образования 140446.03 Электромонтер по ремонту и...»

«2 Содержание 3 1. Общие положения 1.1. Основная образовательная программа (ООП) магистратуры (магистерская программа) 1.2. Нормативные документы для разработки магистерской программы 3 1.3. Общая характеристика магистерской программы 4 1.4 Требования к уровню подготовки, необходимому для освоения магистерской программы 2. Характеристика профессиональной деятельности выпускника магистерской программы 2.1. Область профессиональной деятельности выпускника 8 2.2. Объекты профессиональной...»

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

«Рабочая программа Ф ТПУ 7.1-21/01 учебной дисциплины ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ Государственное образовательное учреждение высшего профессионального образования ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ УТВЕРЖДАЮ Декан ГФ _ В.Г. Рубанов _2004 г. ОСНОВЫ ДЕЛОВОГО АДМИНИСТРИРОВАНИЯ Рабочая программа (специальность 350700 Реклама) Учебный план набора 2004 года (курс – 2, семестр – 4) Распределение учебного времени: Лекции 17 час. Практические (семинарские) занятия 17 час. Всего аудиторных...»

«ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ САРАТОВСКАЯ ГОСУДАРСТВЕННАЯ ЮРИДИЧЕСКАЯ АКАДЕМИЯ УТВЕРЖДАЮ Первый проректор, проректор по учебной работе _С.Н. Туманов 22 июня2012 г. УЧЕБНО-МЕТОДИЧЕСКИЙ КОМПЛЕКС ПО ДИСЦИПЛИНЕ СПЕЦИАЛИЗАИИ ПРАВОТВОРЧЕСКАЯ ПОЛИТИКА по специальности 03050165 – Юриспруденция Разработчик: к.ю.н., доцент Нырков В.В. Саратов – 2012. Учебно-методический комплекс дисциплины специализации обсужден на заседании...»

«Приложение № к приказу №396 от 30.08.2013 г. МУНИЦИПАЛЬНОЕ АВТОНОМНОЕ ОБЩЕОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ЛИЦЕЙ №21 Рекомендована к утверждению Утверждена приказом МО учителей социально-гуманитарных наук №396 от 30.08.2013 г. 18.06.2013 г. протокол № 04 Руководитель МО Директор лицея /О.Ф. Петрова/ /В.В. Парамзин/ Рабочая программа основного общего образования учебного курса Основы экономики для 9 классов на 2013/2014 учебный год г. Тамбов - 2013 г. ПОЯСНИТЕЛЬНАЯ ЗАПИСКА Рабочая программа по основам...»

«ОКРУЖАЮЩИЙ МИР ПОЯСНИТЕЛЬНАЯ ЗАПИСКА Программа разработана на основе Федерального государственного образовательного стандарта начального общего образования, Концепции духовнонравственного развития и воспитания личности гражданина России, планируемых результатов начального общего образования. Изучение курса Окружающий мир в начальной школе направлено на достижение следующих целей: — формирование целостной картины мира и осознание места в нём человека на основе единства рационально-научного...»

«Учебно-познавательная программа для детей Я - ЧЕЛОВЕК Пособие для учителя (Рекомендуется для занятий с детьми 10 - 14 лет) Автор Ирина Царицон Редактор Евгений Новицкий Художник Евгения Царицон Компьютерная верстка Вадим Царицон Пособие разработано отделом детских программ Христианского научно-апологетического центра. www.ScienceAndApologetics.com Руководитель отдела детских программ Ирина Царицон [email protected] Симферополь 2010 2 СОДЕРЖАНИЕ стр. 3 Содержание стр. Вступление...»

«РУCCКИЙ ЯЗЫК В ЦEНТРE EВРOПЫ 4 ACCOЦИAЦИЯ РУCИCТOВ CЛOВAКИИ БAНCКA БИCТРИЦA 2001 РУCCКИЙ ЯЗЫК В ЦEНТРE EВРOПЫ 4 Мeждунaрoднaя рeдaкциoннaя кoллeгия Э. Кoллaрoвa (Cлoвaкия) глaвный рeдaктoр A. Л. Бeрдичeвcкий (Aвcтрия) Л. Л. Вoxминa (Вeнгрия) oтвeтcтвeнный рeдaктoр Я. Гeнцeль (Пoльшa) И. Пocпишил (Чexия) Л. Риc (Чexия) A. Чeрвeняк (Cлoвaкия) Бaнcкa Биcтрицa 2001 Aдрec рeдaкции: Кaфeдрa руcиcтики (AРC) Фaкультeт гумaнитaрныx нaук Унивeрcитeт имeни М. Бeлa Тaйoвcкoгo 40 974 01 Бaнcкa Биcтрицa...»

«МИНИСТЕРСТВО СЕЛЬСКОГО ХОЗЯЙСТВА РОССИЙСКОЙ ФЕДЕРАЦИИ Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования КУБАНСКИЙ ГОСУДАРСТВЕННЫЙ АГРАРНЫЙ УНИВЕРСИТЕТ АННОТАЦИЯ РАБОЧЕЙ ПРОГРАММЫ по дисциплине: ОПД. В1 Ветеринарно-санитарная экспертиза кормов и кормовых добавок (индекс и наименование дисциплины) Направление Ветеринарноподготовки санитарная экспертиза Рабочая программа Ветеринарно-санитарная экспертиза Квалификация Ветеринарно-санитарный врач...»

«Муниципальное бюджетное общеобразовательное учреждение Средняя общеобразовательная школа c. Волково Чернянского района Белгородской области. Утверждаю: Согласовано Согласовано Рассмотрено Руководитель МО Заместитель директора На заседании Директор МБОУ СОШ школы по УВР МБОУ педагогического совета с. Волково Шуваева Ю.А. СОШ с. Волково Протокол № _ от Приболовец Протокол № _ от Дробышева О.М. _2013 г. А.П. _2013 г. Приказ № _ от 2013 г. 2013 г. РАБОЧАЯ ПРОГРАММА по предмету Основы религиозных...»






 
2014 www.av.disus.ru - «Бесплатная электронная библиотека - Авторефераты, Диссертации, Монографии, Программы»

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