UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

134 lines (132 loc) 18.3 kB
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <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>