UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

105 lines (100 loc) 17.5 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>The Spinner</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="The Spinner"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-17-SECT-5"/>The Spinner</h1></div></div></div><p><a id="idx10981" class="indexterm"/> <a id="idx10996" class="indexterm"/> <code class="literal">JList</code> and <code class="literal">JComboBox</code> are two ways to let the user choose from a set of values. A <code class="literal">JComboBox</code> has added flexibility when it is made editable, but, in general, both of these components are limited in that they can only prompt the user from a fixed set of choices. In Java 1.4, Swing added a component called <code class="literal">JSpinner</code> that is useful for large or open-ended sequences of values such as numbers or dates. The <code class="literal">JSpinner</code> is a cousin of the <code class="literal">JComboBox</code>; it displays a value in a field, but instead of providing a drop-down list of choices, it gives the user a small pair of up and down arrows for moving over a range of values (see <a class="xref" href="ch17s04.html#learnjava3-CHP-17-FIG-5" title="Figure 17-5. Image of DateSelector application">Figure 17-5</a>). Like the combo box, a <code class="literal">JSpinner</code> can also be made editable, allowing the user to type a valid value directly into the field.</p><div class="figure"><a id="learnjava3-CHP-17-FIG-5"/><div class="figure-contents"><div class="mediaobject"><a id="I_17_tt1014"/><img src="httpatomoreillycomsourceoreillyimages1707657.png" alt="Image of DateSelector application"/></div></div><p class="title">Figure 17-5. Image of DateSelector application</p></div><p>Swing provides three basic types of <code class="literal">Spinner</code>s, represented by three different data models for the <code class="literal">JSpinner</code> component: <a id="I_indexterm17_id795183" class="indexterm"/><code class="literal">SpinnerListModel</code>, <a id="I_indexterm17_id795194" class="indexterm"/><code class="literal">SpinnerNumberModel</code>, and <a id="I_indexterm17_id795205" class="indexterm"/><code class="literal">SpinnerDateModel</code>.</p><p>The <code class="literal">SpinnerListModel</code> acts like a combo box, specifying a fixed set of objects:</p><a id="I_17_tt1015"/><pre class="programlisting"> <code class="n">String</code> <code class="o">[]</code> <code class="n">options</code> <code class="o">=</code> <code class="k">new</code> <code class="n">String</code> <code class="o">[]</code> <code class="o">{</code> <code class="s">"small"</code><code class="o">,</code> <code class="s">"medium"</code><code class="o">,</code> <code class="s">"large"</code><code class="o">,</code> <code class="s">"huge"</code> <code class="o">};</code> <code class="n">SpinnerListModel</code> <code class="n">model</code> <code class="o">=</code> <code class="k">new</code> <code class="n">SpinnerListModel</code><code class="o">(</code> <code class="n">options</code> <code class="o">);</code> <code class="n">JSpinner</code> <code class="n">spinner</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JSpinner</code><code class="o">(</code> <code class="n">model</code> <code class="o">);</code></pre><p>You can retrieve the current value from the model at any time:</p><a id="I_17_tt1016"/><pre class="programlisting"> <code class="n">String</code> <code class="n">value</code> <code class="o">=</code> <code class="o">(</code><code class="n">String</code><code class="o">)</code><code class="n">model</code><code class="o">.</code><code class="na">getValue</code><code class="o">();</code></pre><p>Alternatively, you can register a <code class="literal">ChangeListener</code> to receive updates as the user changes values. With a <code class="literal">SpinnerListModel</code>, if the spinner is editable and the user enters a value directly, it is validated against the set of choices before being accepted. This behavior is a little different from the other types of <code class="literal">SpinnerModel</code>s which, when editable, accept any valid value of the correct type (e.g., a number or date).</p><p>The <code class="literal">SpinnerNumberModel</code> displays numeric values. It can be configured with initial, minimum, and maximum values:</p><a id="I_17_tt1017"/><pre class="programlisting"> <code class="kt">double</code> <code class="n">initial</code><code class="o">=</code><code class="mf">5.0</code><code class="o">,</code> <code class="n">min</code><code class="o">=</code><code class="mf">0.0</code><code class="o">,</code> <code class="n">max</code><code class="o">=</code><code class="mf">10.0</code><code class="o">,</code> <code class="n">increment</code><code class="o">=</code><code class="mf">0.1</code><code class="o">;</code> <code class="n">SpinnerNumberModel</code> <code class="n">model</code> <code class="o">=</code> <code class="k">new</code> <code class="nf">SpinnerNumberModel</code><code class="o">(</code> <code class="n">initial</code><code class="o">,</code> <code class="n">min</code><code class="o">,</code> <code class="n">max</code><code class="o">,</code> <code class="n">increment</code> <code class="o">);</code> <code class="n">JSpinner</code> <code class="n">spinner</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JSpinner</code><code class="o">(</code><code class="n">model</code><code class="o">);</code></pre><p>Here we have constructed a spinner with an initial value of 5.0 that allows the user to change the value to between 0 and 10.0 in increments of 0.1. The <code class="literal">SpinnerNumberModel getNumber()</code> method retrieves the current value.</p><p>Perhaps the most interesting feature of the <code class="literal">JSpinner</code> is the <code class="literal">SpinnerDateModel</code>, which allows the user to choose calendar dates by moving in specified increments of time. The <code class="literal">SpinnerDateModel</code> accepts a range, such as the <code class="literal">SpinnerNumberModel</code>, but the values are <code class="literal">Date</code> objects and the increment is a <code class="literal">java.util.Calendar</code> constant field such as <code class="literal">Calendar.DAY</code>, <code class="literal">Calendar.WEEK</code>, and so on. The following example, <code class="literal">DateSelector</code>, creates a <code class="literal">JSpinner</code> showing the current date and time. It allows the user to change the date in increments of one week, over a range of one year (six months forward or back). A <code class="literal">ChangeListener</code> is registered with the model to display the values as they are modified:</p><a id="I_17_tt1018"/><pre class="programlisting"> <code class="kn">import</code> <code class="nn">java.awt.*</code><code class="o">;</code> <code class="kn">import</code> <code class="nn">java.awt.event.*</code><code class="o">;</code> <code class="kn">import</code> <code class="nn">javax.swing.*</code><code class="o">;</code> <code class="kn">import</code> <code class="nn">javax.swing.event.*</code><code class="o">;</code> <code class="kn">import</code> <code class="nn">java.util.*</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">DateSelector</code> <code class="o">{</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code><code class="o">[]</code> <code class="n">args</code><code class="o">)</code> <code class="o">{</code> <code class="n">JFrame</code> <code class="n">frame</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JFrame</code><code class="o">(</code><code class="s">"DateSelector v1.0"</code><code class="o">);</code> <code class="n">Calendar</code> <code class="n">now</code> <code class="o">=</code> <code class="n">Calendar</code><code class="o">.</code><code class="na">getInstance</code><code class="o">();</code> <code class="n">Calendar</code> <code class="n">earliest</code> <code class="o">=</code> <code class="o">(</code><code class="n">Calendar</code><code class="o">)</code><code class="n">now</code><code class="o">.</code><code class="na">clone</code><code class="o">();</code> <code class="n">earliest</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="n">Calendar</code><code class="o">.</code><code class="na">MONTH</code><code class="o">,</code> <code class="o">-</code><code class="mi">6</code> <code class="o">);</code> <code class="n">Calendar</code> <code class="n">latest</code> <code class="o">=</code> <code class="o">(</code><code class="n">Calendar</code><code class="o">)</code><code class="n">now</code><code class="o">.</code><code class="na">clone</code><code class="o">();</code> <code class="n">latest</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="n">Calendar</code><code class="o">.</code><code class="na">MONTH</code><code class="o">,</code> <code class="mi">6</code> <code class="o">);</code> <code class="n">SpinnerModel</code> <code class="n">model</code> <code class="o">=</code> <code class="k">new</code> <code class="n">SpinnerDateModel</code><code class="o">(</code> <code class="n">now</code><code class="o">.</code><code class="na">getTime</code><code class="o">(),</code> <code class="n">earliest</code><code class="o">.</code><code class="na">getTime</code><code class="o">(),</code> <code class="n">latest</code><code class="o">.</code><code class="na">getTime</code><code class="o">(),</code> <code class="n">Calendar</code><code class="o">.</code><code class="na">WEEK_OF_YEAR</code><code class="o">);</code> <code class="kd">final</code> <code class="n">JSpinner</code> <code class="n">spinner</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JSpinner</code><code class="o">(</code><code class="n">model</code><code class="o">);</code> <code class="c1">// Disable the built-in date editor</code> <code class="n">spinner</code><code class="o">.</code><code class="na">setEditor</code><code class="o">(</code><code class="k">new</code> <code class="n">JSpinner</code><code class="o">.</code><code class="na">DefaultEditor</code><code class="o">(</code><code class="n">spinner</code><code class="o">)</code> <code class="o">);</code> <code class="n">model</code><code class="o">.</code><code class="na">addChangeListener</code><code class="o">(</code> <code class="k">new</code> <code class="n">ChangeListener</code><code class="o">()</code> <code class="o">{</code> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">stateChanged</code><code class="o">(</code><code class="n">ChangeEvent</code> <code class="n">e</code><code class="o">)</code> <code class="o">{</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="o">((</code><code class="n">SpinnerDateModel</code><code class="o">)</code><code class="n">e</code><code class="o">.</code><code class="na">getSource</code><code class="o">())</code> <code class="o">.</code><code class="na">getDate</code><code class="o">()</code> <code class="o">);</code> <code class="o">}</code> <code class="o">}</code> <code class="o">);</code> <code class="n">frame</code><code class="o">.</code><code class="na">getContentPane</code><code class="o">().</code><code class="na">add</code><code class="o">(</code> <code class="s">"North"</code><code class="o">,</code> <code class="k">new</code> <code class="n">JLabel</code><code class="o">(</code><code class="s">"Choose a week"</code><code class="o">)</code> <code class="o">);</code> <code class="n">frame</code><code class="o">.</code><code class="na">getContentPane</code><code class="o">().</code><code class="na">add</code><code class="o">(</code> <code class="s">"Center"</code><code class="o">,</code> <code class="n">spinner</code> <code class="o">);</code> <code class="n">frame</code><code class="o">.</code><code class="na">pack</code><code class="o">();</code> <code class="n">frame</code><code class="o">.</code><code class="na">setDefaultCloseOperation</code><code class="o">(</code> <code class="n">JFrame</code><code class="o">.</code><code class="na">EXIT_ON_CLOSE</code> <code class="o">);</code> <code class="n">frame</code><code class="o">.</code><code class="na">setVisible</code><code class="o">(</code><code class="kc">true</code><code class="o">);</code> <code class="o">}</code> <code class="o">}</code></pre><p>As we said, the <code class="literal">SpinnerCalendarModel</code> acts just like the <code class="literal">SpinnerNumberModel</code>, except that it works with <code class="literal">Date</code> objects and uses the special <code class="literal">Calendar</code> constants as increments. To create <code class="literal">dates</code>, we construct a <code class="literal">Calendar</code> object for the correct time and use its <code class="literal">getTime()</code> method. In this example, we used the <code class="literal">Calendar</code>’s <code class="literal">add()</code> method to set the minimum and maximum values six months in each direction. <a class="xref" href="ch17s04.html#learnjava3-CHP-17-TABLE-1" title="Table 17-1. Calendar field values">Table 17-1</a> shows values for increments in the <code class="literal">Calendar</code>.</p><div class="table"><a id="learnjava3-CHP-17-TABLE-1"/><p class="title">Table 17-1. Calendar field values</p><div class="table-contents"><table summary="Calendar field values" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; "><colgroup><col/><col/></colgroup><thead><tr><th style="text-align: left"><p>Field value</p></th><th style="text-align: left"><p>Increment</p></th></tr></thead><tbody><tr><td style="text-align: left"><p> <a id="I_indexterm17_id795490" class="indexterm"/> <code class="literal">Calendar.MILLISECOND</code> </p></td><td style="text-align: left"><p>One millisecond</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm17_id795513" class="indexterm"/> <code class="literal">Calendar.SECOND</code> </p></td><td style="text-align: left"><p>One second</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm17_id795536" class="indexterm"/> <code class="literal">Calendar.MINUTE</code> </p></td><td style="text-align: left"><p>One minute</p></td></tr><tr><td style="text-align: left"><p> <code class="literal">Calendar.HOUR Calendar.HOUR_OF_DAY</code> </p></td><td style="text-align: left"><p>One hour</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm17_id795576" class="indexterm"/> <code class="literal">Calendar.AM_PM</code> </p></td><td style="text-align: left"><p>A.M. or P.M.</p></td></tr><tr><td style="text-align: left" valign="top"><p> <a id="I_indexterm17_id795602" class="indexterm"/> <code class="literal">Calendar.DAY_OF_WEEK</code> </p> <p> <a id="I_indexterm17_id795617" class="indexterm"/> <code class="literal">Calendar.DAY_OF_MONTH</code> </p> <p> <a id="I_indexterm17_id795632" class="indexterm"/> <code class="literal">Calendar.DAY_OF_YEAR</code> </p></td><td style="text-align: left" valign="top"><p>One day</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm17_id795658" class="indexterm"/> <code class="literal">Calendar.MONTH</code> </p></td><td style="text-align: left"><p>One month</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm17_id795681" class="indexterm"/> <code class="literal">Calendar.YEAR</code> </p></td><td style="text-align: left"><p>One year</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm17_id795704" class="indexterm"/> <code class="literal">Calendar.ERA</code> </p></td><td style="text-align: left"><p>B.C. or A.D. in the Gregorian calendar</p></td></tr></tbody></table></div></div><p>The <code class="literal">SpinnerDateModel</code> uses the <code class="literal">Calendar add()</code> method with a value of <code class="literal">1</code> or <code class="literal">-1</code> and the corresponding constant value to increment or decrement the value. Increments of one have the same effect on several of the constants, as indicated in <a class="xref" href="ch17s04.html#learnjava3-CHP-17-TABLE-1" title="Table 17-1. Calendar field values">Table 17-1</a>.<a id="I_indexterm17_id795750" class="indexterm"/><a id="I_indexterm17_id795758" class="indexterm"/></p></div></body></html>