epubjs
Version:
Render ePub documents in the browser, across many devices
134 lines (132 loc) • 18.3 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Building Beans</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Building Beans"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-22-SECT-6"/>Building Beans</h1></div></div></div><p>Now that you have a feel for how beans look from the user’s
perspective, let’s build some. In this section, we will become the Magic
Beans Company. We will create some beans, package them for distribution,
and use them in NetBeans to build a very simple application. (The complete
JAR file, along with all the example code for this chapter, is online at
<a class="ulink" href="http://bit.ly/Learn_Java_4E"><span class="emphasis"><em>http://oreil.ly/Learn_Java_4E</em></span></a>.)</p><p>The first thing we’ll remind you of is that absolutely anything can
be a bean. Even the following class is a bean, albeit an invisible
one:</p><a id="I_22_tt1221"/><pre class="programlisting"> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">Trivial</code> <code class="kd">implements</code> <code class="n">java</code><code class="o">.</code><code class="na">io</code><code class="o">.</code><code class="na">Serializable</code> <code class="o">{}</code></pre><p>Of course, this bean isn’t very useful: it doesn’t have any
properties, and it doesn’t do anything. But it’s a bean nonetheless, and
we can drag it into NetBeans as long as we package it correctly. If we
modify this class to extend <code class="literal">JComponent</code>,
we suddenly have a graphical bean that be seen in the layout, with lots of
standard Swing properties, such as size and color information:</p><a id="I_22_tt1222"/><pre class="programlisting"> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">TrivialComponent</code> <code class="kd">extends</code> <code class="n">JComponent</code> <code class="o">{}</code></pre><p>Next, let’s look at a bean that’s a bit more useful.</p><div class="sect2" title="The Dial Bean"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-22-SECT-6.1"/>The Dial Bean</h2></div></div></div><p><a id="idx11143" class="indexterm"/> <a id="idx11152" class="indexterm"/>We created a nifty <code class="literal">Dial</code>
component in <a class="xref" href="ch18.html" title="Chapter 18. More Swing Components">Chapter 18</a>. What would it take to
turn it into a bean? Surprise: it is already a bean! The <code class="literal">Dial</code> has a number of properties that it
exposes in the way prescribed by JavaBeans. A get method retrieves the
value of a property; for example, <code class="literal">getValue()</code> retrieves the dial’s current value.
Likewise, a set method, <code class="literal">setValue()</code>,
modifies the dial’s value. The dial has two other properties, which also
have get and set methods: <code class="literal">minimum</code> and
<code class="literal">maximum</code>. This is all the <code class="literal">Dial</code> needs to inform a tool such as NetBeans
what properties it has and how to work with them. Because <code class="literal">Dial</code> is a <code class="literal">JComponent</code>, it also has all the standard Swing
properties, such as color and size. The <code class="literal">JComponent</code> provides the set and get methods
for all its properties.</p><p>To use our <code class="literal">Dial</code>, we’ll put it
in a Java package named <code class="literal">magicbeans</code>
and store it in a JAR file that can be loaded by NetBeans. The <a class="ulink" href="http://examples.oreilly.com/0636920023463/">source code</a>,
which can be found online, includes
an Ant build file (see <a class="xref" href="ch15.html" title="Chapter 15. Web Applications and Web Services">Chapter 15</a>) that
compiles the code and creates the final JAR file.</p><p>If you were starting from scratch, it would go like this: first,
create a directory called <a id="I_indexterm22_id822106" class="indexterm"/><span class="emphasis"><em>magicbeans</em></span> to hold our beans, add a
<code class="literal">package</code> statement to the source files
<span class="emphasis"><em>Dial.java</em></span>, <span class="emphasis"><em>DialEvent.java</em></span>, and
<span class="emphasis"><em>DialListener.java</em></span> (from <a class="xref" href="ch18.html" title="Chapter 18. More Swing Components">Chapter 18</a>), put the source files into the
<span class="emphasis"><em>magicbeans</em></span> directory, and compile them (using the
command <span class="emphasis"><em>javac magicBeans/Dial.java</em></span>) to create class
files.</p><p>Next, we need to create a manifest file that tells NetBeans which
of the classes in the JAR file are beans and which are support files or
unrelated. At this point, we have only one bean,
<span class="emphasis"><em>Dial.class</em></span>, so create the following file, called
<span class="emphasis"><em>magicBeans.manifest</em></span>:</p><a id="I_22_tt1223"/><pre class="programlisting"> <code class="nl">Name:</code> <code class="n">magicbeans</code><code class="o">/</code><code class="n">Dial</code><code class="o">.</code><code class="na">class</code>
<code class="n">Java</code><code class="o">-</code><code class="nl">Bean:</code> <code class="n">True</code></pre><p>The <code class="literal">Name:</code> label identifies the
class file as it will appear in the JAR: <code class="literal">magicbeans/Dial.class</code>. Specifications
appearing after an item’s <code class="literal">Name:</code> line
and before an empty line apply to that item. (See <a class="xref" href="ch03.html" title="Chapter 3. Tools of the Trade">Chapter 3</a> for more details.) We have added the
attribute <code class="literal">Java-Bean: True</code>, which
flags this class as a bean to tools that read the manifest. We will add
an entry like this for each bean in our package. We don’t need to flag
support classes (such as <code class="literal">DialEvent</code>
and <code class="literal">DialListener</code>) as beans because we
won’t want to manipulate them directly with NetBeans; in fact, we don’t
need to mention them in the manifest at all.</p><p>To create the JAR file, including our manifest information, enter
this command:</p><a id="I_22_tt1224"/><pre class="programlisting"> <code class="o">%</code> <strong class="userinput"><code><code class="n">jar</code> <code class="o">-</code><code class="n">cvmf</code> <code class="n">magicbeans</code><code class="o">.</code><code class="na">manifest</code> <code class="n">magicbeans</code><code class="o">.</code><code class="na">jar</code> <code class="n">magicbeans</code><code class="o">/*.</code><code class="na">class</code></code></strong></pre><p>If you loaded the precompiled examples as instructed earlier, then
you already have the <code class="literal">Dial</code> bean loaded into NetBeans. The
version supplied in the precompiled <span class="emphasis"><em>magicbeans.jar</em></span> file
has additional packaging that allows it to appear with a spiffy icon in
the palette, as we’ll discuss a bit later. (If you haven’t loaded the
example JAR, you can import the one we just created by selecting Palette
→ Swing/AWT Components dialog from the Tools menu, as described earlier
in this chapter.) If you want to replace the <code class="literal">Dial</code> bean on your palette, you can remove it
by right-clicking on the icon and selecting Delete before importing the
new JAR. (Actually, NetBeans 7.2 should reload the JAR automatically if
you overwrite it.)</p><p>You should now have an entry for <code class="literal">Dial</code> in the bean palette. Drop an instance of
the <code class="literal">Dial</code> bean into a new JFrame Form
file in NetBeans.</p><p>As <a class="xref" href="ch22s06.html#learnjava3-CHP-22-FIG-8" title="Figure 22-7. The Dial component as a bean">Figure 22-7</a> shows, the <code class="literal">Dial</code>’s properties—maximum, minimum, and
value—appear in the Properties pane and can be modified by NetBeans. If
you just created the <code class="literal">Dial</code> JAR
following our minimal instructions, you’ll see these properties along
with all the Swing properties inherited from the <code class="literal">JComponent</code> class. The figure shows the
<code class="literal">Dial</code> bean as it appears later in this
chapter (with the supplied packaging), after we’ve learned about the
<code class="literal">BeanInfo</code> class. We’re almost
there.</p><p>Now we’re ready to put the <code class="literal">Dial</code>
to use. Reopen the <code class="literal">Juggler</code> file that
we created in the first section of this chapter. Add an instance of our
new magic <code class="literal">Dial</code> bean to the scenario,
as shown in <a class="xref" href="ch22s06.html#learnjava3-CHP-22-FIG-9" title="Figure 22-8. The Juggler with a dialable animation rate">Figure 22-8</a>.</p><p>Bind the <code class="literal">value</code> property of the
<code class="literal">Dial</code> to the <code class="literal">animationRate</code> of the <code class="literal">Juggler</code>. Use the Connection Wizard, as before,
selecting the <code class="literal">Dial</code> and then the
<code class="literal">Juggler</code>. Select the <code class="literal">DialEvent</code> source and bind the <code class="literal">animationRate</code> property, selecting the <code class="literal">Dial</code>’s value as the property source. When you
complete the hookup, you should be able to vary the speed of the juggler
by turning the dial. Try changing the maximum and minimum values of the
dial to change the range.<a id="I_indexterm22_id822391" class="indexterm"/><a id="I_indexterm22_id822398" class="indexterm"/></p><div class="figure"><a id="learnjava3-CHP-22-FIG-8"/><div class="figure-contents"><div class="mediaobject"><a id="I_22_tt1225"/><img src="httpatomoreillycomsourceoreillyimages1707711.png" alt="The Dial component as a bean"/></div></div><p class="title">Figure 22-7. The Dial component as a bean</p></div><div class="figure"><a id="learnjava3-CHP-22-FIG-9"/><div class="figure-contents"><div class="mediaobject"><a id="I_22_tt1226"/><img src="httpatomoreillycomsourceoreillyimages1707712.png.jpg" alt="The Juggler with a dialable animation rate"/></div></div><p class="title">Figure 22-8. The Juggler with a dialable animation rate</p></div></div><div class="sect2" title="Design Patterns for Properties"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-22-SECT-6.2"/>Design Patterns for Properties</h2></div></div></div><p><a id="idx11151" class="indexterm"/>We said earlier that tools such as NetBeans found out
about a bean’s properties by looking at its get and set methods. The
easiest way to make properties visible is to follow these simple design
patterns:</p><div class="itemizedlist"><ul class="itemizedlist"><li class="listitem"><p>Method for getting the current value of a property:</p><a id="I_22_tt1227"/><pre class="programlisting"> <code class="kd">public</code> <em class="replaceable"><code><code class="n">PropertyType</code></code></em> <code class="n">get</code><em class="replaceable"><code><code class="n">PropertyName</code></code></em><code class="o">()</code></pre></li><li class="listitem"><p>Method for setting the value of a property:</p><a id="I_22_tt1228"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">void</code> <code class="n">set</code><em class="replaceable"><code><code class="n">PropertyName</code></code></em><code class="o">(</code> <em class="replaceable"><code><code class="n">PropertyType</code></code></em> <code class="n">arg</code> <code class="o">)</code></pre></li><li class="listitem"><p>Method for determining whether a Boolean-valued property is
currently <code class="literal">true</code>:</p><a id="I_22_tt1229"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">boolean</code> <code class="n">is</code><em class="replaceable"><code><code class="n">PropertyName</code></code></em><code class="o">()</code></pre></li></ul></div><p>The last method is optional and is used only for properties with
Boolean values. (You could use the get method for Boolean values as
well.)</p><p>The appropriate set and get methods for these features of our bean
are already in the <code class="literal">Dial</code> class, either
methods that we added or methods inherited from the <code class="literal">java.awt.Component</code> and <code class="literal">javax.swing.JComponent</code> classes:</p><a id="I_22_tt1230"/><pre class="programlisting"> <code class="c1">// inherited from Component</code>
<code class="kd">public</code> <code class="n">Color</code> <code class="nf">getForeground</code><code class="o">()</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">setForeground</code><code class="o">(</code><code class="n">Color</code> <code class="n">c</code><code class="o">)</code>
<code class="err"> </code>
<code class="kd">public</code> <code class="n">Color</code> <code class="nf">getBackground</code><code class="o">()</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">setBackground</code><code class="o">(</code><code class="n">Color</code> <code class="n">c</code><code class="o">)</code>
<code class="err"> </code>
<code class="kd">public</code> <code class="n">Font</code> <code class="nf">getFont</code><code class="o">()</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">setFont</code><code class="o">(</code><code class="n">Font</code> <code class="n">f</code><code class="o">)</code>
<code class="err"> </code>
<code class="c1">// many others from Component and JComponent</code>
<code class="c1">// part of the Dial itself</code>
<code class="kd">public</code> <code class="kt">int</code> <code class="nf">getValue</code><code class="o">()</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">setValue</code><code class="o">(</code><code class="kt">int</code> <code class="n">v</code><code class="o">)</code>
<code class="err"> </code>
<code class="kd">public</code> <code class="kt">int</code> <code class="nf">getMinimum</code><code class="o">()</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">setMinimum</code><code class="o">(</code><code class="kt">int</code> <code class="n">m</code><code class="o">)</code>
<code class="err"> </code>
<code class="kd">public</code> <code class="kt">int</code> <code class="nf">getMaximum</code><code class="o">()</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">setMaximum</code><code class="o">(</code><code class="kt">int</code> <code class="n">m</code><code class="o">)</code></pre><p>JavaBeans allows read and write-only properties, which are
implemented simply by leaving out the get or set method.</p><p>NetBeans uses the Reflection API to find out about the <code class="literal">Dial</code> bean’s methods; it then uses these naming
conventions to learn what properties are available. When we use the
properties editor to change a value, NetBeans dynamically invokes the
correct set method to change the value.</p><p>If you look further at the <code class="literal">JComponent</code> class, you’ll notice that other
methods match the design pattern. For example, what about the <code class="literal">setCursor()</code> and <code class="literal">getCursor()</code> pair? NetBeans doesn’t know how to
display or edit a cursor, and we didn’t supply an editor, so it ignores
those properties in the properties sheet.</p><p>NetBeans automatically pulls the property’s name from the name of
its accessor methods; it then lowercases the name for display on the
properties sheet. For example, the <code class="literal">font</code> property is derived from <code class="literal">getFont</code>. Later, we’ll show how to provide a
<code class="literal">BeanInfo</code> class that overrides the way
these properties are displayed, which allows you to provide your own
friendly property names. Again, if you used the <code class="literal">Dial</code> bean from our precompiled example JAR,
you’ll see only our three <code class="literal">Dial</code>
properties. The <code class="literal">JComponent</code> properties
are hidden by our packaging a <code class="literal">BeanInfo</code> class that determines the properties
we wish to show.</p><div class="sect3" title="Generating bean patterns in NetBeans"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-22-SECT-6.2.1"/>Generating bean patterns in NetBeans</h3></div></div></div><p><a id="I_indexterm22_id822659" class="indexterm"/> <a id="I_indexterm22_id822670" class="indexterm"/>NetBeans automatically recognizes JavaBeans getter and
setter method patterns in classes. In the source code view, select the
Source menu Insert Code option and choose Getter and Setter to
automatically generate getter and setter methods for fields in your
class. This can save you a bit of typing if you need to add a lot of
properties.<a id="I_indexterm22_id822682" class="indexterm"/></p></div></div></div></body></html>