| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml"> |
| <head> |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8"> |
| <!-- -*- xhtml -*- --> |
| <title>Руководство по созданию приложения для чтения каналов на платформе NetBeans 6.0</title> |
| <link rel="stylesheet" type="text/css" href="../../../netbeans.css"> |
| <meta name="AUDIENCE" content="NBUSER"> |
| <meta name="TYPE" content="ARTICLE"> |
| <meta name="EXPIRES" content="N"> |
| <meta name="developer" content="geertjan.wielenga@sun.com"> |
| <meta name="indexed" content="y"> |
| <meta name="description" |
| content="FeedReader on 6.0."> |
| <!-- Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. --> |
| <!-- Use is subject to license terms.--> |
| </head> |
| <body> |
| <H1> |
| |
| Руководство по созданию приложения для чтения каналов на платформе NetBeans |
| |
| </H1> |
| |
| |
| <p> |
| Добро пожаловать в руководство по разработке приложений для чтения каналов на платформе NetBeans. Приложение для чтения каналов, создаваемое в настоящем руководстве, является простейшим обозревателем каналов RSS/Atom, моделируемых после запуска подключаемого модуля Sage для Mozilla Firefox. Он представляет собой дерево каналов с подузлами, отражающими отдельные сообщения каналов, которые могут быть открыты в обозревателе. |
| </p><p>Для иллюстрации конечного результата на рисунке показано приложение для чтения каналов, которое будет создано в этом руководстве, с сообщением из канала <a href="https://netbeans.org/rss-091.xml">NetBeans Highlights</a>:</P> |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-result.png" border="1"/> |
| </div> |
| |
| <p></p><p><b>Содержание</b></p> |
| |
| <img src="../../images/articles/60/netbeans-stamp60-61.gif" class="stamp" width="114" height="114" alt="Содержимое на этой странице относится к среде IDE NetBeans 6.1" title="Содержимое на этой странице относится к среде IDE NetBeans 6.1"> </p> |
| <ul class="toc"> |
| <li><A HREF="#knowledge" CLASS="XRef">Необходимые предварительные знания</A> |
| </li><li><A HREF="#setting" CLASS="XRef">Создание приложения</A> |
| </li><li><A HREF="#creating" CLASS="XRef">Создание окна приложения для чтения каналов</A> |
| </li><li><A HREF="#running" CLASS="XRef">Выполнение приложения</A> |
| </li><li><A HREF="#adding" CLASS="XRef">Добавление кода к приложению</A> |
| </li><li><A HREF="#branding" CLASS="XRef">Выбор стиля для приложения</A> |
| </li><li><A HREF="#distributing" CLASS="XRef">Подготовка дистрибутива приложения</A> |
| </li></ul> |
| |
| <p><b>Для работы с этим руководством требуется программное обеспечение и ресурсы, перечисленные в следующей таблице. </b></p> |
| |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Программное обеспечение или ресурс</th> |
| <th class="tblheader" scope="col">Требуемая версия</th> |
| </tr> |
| <tr> |
| <td class="tbltd1">Среда IDE NetBeans</td> |
| <td class="tbltd1">версия <a href="http://download.netbeans.org/netbeans/6.1/final/">версия 6.1</a> или<br> |
| версия 6.0</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">Комплект для разработчика на языке Java (JDK)</td> |
| <td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">версия 6</a> или<br> |
| версия 5</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">Служебные программы RSS и atOM (<A HREF="https://rome.dev.java.net/" CLASS="URL">загрузить</A></tt></td> |
| <td class="tbltd1"></td> |
| </tr> |
| <tr> |
| <td class="tbltd1">Rome Fetcher (<A HREF="http://wiki.java.net/bin/view/Javawsxml/RomeFetcherRelease06" CLASS="URL">загрузить</A></tt>)</td> |
| <td class="tbltd1"></td> |
| </tr> |
| <tr> |
| <td class="tbltd1">JDom (<A HREF="http://jdom.org/downloads/index.html" CLASS="URL">загрузить</A></tt>)</td> |
| <td class="tbltd1"></td> |
| </tr> |
| <tr> |
| <td class="tbltd1">Значок "FeedReader" и экран заставки (<A HREF="https://netbeans.org/files/documents/4/550/feedreader-images.zip" CLASS="URL">загрузить</A></tt>).</td> |
| <td class="tbltd1"></td> |
| </tr> |
| </tbody> |
| </table> |
| |
| |
| |
| <h2><a name="knowledge"></a> Необходимые предварительные знания</H2> |
| <p>Для работы с настоящим руководством не требуются знания в области разработки на платформе NetBeans. Опыт программирования на Java может быть полезен, но его наличие не является обязательным условием. Тем не менее, перед работой с руководством желательно ознакомиться со следующими документами, содержащими рекомендуемую базовую информацию: |
| |
| </p><ul> |
| <li><a href="https://platform.netbeans.org/tutorials/60/nbm-feedreader_background.html">Подготовка к созданию приложения для чтения каналов</a>. Этот документ содержит базовую информацию, с которой рекомендуется ознакомиться перед началом работы с данным руководством. В нем представлены концептуальные основы всех операций, описываемых в руководстве. В этом документе также приведены указания по получению исходного кода примера, который будет разработан по мере изучения настоящего руководства.</li> |
| <li><a href="../61/nbm-htmleditor_ru.html">Руководство по началу работы с платформой NetBeans</a>. Это краткое руководство содержит описание всего процесса создания функционально насыщенного клиентского приложения на платформе NetBeans. В нем рассматриваются основные этапы и средства разработки, при помощи которых в руководстве создается редактор HTML.</li> |
| </ul> |
| |
| <h2><a name="setting"></a> Создание приложения</H2> |
| <p> |
| Создание приложения в среде IDE NetBeans начинается с создания большого количества файлов, используемых в качестве основы для приложения. Например, в среду IDE входит мастер проектов модулей, мастер проектов пакетов модулей и мастер модулей-оберток библиотек, применяемые для создания всех базовых файлов, необходимых для модулей и приложений, основанных на платформе NetBeans.</P> |
| <UL> |
| <li> |
| <b>Проект пакета модулей.</b> Проект, в рамках которого группируются проекты модулей и проекты модулей-оберток библиотек, зависящие друг от друга, которые могут развертываться совместно одним блоком.</li> |
| <li> |
| <b>Проект модуля-обертки библиотеки.</b> Проект, устанавливающий путь к классам для архива JAR библиотеки и экспортирующий некоторые или все пакеты архива JAR из модуля в виде общедоступных пакетов.</li> |
| <li> |
| <b>Проект модуля.</b> Проект, используемый для внедрения функциональных возможностей, бизнес-логики и интерфейса пользователя модуля или приложения на базе платформы NetBeans.</li> |
| </UL> |
| <h3> |
| Создание проекта пакета модулей</H3> |
| <ol> |
| <li> |
| Выберите "File > New Project" (Ctrl-Shift-N). В области "Categories" выберите "NetBeans Modules". В области "Projects" выберите "Module Suite Project". Экран должен выглядеть следующим образом:</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-suite-wiz.png" border="1"/> |
| </p><p>Нажмите кнопку "Next".</p></li> |
| <li> |
| На экране "Name and Location" введите <tt> feedreader-suite</tt> в поле "Project Name". В поле "Project Location" укажите любой каталог на компьютере. Экран должен выглядеть следующим образом:</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-suite-wiz2.png" border="1"/> |
| |
| </p><p>Нажмите кнопку "Finish".</p></li> |
| </ol> |
| |
| <p>В среде IDE создается проект <tt> feedreader-suite</tt>, который отображается в окне "Projects":</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-suite.png" border="1"/> |
| |
| |
| </p><p>Этот проект будет содержать проект модуля и проекты модулей-оберток библиотек, которые будут созданы в следующих подразделах. </P> |
| |
| <h3> |
| Обертывание библиотек</H3> |
| |
| Все приложение для чтения каналов может быть выполнено как отдельный модуль. Однако этому приложению требуются библиотеки Rome, Rome Fetcher и JDom:</P> |
| <UL> |
| <li> |
| <b>Rome.</b> Используется для чтения каналов RSS и Atom при помощи очень простого интерфейса API. </li> |
| <li> |
| <b>Rome Fetcher.</b> Позволяет получать каналы посредством HTTP. </li> |
| <li> |
| <b>JDom.</b> Представляет собой интерфейс API для синтаксического анализа XML. Необходимость наличия этой библиотеки для приложения для чтения каналов обусловлена лишь тем, что она используется библиотекой Rome.</li> |
| </UL> |
| |
| Позднее при необходимости расширить приложение для чтения каналов путем добавления большего числа модулей, которые могут использовать эти библиотеки, целесообразно установить их зависимость от модулей библиотек, а не от всего приложения для чтения каналов. Кроме того, библиотечные модули могут быть "автоматически загружаемыми", т.е. их загрузка будет осуществляться средой NetBeans только в случае необходимости. До этого момента ресурсы памяти на этапе выполнения расходоваться не будут.</P> |
| <ol> |
| <li>Щелкните правой кнопкой мыши узел "Modules" в проекте пакета модулей в окне "Projects", как показано ниже, и выберите пункт "Add New Library":</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-add-lib0.png" border="1"/> |
| </p><p>После этого на экране должно отображаться следующее:</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-lib-wiz.png" border="1"/> |
| |
| </p></li><li> |
| На экране "Select Library", показанном выше, найдите папку, в которую была загружена библиотека JDom, и затем выберите <tt> jdom.jar</tt> и <tt> LICENSE.txt</tt>. Нажмите кнопку "Next".</li> |
| <li> |
| На экране "Name and Location" примите все значения по умолчанию. Экран должен выглядеть следующим образом:</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-lib-wiz3.png" border="1"/> |
| |
| |
| </p><p><b>Примечание:</b> Модуль-обертка библиотеки будет сохранен в проекте пакета модулей. Он также может быть сохранен в другом месте, однако в целях управления версиями рекомендуется разместить его в проекте пакета модулей. Поэтому в раскрывающемся списке "Add to Module Suite" выбирается проект пакета модулей <tt> feedreader-suite</tt>.</p> |
| <p>Нажмите кнопку "Next".</p></li> |
| <li> |
| На экране "Basic Module Configuration" примите все значения по умолчанию. Экран должен выглядеть следующим образом:</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-lib-wiz2.png" border="1"/> |
| |
| |
| |
| |
| </p><p>Нажмите кнопку "Finish".</p> |
| <p>Новый модуль-обертка библиотеки открывается в среде IDE и будет отображен в окне "Projects". Окно "Projects" должно выглядеть следующим образом:</P> |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-lib-wiz4.png" border="1"> |
| </div></li> |
| <li> |
| Вернитесь к действию 1 этого раздела и создайте модуль-обертку для библиотеки Rome. Примите все значения по умолчанию.</li> |
| <li> |
| Вернитесь к действию 1 этого раздела и создайте модуль-обертку для библиотеки Rome Fetcher. Примите все значения по умолчанию.</li> |
| </ol> |
| |
| <p>В этом разделе был создан проект пакета модулей с тремя модулями-обертками библиотек, содержащий большое количество удобных классов Java, которые могут использоваться по мере изучения руководства. |
| |
| |
| </p><h3> |
| Создание проекта модуля </H3> |
| <p>В этом разделе создается проект для реализации функциональных возможностей, которые должны предоставляться приложением. В проекте будут использоваться классы, доступные благодаря применению модулей-оберток библиотек, созданных в предыдущем разделе.</p> |
| <ol> |
| <li> |
| Щелкните правой кнопкой мыши узел "Modules" в проекте пакета модулей в окне "Projects", как показано ниже, и выберите "Add New":</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-module-project.png" border="1"/> |
| </p><p>После этого на экране должно отображаться следующее:</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-module-wiz.png" border="1"/> |
| </p></li> |
| <li> |
| На экране "Name and Location", показанном выше, введите <tt> FeedReader</tt> в поле "Project Name". Примите все значения по умолчанию. Нажмите кнопку "Next". |
| </li><li> |
| На экране "Basic Module Configuration" замените значение <tt> yourorghere</tt> в поле "Code Name Base" на <tt> myorg</tt>, чтобы основа названия кода выглядела как <tt> org.myorg.feedreader.</tt> Введите <tt>FeedReader</tt> в поле "Module Display Name". Не изменяйте местоположение пакета локализации и файла layer.xml для их сохранения в пакете с именем <tt> org/myorg/feedreader.</tt> Экран должен выглядеть следующим образом:</p> |
| <p><IMG SRC="../../images/tutorials/feedreader/60-module-wiz2.png" border="1"/> |
| </p><p></p><p> |
| Нажмите кнопку "Finish".</p></li> |
| </ol> |
| <p> |
| Средой IDE будет создан проект "FeedReader". Проект содержит все исходные файлы модуля и метаданные проекта, например, сценарий сборки Ant. Проект открывается в среде IDE. Логическую структуру проекта можно просмотреть в окне "Projects" (Ctrl-1), а структуру файлов – в окне "Files" (Ctrl-2). Теперь окно "Projects" должно выглядеть следующим образом:</P> |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-module.png" border="1"> |
| </div> |
| |
| <p></p><p>Создана структура исходных файлов нового приложения. В следующем разделе мы приступим к добавлению кода. |
| |
| </p><h2><a name="creating"></a> Создание окна приложения для чтения каналов </H2> |
| <p> |
| В этом разделе при помощи мастера оконных элементов генерируются файлы, необходимые для создания пользовательского элемента, а также действия для его вызова. Мастер также регистрирует действие как пункт меню в файле настройки <tt> layer.xml </tt> и добавляет значения, необходимые для многократного использования оконного элемента. После завершения этого раздела демонстрируется процесс использования некоторых файлов, созданных мастером оконных элементов.</P> |
| <ol> |
| <li> |
| Щелкните правой кнопкой мыши узел проекта <tt> FeedReader</tt> и выберите "New > Other". В области "Categories" выберите "Module Development". В области "File Types" выберите "Window Component", как показано ниже:</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-windowcomp-wiz.png" border="1"> |
| </div> |
| |
| <p> |
| </p><p>Нажмите кнопку "Next".</p></li> |
| <li> |
| На экране "Basic Settings" выберите <tt> explorer</tt> в раскрывающемся списке и установите флажок "Open on Application Start", как показано ниже:</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-windowcomp-wiz2.png" border="1"> |
| </div> |
| |
| <p></p><p>Нажмите кнопку "Next".</p></li> |
| <li> |
| На экране "Name and Location" введите "Feed" в поле "Class Name Prefix" и укажите местоположение сохраненного файла <tt> rss16.gif (<IMG SRC="../../images/tutorials/feedreader/rss16.gif" />).</tt> Файл GIF будет показан в пункте меню, инициирующем действие. Экран должен выглядеть следующим образом:</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-windowcomp-wiz3.png" border="1"> |
| </div> |
| |
| |
| <p></p><p>Нажмите кнопку "Finish".</p></li> |
| </ol> |
| <p>Окно "Projects" должно выглядеть следующим образом: |
| |
| </p><div> |
| <IMG SRC="../../images/tutorials/feedreader/60-windowcomp.png" border="1"> |
| </div> |
| |
| |
| <p></p><p>В среде IDE созданы следующие новые файлы:</P> |
| <UL> |
| <li> |
| <tt> FeedAction.java.</tt> Определяет действие, отображаемое в меню "Window" с текстом "Open Feed Window" и изображением <tt> rss16.gif</tt> (<IMG SRC="../../images/tutorials/feedreader/rss16.gif" />). Оно используется для открытия окна "Feed Window". </li> |
| <li> |
| <tt> FeedTopComponent.java.</tt> Определяет окно "Feed Window". </li> |
| <li> |
| <tt> FeedTopComponentSettings.xml.</tt> Используется для определения всех интерфейсов функционально насыщенного клиентского приложения <tt> org.myorg.feedreader</tt>. Обеспечивает простой поиск экземпляров без необходимости создания каждого из них; позволяет избежать необходимости в загрузке классов или создании объектов и, тем самым, повышает производительность. Регистрируется в папке <tt> Windows2/Components</tt> файла <tt> layer.xml</tt>.</li> |
| <li> |
| <tt> FeedTopComponentWstcref.xml.</tt> Используется для определения ссылки на элемент; дает возможность присвоения элемента более чем одному режиму и регистрируется в папке <tt>Windows2/Modes</tt> файла <tt> layer.xml</tt>.</li> |
| </UL> |
| |
| Средой IDE были изменены следующие существующие файлы:</P> |
| <UL> |
| <li> |
| <b></b> <A NAME="project.xml"></A><tt> project.xml.</tt> Добавлены две зависимости модулей, <tt> Utilities API </tt> (щелкните <A HREF="http://bits.netbeans.org/dev/javadoc/org-openide-util/overview-summary.html" CLASS="URL">здесь</A></tt> для просмотра документации Javadoc) и <tt> Window System API </tt> (щелкните <A HREF="http://bits.netbeans.org/dev/javadoc/org-openide-windows/overview-summary.html" CLASS="URL">здесь</A></tt> для просмотра документации Javadoc).</li> |
| <li> |
| <tt> Bundle.properties.</tt> <A NAME="Bundle.properties"></A> Добавлены три пары "ключ-значение":<br> |
| |
| <ul> |
| <li><tt>CTL_FeedAction.</tt> Позволяет локализовать текст пункта меню, определенного в <tt>FeedAction.java</tt>. |
| </li><li><tt>CTL_FeedTopComponent.</tt> Позволяет локализовать текст <tt>FeedTopComponent.java</tt>. |
| </li><li><tt>HINT_FeedTopComponent.</tt> Позволяет локализовать всплывающую подсказку <tt>FeedTopComponent.java</tt>. |
| </li></ul> |
| |
| </li> |
| </UL> |
| |
| <p>Итак, в файл <tt>layer.xml</tt> добавлены три регистрационных записи.</li> |
| |
| </p><p> |
| Эти записи в файле <tt> layer.xml</tt> предназначены для следующего:</P> |
| <UL> |
| <li> |
| <tt> <Actions></tt> |
| <br> |
| Регистрирует действие в качестве действия в папке "Window".</li> |
| <li> |
| <tt> <Menu></tt> |
| <br> |
| Регистрирует действие в качестве пункта в меню "Window".</li> |
| <li> |
| <tt> <Windows2> <br> |
| </tt> Регистрирует файл <tt>FeedTopComponentSettings.xml</tt>, используемый для поиска оконного элемента. Регистрирует ссылочный файл элемента <tt>FeedTopComponentWstcref.xml</tt> в области "explorer". |
| <br> |
| </tt> |
| </li> |
| </UL> |
| <h2><a name="running"></a> Выполнение приложения</H2> |
| <p> |
| Приложение, для которого не была написана ни одна строка кода, уже может быть запущено. Попытка его использования приведет к развертыванию модулей на платформе NetBeans и к последующей проверки корректности отображения пустого окна "Feed Window".</P> |
| |
| <ol> |
| <li>Сначала удалим все модули, определяющие среду IDE NetBeans, которые не потребуются в приложении для чтения каналов. Щелкните правой кнопкой мыши проект <tt>feedreader-suite</tt>, выберите "Properties", а затем щелкните пункт "Libraries" в диалоговом окне "Project Properties".</p> |
| |
| <p>Появится список "кластеров". Каждый кластер представляет собой ряд связанных модулей. Единственным необходимым кластером является кластер "platform", поэтому отмените выбор всех других кластеров и оставьте только один флажок напротив кластера "platform":</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-runapp4.png" border="1"> |
| </div> |
| |
| <p></p><p>Разверните кластер "platform" и просмотрите содержащиеся в нем модули: |
| </p><div> |
| <IMG SRC="../../images/tutorials/feedreader/60-runapp5.png" border="1"> |
| </div> |
| |
| <p></p><p>Модули платформы обеспечивают общую платформу приложений Swing. Так как был выбран кластер "platform", создавать "технический" код для инфраструктуры приложения, например, строки меню, системы управления окнами и функциональности для начальной загрузки, не потребуется. |
| |
| |
| </p><p></p><p>Нажмите кнопку "OK". |
| |
| </p></li><li>В окне "Projects" щелкните правой кнопкой мыши проект <tt> feedreader-suite</tt> и выберите "Clean and Build All". |
| |
| </li><li>В окне "Projects" щелкните правой кнопкой мыши проект <tt> feedreader-suite</tt> и выберите "Run", как показано ниже:</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-runapp.png" border="1"> |
| </div> |
| </li></ol> |
| |
| <p> |
| </p><p>Приложение будет запущено. На экране появится заставка. После этого будет открыто приложение и появится новое окно "Feed Window", представляющее собой окно обозревателя, показанное ниже:</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-runapp2.png" border="1"> |
| </div> |
| |
| <p></p><p><b>Примечание:</b> В настоящий момент в состав приложения входят следующие модули: |
| </p><ul> |
| <li>Модули, поставляемые с платформой NetBeans и предназначенные для загрузки приложения, управления жизненным циклом и выполнения других операций, связанных с инфраструктурой. |
| </li><li>Три модуля-обертки библиотек, созданные в рамках этого руководства. |
| </li><li>Модуль функциональных возможностей чтения каналов, созданный в рамках этого руководства и предназначенный для вывода окна "Feed Window". |
| </li></ul> |
| |
| |
| <p></p><p>В меню "Window" приложения должен появиться новый пункт (см. ниже), используемый для открытия окна "Feed Window" в случае, если оно закрыто:</li> |
| |
| |
| </p><div> |
| <IMG SRC="../../images/tutorials/feedreader/60-runapp3.png" border="1"> |
| </div> |
| <p> |
| </p><p>Итак, нами было создано готовое приложение без написания какого-либо кода. Оно не содержит множества возможностей, однако его инфраструктура существует и функционирует так, как ожидалось. В следующих разделах мы приступим к добавлению кода в приложение при помощи интерфейсов API среды NetBeans. |
| |
| </p><h2><a name="adding"></a> Добавление кода к приложению</H2> |
| <p> |
| После создания основы для приложения можно приступить к добавлению собственного кода. Перед этим для приложения необходимо определить зависимости. Зависимости – это модули, предоставляющие интерфейсы API NetBeans, которые будут расширены или реализованы. После этого при помощи мастера создания файла и редактора исходного кода будут созданы и закодированы классы, добавляемые в приложение для чтения каналов. |
| </p><h3> |
| Определение зависимостей для приложения</H3> |
| |
| Необходимо создать подклассы нескольких классов, принадлежащих интерфейсам API среды NetBeans. Классы относятся к модулям, которые должны быть объявлены как зависимости приложения для чтения каналов. Для этой цели используйте диалоговое окно "Project Properties", как показано ниже.</P> |
| <ol> |
| <li> |
| В окне "Projects" щелкните правой кнопкой мыши проект <tt> FeedReader</tt> и выберите "Properties". В диалоговом окне "Project Properties" выберите "Libraries". Обратите внимание, что некоторые показанные ниже интерфейсы API уже были объявлены в качестве зависимостей (область "Module Dependencies"):</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-add-lib1.png" border="1"> |
| </div> |
| |
| <p> |
| </p><p>Показанные выше регистрационные записи библиотек были созданы ранее при работе с данным руководством с использованием мастера оконных элементов.</p></li> |
| <li> |
| Нажмите кнопку "Add Dependency".</li> |
| <li> |
| Добавьте следующие интерфейсы API: |
| <pre class="examplecode"> |
| Actions API |
| Datasystems API |
| Dialogs API |
| Explorer and Property Sheet API |
| File System API |
| Nodes API |
| rome |
| rome-fetcher</pre> |
| |
| |
| <p>Экран должен выглядеть следующим образом:</p> |
| |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-add-lib2.png" border="1"> |
| </div> |
| |
| |
| <p></p><p>Нажмите кнопку "OK" для закрытия диалогового окна "Project Properties". </p></li> |
| |
| |
| <li>Разверните узел "Libraries" проекта <tt>FeedReader</tt> и обратите внимание на список модулей, доступных в этом проекте:</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-add-lib5.png" border="1"> |
| </div> |
| |
| </li></ol> |
| |
| <h3> |
| Установка зависимостей между модулями-обертками библиотек</h3> |
| |
| <p>После определения используемых зависимостей модулей интерфейсов API среды NetBeans можно установить зависимости между модулями-обертками библиотек. Например, в файле JAR библиотеки Rome используются классы из файла JAR библиотеки JDom. Теперь, когда они обернуты в отдельных модулях-обертках библиотек, необходимо определить связь между файлами JAR в диалоговом окне "Project Properties" модуля-обертки библиотеки.</p> |
| |
| <ol> |
| <li> |
| Сначала установите зависимость библиотеки Rome от библиотеки JDom. Щелкните правой кнопкой мыши проект модуля-обертки библиотеки Rome в окне "Projects" и выберите "Properties". В диалоговом окне "Project Properties" выберите "Libraries" и затем "Add Dependency". Добавьте зависимости <tt>jdom</tt>. Экран должен выглядеть следующим образом:</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-add-lib3.png" border="1"> |
| </div> |
| |
| <p></p><p>Нажмите кнопку "OK" для закрытия диалогового окна "Project Properties".</p></li> |
| <li> |
| Теперь, после установки зависимости библиотеки Rome Fetcher от библиотек Rome и JDom одновременно, необходимо создать зависимость Rome Fetcher от Rome, показанную ниже:</p> |
| |
| <div> |
| <IMG SRC="../../images/tutorials/feedreader/60-add-lib4.png" border="1"> |
| </div> |
| |
| |
| <p></p><p>Поскольку библиотека Rome уже зависит от JDom, определять зависимость библиотеки Rome Fetcher от JDom не требуется. </p></li> |
| </ol> |
| <h3> |
| Создание папки "RssFeeds"</H3> |
| |
| <p>Для добавления папки в файл <tt>layer.xml</tt> будет использоваться интерфейс пользователя среды IDE. Папка будет содержать объекты канала RSS. Затем к объекту <tt> FeedTopComponent.java</tt>, созданному в мастере оконных элементов, будет добавлен код для просмотра содержимого этой папки.</P> |
| <ol> |
| <li> |
| В окне "Projects" разверните узел проекта <tt> FeedReader</tt>, а затем разверните узлы "Important Files" и "XML Layer". На экране должны быть представлены следующие узлы:<p></p><p> |
| </p><ul><li><tt> <this layer>.</tt> Используется для вывода на экран папок, содержащихся в текущем модуле. Например, как видно на приведенном ниже рисунке, модуль "FeedReader" содержит папки с именами "Actions", "Menu" и "Windows2", ранее описанные в данном руководстве: |
| |
| <p></p><div> |
| <IMG SRC="../../images/tutorials/feedreader/60-feedfolder-1.png" border="1"> |
| </div> |
| |
| <p></p><p></p></li><li><tt> <this layer in context>. </tt> Используется для вывода на экран всех папок, доступных во всем приложении. Этот узел будет рассматриваться далее в настоящем руководстве.<br> |
| <br></li></ul> |
| </li> |
| <li> |
| Щелкните правой кнопкой мыши узел <tt> <this layer></tt> и выберите "New > Folder", как показано ниже: |
| |
| |
| <p></p><div> |
| <IMG SRC="../../images/tutorials/feedreader/60-feedfolder-2.png" border="1"> |
| </div> |
| |
| |
| </li> |
| <li> |
| Введите <tt> RssFeeds</tt> в диалоговом окне "New Folder". Нажмите кнопку "OK". Таким образом, была создана новая папка, показанная ниже: |
| |
| <p></p><div> |
| <IMG SRC="../../images/tutorials/feedreader/60-feedfolder-3.png" border="1"> |
| </div> |
| |
| |
| </li><li>Дважды щелкните узел файла <tt> layer.xml</tt> для его открытия в редакторе исходного кода. Обратите внимание на добавление следующей записи:<br> |
| <tt> |
| <br> |
| <folder name="RssFeeds"/></tt> |
| </li> |
| </ol> |
| <h3> |
| Создание объекта канала </H3> |
| |
| <p>Затем создайте простой элемент POJO, инкапсулирующий URL-адрес и связанный с ним канал Rome.</p> |
| <ol> |
| <li> |
| Щелкните правой кнопкой мыши узел проекта <tt> FeedReader</tt> и выберите "New > Java Class". Нажмите кнопку "Next". </li> |
| <li> |
| Присвойте классу имя <tt> Feed</tt> и выберите <tt> org.myorg.feedreader</tt> в раскрывающемся списке "Package". Нажмите кнопку "Finish".</li> |
| <li> |
| В редакторе исходного кода замените класс <tt> Feed</tt>, установленный по умолчанию, на следующий:</li> |
| </ol> |
| <pre class="examplecode">public class Feed implements Serializable { |
| |
| private static FeedFetcher s_feedFetcher |
| = new HttpURLFeedFetcher(HashMapFeedInfoCache.getInstance()); |
| private transient SyndFeed m_syndFeed; |
| private URL m_url; |
| private String m_name; |
| |
| protected Feed() { |
| } |
| |
| public Feed(String str) throws MalformedURLException { |
| m_url = new URL(str); |
| m_name = str; |
| } |
| |
| public URL getURL() { |
| return m_url; |
| } |
| |
| public SyndFeed getSyndFeed() throws IOException { |
| if (m_syndFeed == null) { |
| try { |
| m_syndFeed = s_feedFetcher.retrieveFeed(m_url); |
| if (m_syndFeed.getTitle() != null) { |
| m_name = m_syndFeed.getTitle(); |
| } |
| } catch (Exception ex) { |
| throw new IOException(ex.getMessage()); |
| } |
| } |
| return m_syndFeed; |
| } |
| |
| @Override |
| public String toString() { |
| return m_name; |
| } |
| |
| }</pre> |
| |
| Значительная часть кода подчеркнута, поскольку многие пакеты не были объявлены. Это будет выполнено в дальнейшем. </P> |
| |
| Для переформатирования файла и объявления его зависимостей выполните следующие действия:</P> |
| <ol> |
| <li> |
| Нажмите Alt-Shift-F для форматирования кода. </li> |
| <li> |
| Нажмите Ctrl-Shift-I и проверьте, что выбраны следующие операторы импорта: |
| |
| |
| <p></p><div> |
| <IMG SRC="../../images/tutorials/feedreader/60-imports.png" border="1"> |
| </div> |
| |
| |
| <p></p><p>Нажмите кнопку "OK", после чего в класс будут добавлены следующие операторы импорта: |
| |
| </p><pre class="examplecode">import com.sun.syndication.feed.synd.SyndFeed; |
| import com.sun.syndication.fetcher.FeedFetcher; |
| import com.sun.syndication.fetcher.impl.HashMapFeedInfoCache; |
| import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher; |
| import java.io.IOException; |
| import java.io.Serializable; |
| import java.net.MalformedURLException; |
| import java.net.URL;</pre> |
| </li> |
| </ol> |
| |
| Красное подчеркивание должно исчезнуть. В противном случае не выполняйте следующие действия, указанные в этом руководстве, до разрешения проблемы.</P> |
| <h3> |
| Добавление окна "Feed Window"</H3> |
| <ol> |
| <li> |
| Дважды щелкните элемент <tt> FeedTopComponent.java</tt> для его открытия в редакторе исходного кода.</li> |
| <li> |
| Введите строку <tt> implements ExplorerManager.Provider</tt> в конце объявления класса.</li> |
| <li> |
| Нажмите Alt-Enter, установив курсор на строке, и щелкните предложенное значение. Средой IDE будет добавлен оператор импорта для требуемого пакета <tt> org.openide.explorer.ExplorerManager</tt>.</li> |
| <li> |
| Снова нажмите Alt-Enter и щелкните предложенное значение. При этом будет реализован абстрактный метод <tt> getExplorerManager()</tt>. </li> |
| <li> |
| Введите <tt> return manager;</tt> в теле нового метода <tt> getExplorerManager() </tt>. Нажмите Alt-Enter, установив курсор на строку, после чего будет создано поле под названием <tt> manager</tt>. Замените определение по умолчанию на следующее: |
| <pre class="examplecode">private final ExplorerManager manager = new ExplorerManager();</pre> |
| </li> |
| <li> |
| Сразу после объявления поля на предыдущем этапе объявите этот класс:<br> |
| <pre class="examplecode">private final BeanTreeView view = new BeanTreeView();</pre> |
| </li> |
| <li> |
| После этого добавьте следующий код в конце конструктора:<br> |
| <pre class="examplecode">setLayout(new BorderLayout()); |
| add(view, BorderLayout.CENTER); |
| view.setRootVisible(true); |
| try { |
| manager.setRootContext(new RssNode.RootRssNode()); |
| } catch (DataObjectNotFoundException ex) { |
| ErrorManager.getDefault().notify(ex); |
| } |
| ActionMap map = getActionMap(); |
| map.put("delete", ExplorerUtils.actionDelete(manager, true)); |
| associateLookup(ExplorerUtils.createLookup(manager, map));</pre> |
| </li> |
| </ol> |
| |
| <p> |
| В настоящее время большая часть кода подчеркнута, поскольку соответствующие пакеты не были объявлены. Это будет выполнено в дальнейшем. </P> |
| <p> |
| Для переформатирования файла и объявления его зависимостей выполните следующие действия:</P> |
| <ol> |
| <li> |
| Нажмите Alt-Shift-F для форматирования кода. </li> |
| <li> |
| Нажмите Ctrl-Shift-I, выберите <tt>org.openide.ErrorManager</tt>, нажмите кнопку "OK", после чего под оператором пакета будет создано несколько операторов импорта. Теперь полный список операторов импорта должен выглядеть следующим образом: |
| |
| <pre class="examplecode">import java.awt.BorderLayout; |
| import java.io.Serializable; |
| import javax.swing.ActionMap; |
| import org.openide.ErrorManager; |
| import org.openide.explorer.ExplorerManager; |
| import org.openide.explorer.ExplorerUtils; |
| import org.openide.explorer.view.BeanTreeView; |
| import org.openide.loaders.DataObjectNotFoundException; |
| import org.openide.util.NbBundle; |
| import org.openide.util.RequestProcessor; |
| import org.openide.util.Utilities; |
| import org.openide.windows.TopComponent;</pre> |
| |
| </li> |
| <li> |
| Следует отметить, что строка <tt> manager.setRootContext(new RssNode.RootRssNode());</tt> по-прежнему подчеркнута красным цветом, поскольку элемент <tt> RssNode.java </tt> до сих пор не создан. Это будет выполнено в следующем подразделе. Прочие красные линии должны исчезнуть. В противном случае не выполняйте следующие действия, указанные в этом руководстве, до разрешения проблемы.</li> |
| </ol> |
| <h3> |
| Создание класса "RssNode"</H3> |
| |
| <p></p><p>Верхний узел приложения для чтения каналов обеспечивается классом "RssNode". Этот класс расширяет <tt><a href="http://bits.netbeans.org/dev/javadoc/org-openide-nodes/org/openide/nodes/FilterNode.html">FilterNode</a></tt>, используемый в качестве прокси для узла "RssFeeds". На этом этапе будет определено отображаемое имя и объявлены два пункта меню "Add" и "Add Folder", показанные ниже: |
| |
| </p><p></p><div> |
| <IMG SRC="../../images/tutorials/feedreader/60-actions.png" border="1"> |
| </div></p> |
| |
| <p>Для создания этого класса выполните следующие действия: |
| |
| </p><ol> |
| <li> |
| Создайте элемент <tt> RssNode.java</tt> в пакете <tt> org.myorg.feedreader</tt>.</li> |
| <li> |
| Замените класс по умолчанию на следующий:</li> |
| </ol> |
| <pre class="examplecode">public class RssNode extends FilterNode { |
| |
| public RssNode(Node folderNode) throws DataObjectNotFoundException { |
| super(folderNode, new RssFolderChildren(folderNode)); |
| } |
| |
| @Override |
| public Action[] getActions(boolean popup) { |
| |
| <b>//Объявление действий и переход к папке данных узла:</b> |
| DataFolder df = getLookup().lookup(DataFolder.class); |
| return new Action[]{ |
| new AddRssAction(df), |
| new AddFolderAction(df) |
| }; |
| |
| } |
| |
| public static class RootRssNode extends RssNode { |
| |
| <b>//Узел фильтра будет служить в качестве прокси для узла "RssFeeds", который здесь будет получен из пользовательского каталога NetBeans:</b> |
| public RootRssNode() throws DataObjectNotFoundException { |
| super(DataObject.find(Repository.getDefault().getDefaultFileSystem(). |
| getRoot().getFileObject("RssFeeds")).getNodeDelegate()); |
| } |
| |
| <b>//Определение отображаемого имени узла, относящегося к объединенному файлу, и ключа, который будет определен позже:</b> |
| @Override |
| public String getDisplayName() { |
| return NbBundle.getMessage(RssNode.class, "FN_title"); |
| } |
| |
| } |
| |
| }</pre> |
| |
| |
| </ol> |
| |
| <p>Некоторые строки кода, относящиеся к классу, по-прежнему подчеркиваются красным цветом, поскольку не были созданы действия и класс, определяющий нижестоящие узлы. |
| |
| |
| </p><h3> |
| Создание класса "RssFolderChildren"</H3> |
| |
| <p>Теперь обратимся к дочерним узлам узла "RSS/Atom Feeds". Дочерние элементы являются папками или каналами. Все это реализуется посредством кода, приведенного ниже. |
| |
| |
| </p><p>Для создания этого класса выполните следующие действия: |
| |
| |
| </p><ol> |
| <li> |
| Создайте элемент <tt> RssFolderChildren.java</tt> в пакете <tt> org.myorg.feedreader</tt>.</li> |
| <li> |
| Замените класс по умолчанию на следующий:</li> |
| </ol> |
| <pre class="examplecode">public class RssFolderChildren extends FilterNode.Children { |
| |
| RssFolderChildren(Node rssFolderNode) { |
| super(rssFolderNode); |
| } |
| |
| @Override |
| protected Node[] createNodes(Node key) { |
| Node n = key; |
| |
| <b>//При нахождении папки данных создается узел "RssNode", в противном случае осуществляется поиск канала и создание узла "OneFeedNode":</b> |
| try { |
| if (n.getLookup().lookup(DataFolder.class) != null) { |
| return new Node[]{new RssNode(n)}; |
| } else { |
| Feed feed = getFeed(n); |
| if (feed != null) { |
| return new Node[]{ |
| new OneFeedNode(n, feed.getSyndFeed()) |
| }; |
| } else { |
| // Лучшее из возможного |
| return new Node[]{new FilterNode(n)}; |
| } |
| } |
| } catch (IOException ioe) { |
| Exceptions.printStackTrace(ioe); |
| } catch (IntrospectionException exc) { |
| Exceptions.printStackTrace(exc); |
| } |
| // Другой тип узла (требует какой-то обработки) |
| return new Node[]{new FilterNode(n)}; |
| } |
| |
| /** Поиск канала */ |
| private static Feed getFeed(Node node) { |
| InstanceCookie ck = node.getCookie(InstanceCookie.class); |
| if (ck == null) { |
| throw new IllegalStateException("Bogus file in feeds folder: " + node.getLookup().lookup(FileObject.class)); |
| } |
| try { |
| return (Feed) ck.instanceCreate(); |
| } catch (ClassNotFoundException ex) { |
| Exceptions.printStackTrace(ex); |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| return null; |
| } |
| |
| }</pre> |
| </ol> |
| |
| |
| <p>Некоторые строки кода, относящегося к классу, подчеркнуты красным цветом, поскольку класс <tt>OneFeedNode</tt> до сих пор не создан. |
| |
| |
| </p><h3> |
| Создание класса "OneFeedNode"</H3> |
| |
| <p>В этом разделе рассматривается контейнер узлов статьей, проиллюстрированный ниже на примере узла "NetBeans Highlights": |
| |
| </p><p></p><div> |
| <IMG SRC="../../images/tutorials/feedreader/60-actions2.png" border="1"> |
| </div></p> |
| |
| <p>Можно отметить, что каждый из этих узлов имеет отображаемое имя, получаемое из канала, значок и пункт меню "Delete". |
| |
| |
| </p><p>Для создания этого класса выполните следующие действия: |
| |
| </p><ol> |
| <li> |
| Создайте элемент <tt> OneFeedNode.java</tt> в пакете <tt> org.myorg.feedreader</tt>.</li> |
| <li> |
| Замените класс по умолчанию на следующий:</li> |
| </ol> |
| <pre class="examplecode">public class OneFeedNode extends FilterNode { |
| |
| OneFeedNode(Node feedFileNode, SyndFeed feed) throws IOException, IntrospectionException { |
| super(feedFileNode, |
| new FeedChildren(feed), |
| new ProxyLookup( |
| new Lookup[]{Lookups.fixed( |
| new Object[]{feed}), |
| feedFileNode.getLookup() |
| })); |
| } |
| |
| @Override |
| public String getDisplayName() { |
| SyndFeed feed = getLookup().lookup(SyndFeed.class); |
| return feed.getTitle(); |
| } |
| |
| @Override |
| public Image getIcon(int type) { |
| return Utilities.loadImage("org/myorg/feedreader/rss16.gif"); |
| } |
| |
| @Override |
| public Image getOpenedIcon(int type) { |
| return getIcon(0); |
| } |
| |
| @Override |
| public Action[] getActions(boolean context) { |
| return new Action[]{SystemAction.get(DeleteAction.class)}; |
| } |
| |
| }</pre> |
| |
| </ol> |
| |
| |
| <p>Некоторые строки кода, относящегося к классу, подчеркнуты красным цветом, поскольку <tt>FeedChildren</tt> до сих пор не создан. |
| |
| |
| </p><h3> |
| Создание класса "FeedChildren"</H3> |
| |
| <p>В этом разделе будет добавлена часть кода, необходимого для представления узлов для каждой из статей, содержащихся в канале. |
| |
| </p><p>Для создания этого класса выполните следующие действия: |
| |
| </p><ol> |
| <li> |
| Создайте элемент <tt> FeedChildren.java</tt> в пакете <tt> org.myorg.feedreader</tt>.</li> |
| <li> |
| Замените класс по умолчанию на следующий:</li> |
| </ol> |
| <pre class="examplecode">public class FeedChildren extends Children.Keys { |
| |
| private final SyndFeed feed; |
| |
| public FeedChildren(SyndFeed feed) { |
| this.feed = feed; |
| } |
| |
| @SuppressWarnings(value = "unchecked") |
| @Override |
| protected void addNotify() { |
| setKeys(feed.getEntries()); |
| } |
| |
| public Node[] createNodes(Object key) { |
| |
| <b>//Возвращение новых узлов на уровне статьи:</b> |
| try { |
| return new Node[]{ |
| new EntryBeanNode((SyndEntry) key) |
| }; |
| |
| } catch (final IntrospectionException ex) { |
| Exceptions.printStackTrace(ex); |
| <b>//Это не должно происходить, причины для сбоя отсутствуют:</b> |
| return new Node[]{new AbstractNode(Children.LEAF) { |
| @Override |
| public String getHtmlDisplayName() { |
| return "" + ex.getMessage() + ""; |
| } |
| }}; |
| } |
| } |
| }</pre> |
| |
| </ol> |
| |
| <p>Некоторые строки кода, относящегося к классу, подчеркнуты красным цветом, поскольку <tt>EntryBeanNode</tt> до сих пор не создан. |
| |
| |
| </p><h3> |
| Создание класса "EntryBeanNode"</H3> |
| |
| <p>Теперь рассмотрим узлы самых нижних уровней, отражающие статьи, содержащиеся в канале. |
| |
| </p><p>Для создания этого класса выполните следующие действия: |
| |
| </p><ol> |
| <li> |
| Создайте элемент <tt> EntryBeanNode.java</tt> в пакете <tt> org.myorg.feedreader</tt>.</li> |
| <li> |
| Замените класс по умолчанию на следующий:</li> |
| </ol> |
| <pre class="examplecode">public class EntryBeanNode extends FilterNode { |
| |
| private SyndEntry entry; |
| |
| @SuppressWarnings(value = "unchecked") |
| public EntryBeanNode(SyndEntry entry) throws IntrospectionException { |
| super(new BeanNode(entry), Children.LEAF, |
| Lookups.fixed(new Object[]{ |
| entry, |
| new EntryOpenCookie(entry) |
| })); |
| this.entry = entry; |
| } |
| |
| <b>/** Использование "HtmlDisplayName" обеспечивает правильность обработки, выхода, получения объектов и т.д. для любого кода HTML в заголовках сообщений RSS. */</b> |
| @Override |
| public String getHtmlDisplayName() { |
| return entry.getTitle(); |
| } |
| |
| <b>/** Создание всплывающей подсказки к описанию сообщения */</b> |
| @Override |
| public String getShortDescription() { |
| return entry.getDescription().getValue(); |
| } |
| |
| <b>/** Ввод действия "Open" для сообщения канала */</b> |
| @Override |
| public Action[] getActions(boolean popup) { |
| return new Action[]{SystemAction.get(OpenAction.class)}; |
| } |
| |
| @Override |
| public Action getPreferredAction() { |
| return (SystemAction) getActions(false) [0]; |
| } |
| |
| <b>/** Указание на операцию, выполняемую после вызова пользователем действия "Open" */</b> |
| private static class EntryOpenCookie implements OpenCookie { |
| |
| private final SyndEntry entry; |
| |
| EntryOpenCookie(SyndEntry entry) { |
| this.entry = entry; |
| } |
| |
| public void open() { |
| try { |
| URLDisplayer.getDefault().showURL(new URL(entry.getUri())); |
| } catch (MalformedURLException mue) { |
| Exceptions.printStackTrace(mue); |
| } |
| } |
| |
| } |
| |
| }</pre> |
| |
| </ol> |
| |
| |
| |
| <h3> |
| Создание пункта меню "Add Folder"</H3> |
| |
| <p>В этом разделе создается пункт меню, предназначенный для создания объявленных ранее папок. |
| |
| </p><p>Для создания этого класса выполните следующие действия: |
| |
| </p><ol> |
| <li> |
| Создайте элемент <tt> AddFolderAction.java</tt> в пакете <tt> org.myorg.feedreader</tt>.</li> |
| <li> |
| Замените класс по умолчанию на следующий:</li> |
| </ol> |
| <pre class="examplecode">public class AddFolderAction extends AbstractAction { |
| |
| private DataFolder folder; |
| |
| public AddFolderAction(DataFolder df) { |
| folder = df; |
| putValue(Action.NAME, NbBundle.getMessage(RssNode.class, "FN_addfolderbutton")); |
| } |
| |
| public void actionPerformed(ActionEvent ae) { |
| NotifyDescriptor.InputLine nd = |
| new NotifyDescriptor.InputLine( |
| NbBundle.getMessage(RssNode.class, "FN_askfolder_msg"), |
| NbBundle.getMessage(RssNode.class, "FN_askfolder_title"), |
| NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.PLAIN_MESSAGE); |
| Object result = DialogDisplayer.getDefault().notify(nd); |
| if (result.equals(NotifyDescriptor.OK_OPTION)) { |
| final String folderString = nd.getInputText(); |
| try { |
| DataFolder.create(folder, folderString); |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| } |
| } |
| }</pre> |
| |
| </ol> |
| |
| |
| <h3> |
| Создание пункта меню "Add RSS"</H3> |
| |
| <p>В этом разделе рассматривается создание пункта меню для добавления новых каналов. |
| |
| </p><p>Для создания этого класса выполните следующие действия: |
| |
| </p><ol> |
| <li> |
| Создайте элемент <tt> AddRssAction.java</tt> в пакете <tt> org.myorg.feedreader</tt>.</li> |
| <li> |
| Замените класс по умолчанию на следующий:</li> |
| </ol> |
| <pre class="examplecode">public class AddRssAction extends AbstractAction { |
| |
| private DataFolder folder; |
| |
| public AddRssAction(DataFolder df) { |
| folder = df; |
| putValue(Action.NAME, NbBundle.getMessage(RssNode.class, "FN_addbutton")); |
| } |
| |
| public void actionPerformed(ActionEvent ae) { |
| |
| NotifyDescriptor.InputLine nd = new NotifyDescriptor.InputLine( |
| NbBundle.getMessage(RssNode.class, "FN_askurl_msg"), |
| NbBundle.getMessage(RssNode.class, "FN_askurl_title"), |
| NotifyDescriptor.OK_CANCEL_OPTION, |
| NotifyDescriptor.PLAIN_MESSAGE); |
| |
| Object result = DialogDisplayer.getDefault().notify(nd); |
| |
| if (result.equals(NotifyDescriptor.OK_OPTION)) { |
| String urlString = nd.getInputText(); |
| URL url; |
| try { |
| url = new URL(urlString); |
| } catch (MalformedURLException e) { |
| String message = NbBundle.getMessage(RssNode.class, "FN_askurl_err", urlString); |
| Exceptions.attachLocalizedMessage(e, message); |
| Exceptions.printStackTrace(e); |
| return; |
| } |
| try { |
| checkConnection(url); |
| } catch (IOException e) { |
| String message = NbBundle.getMessage(RssNode.class, "FN_cannotConnect_err", urlString); |
| Exceptions.attachLocalizedMessage(e, message); |
| Exceptions.printStackTrace(e); |
| return; |
| } |
| Feed f = new Feed(url); |
| FileObject fld = folder.getPrimaryFile(); |
| String baseName = "RssFeed"; |
| int ix = 1; |
| while (fld.getFileObject(baseName + ix, "ser") != null) { |
| ix++; |
| } |
| try { |
| FileObject writeTo = fld.createData(baseName + ix, "ser"); |
| FileLock lock = writeTo.lock(); |
| try { |
| ObjectOutputStream str = new ObjectOutputStream(writeTo.getOutputStream(lock)); |
| try { |
| str.writeObject(f); |
| } finally { |
| str.close(); |
| } |
| } finally { |
| lock.releaseLock(); |
| } |
| } catch (IOException ioe) { |
| Exceptions.printStackTrace(ioe); |
| } |
| } |
| |
| private static void checkConnection(final URL url) throws IOException { |
| InputStream is = url.openStream(); |
| is.close(); |
| } |
| |
| }</pre> |
| |
| </ol> |
| |
| |
| |
| <h3> |
| Локализация класса "RssNode"</H3> |
| <ol> |
| <li> |
| Откройте файл <tt> Bundle.properties</tt> модуля <tt> FeedReader</tt>.</li> |
| <li> |
| Добавьте следующие пары "ключ-значение":<br> |
| |
| <pre class="examplecode">FN_title=RSS/Atom Feeds |
| FN_addbutton=Add |
| FN_askurl_title=New Feed |
| FN_askurl_msg=Enter the URL of an RSS/Atom Feed |
| FN_askurl_err=Invalid URL: {0}| |
| FN_addfolderbutton=Add Folder |
| FN_askfolder_msg=Enter the folder name |
| FN_askfolder_title=New Folder</pre> |
| |
| </li> |
| </ol> |
| |
| Ниже приведено пояснение новых пар "ключ-значение", локализующих строки, определенные в элементе <tt> RssNode.java</tt>:</P> |
| <UL> |
| <li> |
| <b>FN_title.</b> Локализует текст верхнего узла в окне "Feed Window".</li> |
| </UL> |
| |
| Локализация интерфейса пользователя для добавления канала:</P> |
| <UL> |
| <li> |
| <b>FN_addbutton.</b> Локализует текст пункта меню "Add" в контекстном меню верхнего узла.</li> |
| <li> |
| <b>FN_askurl_title.</b> Локализует заголовок диалогового окна "New Feed".</li> |
| <li> |
| <b>FN_askurl_msg.</b> Локализует сообщение, появляющееся в диалоговом окне "New Feed".</li> |
| <li> |
| <b>FN_askurl_err.</b> Локализует строку ошибки, отображаемую в случае недействительности URL-адреса.</li> |
| </UL> |
| |
| Локализация интерфейса пользователя для добавления папки:</P> |
| <UL> |
| <li> |
| <b>FN_addfolderbutton.</b> Локализует текст пункта меню "Add Folder" в контекстном меню верхнего узла.</li> |
| <li> |
| <b>FN_askfolder_msg.</b> Локализует сообщение, появляющееся в диалоговом окне "Add Folder".</li> |
| <li> |
| <b>FN_askfolder_title. </b> Локализует заголовок диалогового окна "Add Folder".</li> |
| </UL> |
| <h2><a name="branding"></a> Выбор стиля для приложения</H2> |
| <p> |
| В конце цикла разработки, на этапе заключительной подготовки приложения, необходимо рассмотреть следующие вопросы:</P> |
| <UL> |
| <li> |
| Каким должно быть имя исполняемого файла приложения?</li> |
| <li> |
| Что должен увидеть пользователь после запуска приложения? Индикатор хода выполнения? Экран заставки? И то, и другое?</li> |
| <li> |
| Что должно отображаться в строке заголовка при запуске приложения?</li> |
| <li> |
| Являются ли все меню и кнопки панелей инструментов, предоставляемые платформой NetBeans по умолчанию, действительно необходимыми?</li> |
| </UL> |
| <p> |
| Эти вопросы относятся к сфере выбора стиля, персонализации приложения, построенного на базе платформы NetBeans. В среде IDE в диалоговом окне "Project Properties" проектов пакетов модулей предусмотрена специальная панель, упрощающая выбор стиля.</P> |
| <ol> |
| <li> |
| Щелкните правой кнопкой мыши узел проекта <tt> feedreader-suite</tt> (а не узел проекта <tt> FeedReader</tt>) и выберите "Properties". В диалоговом окне "Project Properties" выберите "Build". </li> |
| <li> |
| На экране "Build" введите значение <tt> feedreader</tt> в поле "Branding Name". Введите <tt> Feed Reader Application</tt> в поле "Application Title". Значение поля "Branding Name" определяет имя исполняемой программы, а значение поля "Application Title" – строку заголовка приложения. </li> |
| <li> |
| Нажмите кнопку "Browse" и найдите значок <tt> rss16.gif</tt> (<IMG SRC="../../images/tutorials/feedreader/rss16.gif" />). Значок будет отображаться в диалоговом окне "Help > About".</li> |
| |
| <p>Экран должен выглядеть следующим образом:</p> |
| <IMG SRC="../../images/tutorials/feedreader/60-brand1.png" border="1"/> |
| |
| |
| <li> |
| На экране "Splash Screen" нажмите кнопку "Browse" и найдите файл <tt> splash.gif</tt> . Кроме того, можно изменить цвет и размер текста индикатора хода выполнения. Если индикатор хода выполнения не требуется, снимите флажок "Enabled".</li> |
| |
| <p>Экран должен выглядеть следующим образом:</p> |
| <IMG SRC="../../images/tutorials/feedreader/60-brand2.png" border="1"/> |
| |
| |
| <li> |
| Нажмите кнопку "OK".<br> |
| В проекте <tt> FeedReader Application</tt> будет создана папка <tt> branding</tt>. Она будет отображена в окне "Files" (Ctrl-2).</li> |
| <li> |
| В окне "Files" разверните узел проекта <tt> FeedReader Application</tt>. После этого продолжайте разворачивать узлы до тех пор, пока не найдете следующий узел:<br> |
| <tt> branding/modules/org-netbeans-core-window.jar/org/netbeans/core/windows</tt> |
| </li> |
| <li> |
| Щелкните правой кнопкой мыши этот узел, выберите "New > Other", а затем пункт "Folder" в категории "Other". Нажмите кнопку "Next" и присвойте папке имя <tt> resources</tt> . Нажмите кнопку "Finish". </li> |
| <li> |
| Щелкните правой кнопкой мыши новый узел <tt> resources</tt>, выберите "New > Other", а затем "XML Document" в категории XML. Нажмите кнопку "Next". Присвойте файлу имя <tt> layer</tt> . Нажмите кнопку "Next", а затем кнопку "Finish". Замените содержимое нового файла <tt> layer.xml</tt> на следующий текст:</li> |
| </ol> |
| <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"? > |
| <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "https://netbeans.org/dtds/filesystem-1_1.dtd"> |
| <!-- |
| Это уровень "стиля". Он объединяется с файлом layer.xml, для настройки которого используется. |
| В данном случае осуществляется скрытие нежелательных пунктов меню и панелей инструментов. |
| --> |
| <filesystem> |
| |
| <!-- Скрытие неиспользуемых панелей инструментов --> |
| <folder name="Toolbars"> |
| <folder name="File_hidden"/> |
| <folder name="Edit_hidden"/> |
| </folder> |
| |
| <folder name="Menu"> |
| <folder name="File"> |
| <file name="org-openide-actions-SaveAction.instance_hidden"/> |
| <file name="org-openide-actions-SaveAllAction.instance_hidden"/> |
| <file name="org-netbeans-core-actions-RefreshAllFilesystemsAction.instance_hidden"/> |
| <file name="org-openide-actions-PageSetupAction.instance_hidden"/> |
| <file name="org-openide-actions-PrintAction.instance_hidden"/> |
| </folder> |
| <folder name="Edit_hidden"/> |
| <folder name="Tools_hidden"/> |
| </folder> |
| |
| </filesystem></pre> |
| <h2><a name="distributing"></a> Подготовка дистрибутива приложения</H2> |
| <p> |
| Для создания дистрибутива приложения в среде IDE используется сценарий сборки Ant. Сценарий сборки создается при создании проекта.</P> |
| <ol> |
| <li> |
| В окне "Projects" щелкните правой кнопкой мыши узел проекта <tt> FeedReader Application</tt> и выберите "Build ZIP Distribution". В окне "Output" отображается местоположение созданного ZIP-файла дистрибутива. </li> |
| <li> |
| В файловой системе найдите дистрибутив <tt> feedreader.zip</tt> в папке <tt> dist</tt> каталога проекта. Разархивируйте его. Запустите приложение, находящееся в папке <tt> bin</tt>. При запуске на экране отобразится заставка. После запуска приложения вызовите диалоговое окно "Help > About" и обратите внимание на значок и экран заставки, которые были настроены в разделе <A HREF="#branding" CLASS="XRef">Выбор стиля для приложения</A>.</li> |
| </ol> |
| <p> |
| После запуска и в ходе работы в приложении для чтения каналов отображается окно "RSS/Atom Feeds", содержащее узел под названием "RSS/Atom Feeds". </P> |
| <p> |
| Поздравляем! Изучение руководства по созданию приложения для чтения каналов завершено.</P> |
| <br> |
| <div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback: NetBeans Platform 6.0 Feed Reader Tutorial">Мы ждем ваших отзывов</a></div> |
| <br style="clear:both;" /> |
| <hr> |
| </BODY> |
| </HTML> |