<!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> | |
<title>Platform Quick Start for NetBeans Platform</title> | |
<meta name="AUDIENCE" content="NBUSER"/> | |
<meta name="TYPE" content="ARTICLE"/> | |
<link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"/> | |
<meta name="EXPIRES" content="N"/> | |
<meta name="developer" content="gwielenga@netbeans.org"/> | |
<meta name="indexed" content="y"/> | |
<meta name="description" | |
content="A short guide to getting started with the NetBeans Platform."/> | |
<!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> | |
<!-- Use is subject to license terms.--> | |
</head> | |
<body> | |
<h1>NetBeans Platform Quick Start</h1> | |
<p>Welcome to the <a href="https://platform.netbeans.org/"><b>NetBeans Platform</b></a>!</p> | |
<p>The NetBeans Platform is a generic application framework primarily for Java desktop applications. | |
The main benefit of the NetBeans Platform is its predefined modular architecture. Secondary | |
benefits are the NetBeans Platform's reusable solutions such as its | |
docking framework and its out-of-the-box pluggable components, in combination with the tools | |
provided by its SDK, NetBeans IDE, in particular | |
its award winning "Matisse" GUI Builder for designing GUI components.</p> | |
<p>In this quick start, you are introduced to the benefits and usages of modularity | |
on the Java desktop via | |
a very simple example, contributed by Thomas Würthinger, a | |
PhD student at the Johannes Kepler University in Linz, Austria. Once you have | |
grasped the concepts introduced in this quick start, you will be ready to | |
step onto the <a href="https://netbeans.org/kb/trails/platform.html">NetBeans Platform Learning Trail</a>, | |
providing a very rich variety of tutorials for many different scenarios | |
relating to the NetBeans Platform.</p> | |
<p class="tips"> If you are new to the NetBeans Platform, it is highly | |
recommended to watch the screencast series <a href="https://platform.netbeans.org/tutorials/nbm-10-top-apis.html">Top 10 NetBeans APIs</a>.</p> | |
<p><strong class="notes">Note: </strong>This document uses NetBeans Platform 7.3 and | |
NetBeans IDE 7.3. If you | |
are using an earlier version, see <a href="72/nbm-quick-start.html">the previous version | |
of this document</a>.</p> | |
<p><b>Contents</b></p> | |
<p><img src="../images/articles/74/netbeans_stamp_74_73_72.png" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 7.3" title="Content on this page applies to NetBeans IDE 7.3"/></p> | |
<ul class="toc"> | |
<li>Part 1: <a href="#single">A Single Module NetBeans Platform Application</a> | |
<ul> | |
<li><a href="#application">Create the Application</a></li> | |
<li><a href="#module">Create the Module</a></li> | |
<li><a href="#window">Create the Window</a></li> | |
<li><a href="#run">Run the Application</a></li> | |
</ul> | |
</li> | |
<li>Part 2: <a href="#lookup">A Modular Application Using Lookup</a> | |
<ul> | |
<li><a href="#api">Create the API</a></li> | |
<li><a href="#impl">Implement the API</a></li> | |
<li><a href="#run2">Run the Application</a></li> | |
</ul> | |
</li> | |
<li>Part 3: <a href="#listener">Publishing and Subscribing to the Lookup</a> | |
<ul> | |
<li><a href="#publish">Publish to the Lookup</a></li> | |
<li><a href="#subscribe">Subscribe to the Lookup</a></li> | |
</ul> | |
</li> | |
</ul> | |
<p><b>To follow this tutorial, you need the software and resources listed in the following | |
table.</b></p> | |
<table> | |
<tbody> | |
<tr> | |
<th class="tblheader" scope="col">Software or Resource</th> | |
<th class="tblheader" scope="col">Version Required</th> | |
</tr> | |
<tr> | |
<td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td> | |
<td class="tbltd1">version 7.3 or above</td> | |
</tr> | |
<tr> | |
<td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">Java Developer Kit (JDK)</a></td> | |
<td class="tbltd1">version 7 or above</td> | |
</tr> | |
</tbody> | |
</table> | |
<p class="tips">For troubleshooting purposes, you are welcome to download the <a href="http://java.net/projects/nb-api-samples/sources/api-samples/show/versions/7.3/tutorials/WordProcessor">completed tutorial source code</a>.</p> | |
<p></p> | |
<p><b class="notes">Note:</b> Even though it is a separate product, there is no | |
need to download the NetBeans Platform separately. Typically, you develop the | |
application in NetBeans IDE and then exclude the modules that are specific to | |
the IDE but that are superfluous to your application.</p> | |
<p class="tips"> Do some background reading before diving into | |
this tutorial. In particular, read the <a href="http://bits.netbeans.org/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html">Modules API Reference</a> document, | |
which explains what modules are and provides some | |
context for this tutorial, while noting that there is an extensive Reference Material section | |
on the <a href="https://netbeans.org/kb/trails/platform.html">NetBeans Platform Learning Trail</a>.</p> | |
<!-- ===================================================================================== --> | |
<h2 class="tutorial"><a name="single"></a>A Single Module NetBeans Platform Application</h2> | |
<p>We start by creating a new NetBeans Platform application, | |
containing a single module.</p> | |
<ul> | |
<li><a href="#application">Create the Application</a></li> | |
<li><a href="#module">Create the Module</a></li> | |
<li><a href="#window">Create the Window</a></li> | |
<li><a href="#run">Running the Application</a></li> | |
</ul> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="application"></a>Create the Application</h3> | |
<p>In this section, you create your first NetBeans Platform application.</p> | |
<div class="indent"> | |
<ol> | |
<li><p>Choose File | New Project and then choose NetBeans Modules. | |
Select "NetBeans Platform Application". You should see this:</p><br/> | |
<p><img src="../images/tutorials/quickstart-platform/73/new-project-1.png" alt="Fig 1"/></p> | |
<p>The difference between the 4 templates above is as follows:</p> | |
<ul> | |
<li> | |
<b>NetBeans Platform Application.</b> A project that groups a set of | |
module projects and library wrapper module projects that have dependencies on | |
each other, and lets you deploy them together as a unit. Automatically included | |
are a subset of the modules that make up the NetBeans Platform.</li> | |
<li> | |
<b>Module Suite.</b> Same as above, except that the pre-included modules are | |
more than only those relating to the NetBeans Platform—in this case, | |
all the modules that make up NetBeans IDE are included as well.</li> | |
<li> | |
<b>Library Wrapper Module.</b> A project that puts a library JAR file on its classpath and exports some or all of the JAR file's packages from the module as public packages.</li> | |
<li> | |
<b>Module.</b> A project for implementing the functionality, business logic, and user interface of a module or application built on the NetBeans Platform.</li> | |
</ul> | |
<br/><p>Click Next.</p></li> | |
<li><p>Name your new application "WordProcessor" and specify a folder on disk | |
for storing it:</p><br/> | |
<p><img src="../images/tutorials/quickstart-platform/73/new-project-2.png" alt="Fig 2"/></p> | |
<br/><p>Click Finish. The new project appears as follows in the Projects window:</p> | |
<br/><p><img src="../images/tutorials/quickstart-platform/73/new-project-3.png" alt="Fig 2-1"/></p></li> | |
</ol> | |
</div> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="module"></a>Create the Module</h3> | |
<p>In this section, you create your first NetBeans Platform module.</p> | |
<div class="indent"> | |
<ol> | |
<li><p>Right-click the "Modules" node, shown in the screenshot above, | |
and choose "Add New":</p> | |
<br/><p><img src="../images/tutorials/quickstart-platform/73/new-module-1.png" alt="Fig 2-1"/></p> | |
<p>Name the new | |
module "WordEditorCore":</p> | |
<br/><p><img alt="create new module" src="../images/tutorials/quickstart-platform/73/new-module-2.png"/></p> | |
<br/><p>Click Next.</p></li> | |
<li><p>Specify "org.word.editor.core" as the unique string identifying the module, which is its code name | |
base, together with a project display name that will be shown in the Projects window.</p><br/> | |
<p><img alt="create new module" src="../images/tutorials/quickstart-platform/73/new-module-3.png"/></p> | |
<br/><p>Click Finish. The new module is created and its structure is | |
shown in the Projects window:</p> | |
<br/><p><img alt="specify a name" src="../images/tutorials/quickstart-platform/73/new-module-4.png"/></p></li> | |
</ol> | |
</div> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="window"></a>Create the Window</h3> | |
<p>In this section, you create your first NetBeans window.</p> | |
<div class="indent"> | |
<ol> | |
<li><p>Right-click the "WordEditorCore" module and choose New | Other. | |
In the Module Development category, select "Window":</p> | |
<p><br/><img alt="create new window" src="../images/tutorials/quickstart-platform/73/new-window-1.png"/></p> | |
<br/><p>Click Next.</p></li> | |
<li><p>You should now see a dialog for specifying the position where the new window | |
will appear in the application frame, as well as whether it will open automatically when the application | |
starts, among other settings:</p> | |
<p><br/><img alt="create new window" src="../images/tutorials/quickstart-platform/73/new-window-2.png"/></p> | |
<p><br/>In the wizard step above, select "editor", which is the default central | |
position within the application frame, and "Open on Application Start". Then click Next.</p></li> | |
<li><p>Set the class name prefix to "Word" and the package to "org.word.editor.core":</p> | |
<p><br/><img alt="set definitions" src="../images/tutorials/quickstart-platform/73/new-window-3.png"/></p> | |
<p><br/>Click Finish. The new window is added to the source structure | |
of your module:</p> | |
<p><br/><img alt="set definitions" src="../images/tutorials/quickstart-platform/73/new-window-4.png"/></p></li> | |
<li><p>Now double click on the file "WordTopComponent.java" to open | |
it in the Design view of the "Matisse" GUI Builder.</p> | |
<p><br/><img alt="palette" style="border: 1px solid black;" src="../images/tutorials/quickstart-platform/73/new-window-5.png"/></p> | |
<br/><p>Use the Palette (Ctrl-Shift-8) to | |
drag and drop a button and a text area onto the window:</p> | |
<p><br/><img alt="palette" style="border: 1px solid black;" src="../images/tutorials/quickstart-platform/73/new-window-5a.png"/></p> | |
<br/><p>Do the following to make the new GUI components meaningful:</p> | |
<br/><ul> | |
<li>Right-click the text area, choose "Change Variable Name", and then | |
name it "text".</li> | |
<li>Right-click the button, choose "Edit Text", and then set the text of the button to "Filter!"</li> | |
</ul></li> | |
<li>Double click on the button, causing an event handling method | |
to automatically be created in the Source editor. The method is called whenever the button is clicked. Change the body | |
of the method to the following code. | |
<pre class="examplecode">private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { | |
<b>String s = text.getText(); | |
s = s.toUpperCase(); | |
text.setText(s);</b> | |
}</pre></li> | |
</ol> | |
</div> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="run"></a>Run the Application</h3> | |
<p>In this section, you deploy the application.</p> | |
<div class="indent"> | |
<ol> | |
<li><p>Right-click the WordProcessor application and choose Run. Doing so will start up your | |
new NetBeans Platform application and install your module. You will have a new | |
window, as well as a new menu item for opening it, | |
as shown below:</p> | |
<br/><p><img alt="show new app" src="../images/tutorials/quickstart-platform/73/new-app-1.png"/></p></li> | |
<li><p>Enter a text in lowercase in the text area, and click "Filter!". | |
You should see that the text is now shown | |
in uppercase:</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-app-2.png"/></p></li> | |
</ol> | |
</div> | |
</div> | |
<p>You have learned how to create a new NetBeans Platform application and how | |
to add new modules to it. In the next section, you will be introduced | |
to the NetBeans Platform's pluggable service infrastructure.</p> | |
<!-- ===================================================================================== --> | |
<h2 class="tutorial"><a name="lookup"></a>A Modular Application Using Lookup</h2> | |
<p>In this section, you create two additional modules. The first | |
new module, "WordEditorAPI", | |
contains a service provider interface. The second module, | |
"UppercaseFilter", is a service provider for the interface.</p> | |
<p> The GUI module, which you created in the previous section, will be loosely coupled from | |
the "UppercaseFilter" service provider because the GUI module | |
will not refer to any code from the "UppercaseFilter" service provider. | |
That will be possible because the "UppercaseFilter" | |
service provider will be registered in the META-INF/services folder | |
and loaded via the NetBeans Lookup class, which is comparable to | |
the JDK 6 ServiceLoader class.</p><p> You will then | |
create another loosely coupled service provider, | |
named "LowercaseFilter".</p> | |
<ul> | |
<li><a href="#api">Create the API</a></li> | |
<li><a href="#impl">Implement the API</a></li> | |
<li><a href="#run2">Run the Application</a></li> | |
</ul> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="api"></a>Create the API</h3> | |
<p>In this section, you create an API.</p> | |
<div class="indent"> | |
<ol> | |
<li><p>Expand the new application in the Projects window, | |
right-click the Modules node, and choose "Add New":</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-api-1.png"/></p> | |
<br/><p>Name the new | |
module "WordEditorAPI":</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-api-2.png"/></p> | |
<br/><p>Click Next. Use code name base "org.word.editor.api", as shown below:</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-api-3.png"/></p> | |
<br/><p>Complete the wizard, which adds the module to your previously created | |
application, as you did in the previous section:</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-api-4.png"/></p> | |
</li> | |
<li><p>Right-click the "WordEditorAPI" module and choose | |
New | Java Interface. Name the Java interface "WordFilter", | |
in the package "org.word.editor.api":</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-api-5.png"/></p> | |
<p>Use the editor | |
to define it as follows:</p> | |
<pre class="examplecode">package org.word.editor.api; | |
public interface WordFilter { | |
String process(String s); | |
}</pre></li> | |
<li><p>Right-click the "WordEditorAPI" module, | |
choose Properties, and use the "API Versioning" | |
tab to specify that the package containing the | |
interface should be available throughout the | |
application:</p> | |
<br/><p><img alt="" src="../images/tutorials/quickstart-platform/73/new-api-6.png"/></p> | |
<br/><p>Click OK.</p> | |
<p class="tips">In the Projects window, expand "Important Files" in the | |
"WordEditorAPI" project and then | |
double-click "Project Metadata". The "project.xml" file | |
opens and you should see that the package has now been declared | |
public:</p> | |
<pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="https://netbeans.org/ns/project/1"> | |
<type>org.netbeans.modules.apisupport.project</type> | |
<configuration> | |
<data xmlns="https://netbeans.org/ns/nb-module-project/3"> | |
<code-name-base>org.word.editor.api</code-name-base> | |
<suite-component/> | |
<module-dependencies/> | |
<b><public-packages> | |
<package>org.word.editor.api</package> | |
</public-packages></b> | |
</data> | |
</configuration> | |
</project></pre> | |
</li> | |
</ol> | |
</div> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="impl"></a>Implement the API</h3> | |
<p>In this section, you implement the API, in a separate module.</p> | |
<div class="indent"> | |
<ol> | |
<li><p>Expand the new application in the Projects window, | |
right-click the Modules node, and choose "Add New" again:</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-impl-1.png"/></p> | |
<br/><p>Name the new | |
module "UppercaseFilter":</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-impl-2.png"/></p> | |
<br/><p>Click Next. Use code name base "org.word.editor.uppercase", as shown below:</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-impl-3.png"/></p> | |
<br/><p>Complete the wizard, which adds the module to your previously created | |
application, as you did in the previous section:</p> | |
<br/><p><img alt="uppercase" src="../images/tutorials/quickstart-platform/73/new-impl-4.png"/></p></li> | |
<li><p>Right-click the Libraries node of the "UppercaseFilter" module, and choose | |
Add Module Dependency, as shown below:</p> | |
<br/><p><img alt="" src="../images/tutorials/quickstart-platform/73/new-impl-5.png"/></p> | |
<br/><p>Start typing the name of the API class and notice that the list narrows | |
until the module containing the class is found:</p> | |
<br/><p><img alt="" src="../images/tutorials/quickstart-platform/73/new-impl-6.png"/></p> | |
<br/><p>Click OK.</p> | |
<br/><p class="tips">In the Projects window, expand "Important Files" in the "UppercaseFilter" project, | |
and then | |
double-click "Project Metadata". The "project.xml" file | |
opens and you should see that a new dependency has been declared:</p> | |
<pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="https://netbeans.org/ns/project/1"> | |
<type>org.netbeans.modules.apisupport.project</type> | |
<configuration> | |
<data xmlns="https://netbeans.org/ns/nb-module-project/3"> | |
<code-name-base>org.word.editor.uppercase</code-name-base> | |
<suite-component/> | |
<b><module-dependencies> | |
<dependency> | |
<code-name-base>org.word.editor.api</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<specification-version>1.0</specification-version> | |
</run-dependency> | |
</dependency> | |
</module-dependencies></b> | |
<public-packages/> | |
</data> | |
</configuration> | |
</project></pre></li> | |
<li><p>In the same way as shown in the previous step, | |
set a dependency on the Lookup API module, which provides the | |
@ServiceProvider annotation that you will use in the next step.</p></li> | |
<li>Because of the Lookup API dependency you defined above, | |
you can now implement the | |
interface defined in the WordEditorAPI module. Do so in the "UppercaseFilter" module, by creating | |
a new class named "UppercaseFilter", in the "org.word.editor.uppercase" package, | |
as shown below. Start by creating a new Java class, named "UppercaseFilter", and | |
then define it as follows: | |
<pre class="examplecode">package org.word.editor.uppercase; | |
import org.openide.util.lookup.ServiceProvider; | |
import org.word.editor.api.WordFilter; | |
@ServiceProvider(service=WordFilter.class) | |
public class UppercaseFilter implements WordFilter { | |
@Override | |
public String process(String s) { | |
return s.toUpperCase(); | |
} | |
}</pre> | |
<p class="tips"> At compile time, the @ServiceProvider annotation will create a META-INF/services | |
folder with a file that registers your implementation of the | |
WordFilter interface, following the JDK 6 ServiceLoader mechanism.</p></li> | |
<li><p>In the WordEditorCore module, the code that handles a click on the | |
filter button now needs to be changed, so that all | |
implementations of the interface "WordFilter" are located | |
and loaded. | |
When such implementations are found, you need to invoke its method to | |
filter the text. Before we can do this, we need to | |
add a dependency in the | |
the "WordEditorCore" module on the "WordEditorAPI" module:</p> | |
<br/><p><img alt="" src="../images/tutorials/quickstart-platform/73/new-impl-7.png"/></p> | |
<p>Now, you can load implementations of the | |
"WordFilter" class, as shown below:</p> | |
<pre class="examplecode">private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { | |
<b>String enteredText = text.getText(); | |
Collection<? extends WordFilter> allFilters = Lookup.getDefault().lookupAll(WordFilter.class); | |
StringBuilder sb = new StringBuilder(); | |
for (WordFilter textFilter : allFilters) { | |
String processedText = textFilter.process(enteredText); | |
sb.append(processedText).append("\n"); | |
} | |
text.setText(sb.toString());</b> | |
}</pre> | |
<p class="tips"> The above could be achieved via the | |
JDK 6 "ServiceLoader" class, except that the | |
"Lookup" class can be used in JDK's prior | |
to JDK 6. Aside from that, the "Lookup" class | |
has a number of additional features, as the | |
next section will illustrate.</p> | |
</li> | |
</ol> | |
</div> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="run2"></a>Run the Application</h3> | |
<p>In this section, you run the application again.</p> | |
<div class="indent"> | |
<ol> | |
<li><p>Now you can run the application again and check | |
that everything works just as before. While the functionality | |
is the same, the new modular design offers a clear separation | |
between the GUI and the implementation | |
of the filter. The structure of the application should be as shown below:</p> | |
<br/><p><img alt="" src="../images/tutorials/quickstart-platform/73/new-impl-8.png"/></p> | |
</li> | |
<li><p>The new application can also be extended | |
quite easily, by adding new service providers to | |
the application's classpath. As an exercise, add a new module that provides a "LowercaseFilter" | |
implementation of the API to the application.</p></li> | |
</ol> | |
</div> | |
</div> | |
<p>You have now used the default Lookup, that is, "Lookup.getDefault()", to load | |
implementations of an interface from the META-INF/services folder.</p> | |
<!-- ===================================================================================== --> | |
<h2 class="tutorial"><a name="listener"></a>Publishing and Subscribing to the Lookup</h2> | |
<p>In this section, we create a fourth module, which receives texts | |
dynamically whenever we click the "Filter!" button | |
in our first module.</p> | |
<ul> | |
<li><a href="#publish">Publish to the Lookup</a></li> | |
<li><a href="#subscribe">Subscribe to the Lookup</a></li> | |
</ul> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="publish"></a>Publish to the Lookup</h3> | |
<p>In this section, you publish a String into the Lookup of the TopComponent. Whenever | |
the TopComponent is selected, the String is published into the application's context.</p> | |
<div class="indent"> | |
<ol> | |
<li>In the "WordEditorCore" module, we publish a String whenever | |
the user clicks the "Filter!" button. To do so, change the | |
constructor of the "WordTopComponent" as follows: | |
<pre class="examplecode"><b>private <a href="http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/org/openide/util/lookup/InstanceContent.html">InstanceContent</a> content;</b> | |
private WordTopComponent() { | |
initComponents(); | |
setName(Bundle.CTL_WordTopComponent()); | |
setToolTipText(Bundle.HINT_WordTopComponent()); | |
<b>content = new InstanceContent(); | |
<a href="http://bits.netbeans.org/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html#associateLookup(org.openide.util.Lookup)">associateLookup</a>(new <a href="http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/org/openide/util/lookup/AbstractLookup.html">AbstractLookup</a>(content));</b> | |
}</pre></li><li><p>Change the code of the filter | |
button so that the entered text is added to | |
the <tt>InstanceContent</tt> object when the button is clicked.</p> | |
<pre class="examplecode">private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { | |
String enteredText = text.getText(); | |
Collection<? extends WordFilter> allFilters = Lookup.getDefault().lookupAll(WordFilter.class); | |
StringBuilder sb = new StringBuilder(); | |
for (WordFilter textFilter : allFilters) { | |
String processedText = textFilter.process(enteredText); | |
sb.append(processedText).append("\n"); | |
<b>content.add(enteredText);</b> | |
} | |
text.setText(sb.toString()); | |
}</pre> | |
</li> | |
</ol> | |
</div> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="subscribe"></a>Subscribe to the Lookup</h3> | |
<p>In this section, you create a new module, with a new window. In | |
the new window, you listen to the application's context for Strings. When there | |
is a new String in the Lookup, you display it in the window.</p> | |
<div class="indent"> | |
<ol> | |
<li><p>In the same way as done in the previous sections, | |
create another module in your application and name it "WordHistory". | |
Use code name base "org.word.editor.history".</p> | |
</li> | |
<li><p>In the WordHistory module, right-click the "org.word.editor.history" package | |
and choose New | Window. Use the New Window wizard to create a | |
new window component that will automatically be opened on the left side of the | |
application frame, which is the "explorer" position:</p> | |
<br/><p><img alt="" src="../images/tutorials/quickstart-platform/73/new-history-1.png"/></p> | |
<br/><p>Click Next. Use prefix "WordHistory" and specify that the new window will be stored | |
in the "org.word.editor.history" package. Click Finish.</p> | |
</li> | |
<li><p>Once | |
you have created the window, add a | |
<tt>JTextArea</tt> to it, resizing it so that it covers the whole area of the window:</p> | |
<br/><p><img alt="" style="border:1px solid black" src="../images/tutorials/quickstart-platform/73/new-history-w.png"/></p> | |
<p>Change the variable | |
name of the text area to "historyText".</p> | |
</li> | |
<li>In the Source view, add code to the constructor of the HistoryTopComponent class so | |
that it listens to the lookup of the <tt>String</tt> class | |
of the current active window. It displays all retrieved | |
<tt>String</tt> objects in the text area: | |
<pre class="examplecode">... | |
... | |
... | |
public final class HistoryTopComponent extends TopComponent <b>implements LookupListener</b> { | |
<b>private org.openide.util.Lookup.Result<String> result;</b> | |
... | |
... | |
... | |
<b>@Override | |
public void componentOpened() { | |
result = org.openide.util.Utilities.actionsGlobalContext().lookupResult(String.class); | |
result.addLookupListener(this); | |
} | |
@Override | |
public void componentClosed() { | |
result.removeLookupListener(this); | |
} | |
@Override | |
public void resultChanged(LookupEvent le) { | |
Collection<? extends String> allStrings = result.allInstances(); | |
StringBuilder sb = new StringBuilder(); | |
for (String string : allStrings) { | |
sb.append(string).append("\n"); | |
} | |
historyText.setText(sb.toString()); | |
}</b> | |
... | |
... | |
... | |
</pre></li> | |
<li><p>Then you can start the application and | |
experiment with it. The result should look similar | |
to that shown in the screenshot below:</p> | |
<br/><p><img alt="" src="../images/tutorials/quickstart-platform/73/new-result-1.png"/></p> | |
<p class="tips">As an exercise, redesign the user interface of the "WordTopComponent" | |
in such a way that a <tt>JList</tt> displays the filters.</p> | |
</li> | |
</ol> | |
</div> | |
</div> | |
<p>Congratulations! At this stage, with very little coding, | |
you have created a small example of a loosely-coupled modular | |
application:</p> | |
<p><img alt="" src="../images/tutorials/quickstart-platform/73/new-result-2.png"/></p> | |
<p>Two important concepts have been covered in this tutorial.</p> | |
<div class="indent"> | |
<ol> | |
<li>The application consists of four modules. Code from one module can only | |
be used by another module if (1) the first module explicitly exposes | |
packages and (2) the second module sets a dependency on the first module. | |
In this way, the NetBeans Platform helps to organize your code in a | |
strict modular architecture, ensuring that code isn't reused randomly | |
but only when there are contracts set between the modules that provide | |
the code.</li> | |
<li>Secondly, the <tt>Lookup</tt> class has been introduced as | |
a mechanism for communicating between modules, as an extension of the | |
JDK 6 ServiceLoader approach. Implementations are loaded via their | |
interfaces. Without using any code from an implementation, the "WordEditorCore" | |
module is able to display the service provided by the implementor. Loose | |
coupling is provided to NetBeans Platform applications in this way.</li> | |
</ol> | |
</div> | |
<p class="tips"> To continue learning about modularity | |
and the NetBeans Platform, head on to | |
the four-part "NetBeans Platform Selection | |
Management" series, <a href="https://platform.netbeans.org/tutorials/nbm-selection-1.html">which starts here</a>. | |
After that, get started with the <a href="https://netbeans.org/kb/trails/platform.html">NetBeans Platform Learning Trail</a>, choosing | |
the tutorials that are most relevant to your particular business scenario. Also, | |
whenever you have questions about the NetBeans Platform, of any kind, feel free | |
to write to the mailing list, dev@platform.netbeans.org; its related | |
archive <a href="https://netbeans.org/projects/platform/lists/dev/archive">is here</a>.</p> | |
<p>Have fun with the NetBeans Platform and see you on the mailing list!</p> | |
<div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback: NetBeans Platform Quick Start 7.3">Send Us Your Feedback</a> | |
<br style="clear:both;" /></div> | |
</body> | |
</html> |