7.10 Spinner Editors


You probably noticed that the JSpinner class also includes several inner classes. These inner classes provide basic editors (and renderers) for spinners for each of the major model types. While you'll typically rely on the editor picked by your spinner when you create it, you can override that decision if you like. Here's a simple example of a modified DateEditor. This spinner displays an mm/yy date, and the step size is one month. Figure 7-16 shows such a spinner.

Figure 7-16. A customized DateEditor used in a JSpinner
figs/swng2.0716.gif

Here's the source code that built this editor:

// MonthSpinner.java // import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.util.*; public class MonthSpinner extends JFrame {   public MonthSpinner( ) {     super("Month Spinner");     setSize(200,100);     setDefaultCloseOperation(EXIT_ON_CLOSE);     Container c = getContentPane( );     c.setLayout(new FlowLayout(FlowLayout.LEFT, 4,4));     c.add(new JLabel("Expiration Date:"));     Date today = new Date( );     // Start the spinner today, but don't set a min or max date.     // The increment should be a month.     JSpinner s = new JSpinner(new SpinnerDateModel(today,                   null, null, Calendar.MONTH));     JSpinner.DateEditor de = new JSpinner.DateEditor(s, "MM/yy");     s.setEditor(de);     c.add(s);     setVisible(true);   }   public static void main(String args[]) {     new MonthSpinner( );   } }

7.10.1 DefaultEditor

All of the other inner class editors descend from the DefaultEditor class, as shown in Figure 7-14. That's exactly why you would use this class: it's a starting point for creating other simple editors. It's based on a single JFormattedTextField.

7.10.1.1 Constructors

This editor takes a single constructor:

public JSpinner.DefaultEditor(JSpinner spinner)

Build an editor for the given spinner. This constructor registers itself as a listener to spinner's change events and displays the current value of spinner's model.

7.10.1.2 Properties

The DefaultEditor has two read-only properties, which are shown in Table 7-22.

Table 7-22. JSpinner.DefaultEditor properties

Property

Data type

get

is

set

Default value

spinner

JSpinner

·

     

textField

JFormattedTextField

·

     

7.10.1.3 Editing methods
public void commitEdit( ) throws ParseException

Send the current value in the editor to the model for the spinner.

public void dismiss(JSpinner spinner)

Disconnect the editor from the specified spinner. (This should be the same spinner as the one passed to the constructor.) By default, this simply detaches the editor from spinner's ChangeListener list. For example, if you want to cancel your edits, you dismiss( ) the spinner.

7.10.2 DateEditor

As you can see in the previous example, the DateEditor inner class provides simple display and edit functionality for dates. The supported formats follow those in the java.text.SimpleDateFormat class.

Note that the editor is just looking for valid date formats. You can set up a SpinnerDateModel that increments dates on a week-by-week basis, e.g., every Sunday. If you type in a date that should be a Monday, the DateEditor allows it, and the default model sets the new date. Now when you use the spinner's up/down buttons, you'll bounce forward and backward on Mondays not Sundays. Check out the ListEditor discussion for an example of stopping the user from editing spinner values by hand.

7.10.2.1 Constructors
public JSpinner.DateEditor(JSpinner spinner)

Create a standard editor (a formatted text field) for dates using the model from the given spinner. The format of the date (in the U.S. English locale) is M/d/yy h:mm a (for example, 4/13/07 3:14 PM).

public JSpinner.DateEditor(JSpinner spinner, String dateFormatPattern)

Create a standard editor for dates using the model from the specified spinner. The dateFormatPattern determines how dates are shown as well as how they can be entered by a user. The pattern must match the specifications of the java.text.SimpleDateFormat class. Table 7-23 shows some of the more common elements you might use in such a pattern.

Table 7-23. SimpleDateFormat common formats

Code

Description

Example usage

d

Day in month

d -> "7", "17"; dd -> "07", "17"

E

Day in week

E -> "Monday"; EEE -> "Mon"

M

Month in year

M -> "4", "12"; MM -> "04", "12";MMM -> "Apr", "Dec"; MMMM -> "April", "December"

y

Year

yy -> "02", "99"; yyyy -> "2002", "1999"

h

Hours (1-12)

h -> "5", "10"; hh -> "05", "10"

m

Minutes (0-59)

mm -> "15", "32"

a

A.M./P.M. marker

a -> "AM", "PM"

7.10.2.2 Properties

Two read-only properties exist for the DateEditor. These are shown in Table 7-24.

Table 7-24. JSpinner.DateEditor properties

Property

Data type

get

is

set

Default value

format

SimpleDateFormat

·

   

"M/d/yy h:mm a"

model

SpinnerDateModel

·

   

7.10.3 ListEditor

This simple editor works on spinners with a SpinnerListModel installed. Its primary function is to make sure typed values match up with values in the actual model. If you start typing in a list spinner, the text field tries to auto-complete. If you type a value that does not exist in the model, the typed value is discarded when you press Enter.

This editor works only on strings. If your list is numeric (like denominations of paper money) or composed of arbitrary objects, they will be represented and edited as strings. For non-String objects, then, typing values into the spinner is a futile exercise. Even if you type the representation of a valid object, the List underneath it will not recognize the value. (The editor handed over a String, but the List is composed of Number objects, so how can they be equivalent?) In cases such as this, you should either build your own editor or, more simply, disable the editing features of the spinner to restrict the user to the up/down buttons:

Integer[] bills = new Integer[] { new Integer(1), new Integer(2), new Integer(5),                                   new Integer(10), new Integer(20) }; JSpinner spinner = new JSpinner(new SpinnerListModel(bills)); ((JSpinner.DefaultEditor)spinner.getEditor( )).getTextField( ).setEditable(false);

For the record, this code snippet happily removes the editing capacity from any spinner not just those built on the ListSpinnerModel.

7.10.3.1 Constructor
public JSpinner.ListEditor(JSpinner spinner)

Create an editor for spinner and register for change events coming from the spinner.

7.10.3.2 Property

As you can see in Table 7-25, the spinner's model is the only property for the ListEditor inner class.

Table 7-25. JSpinner.ListEditor property

Property

Data type

get

is

set

Default value

model

SpinnerListModel

·

     

7.10.4 NumberEditor

The NumberEditor closely resembles the DateEditor. It creates a formatted text field for the display and input of numeric data and can use a custom formatter to alter the syntax of acceptable information.

7.10.4.1 Constructors
public JSpinner.NumberEditor(JSpinner spinner)

Create a standard editor (a formatted text field) for decimal numbers using the model from the given spinner. The format of the number (in the U.S. English locale) is #,##0.### (for example, 6,789.125).

public JSpinner.NumberEditor(JSpinner spinner, String decimalFormatPattern)

Create a standard editor for numbers using the model from the specified spinner. The decimalFormatPattern determines how numbers are shown as well as how they can be entered by a user. The pattern must match the specifications of the java.text.DecimalFormat class. Table 7-26 shows some of the more common elements you might use in such a pattern. Note that the pattern is localized. If your locale uses "," for the decimal separator, that's precisely what appears on the screen. The code you enter should follow the (nonlocalized!) syntax in the DecimalFormat class.

Table 7-26. DecimalFormat common formats

Code

Description

Example usage

#

Digit, zeros don't show

# -> "4", "123456"

0

Digit, zeros show as zeros

0.00 -> "3.14", "250.00"

,

Grouping separator

#,##0 -> "25", "1,250", "3,141,593"

.

Decimal separator

0.# -> "25", "3.1"

-

A (required) minus sign

-#.0## -> "-25.0", "-1.414"

;

Positive and negative pattern separator

#;(#) -> "25", "(32)"

7.10.4.2 Properties

The NumberEditor has two read-only properties (see Table 7-27). Note that these are the same properties the DateEditor has.

Table 7-27. JSpinner.NumberEditor properties

Property

Data type

get

is

set

Default value

format

DecimalFormat

·

   

"#,##0.###"

model

SpinnerNumberModel

·

     

7.10.5 A Custom Editor

"Custom editor" is a bit of a misnomer in this case. While we will install our own editor for a JSpinner, it doesn't allow editing. What we're really after is the rendering facilities that are provided by the editor component. This example does lay out the pieces of the custom editor that make it interesting if you need to build an editor that is not based on JFormattedTextField.

One of the most obvious things missing from JFormattedTextField is the ability to display graphics. We'll build a simple " editor" that displays Icon objects. Figure 7-17 is a quick look at the spinner in action.

Figure 7-17. Our IconEditor used in a JSpinner (before and after pressing the up arrow)
figs/swng2.0717.gif

The code to build a custom editor is not too difficult if you can base your editor on existing components. Our IconEditor class is based on JLabel. The most important step in making the editor render the proper image is registering a ChangeListener with the spinner. (Recall that the spinner fires a ChangeEvent any time the user alters the current value.) Here's the code for IconEditor:

// IconEditor.java // import javax.swing.*; import javax.swing.event.*; public class IconEditor extends JLabel implements ChangeListener {   JSpinner spinner;   Icon icon;   public IconEditor(JSpinner s) {     super((Icon)s.getValue( ), CENTER);     icon = (Icon)s.getValue( );     spinner = s;     spinner.addChangeListener(this);   }   public void stateChanged(ChangeEvent ce) {     icon = (Icon)spinner.getValue( );     setIcon(icon);   }   public JSpinner getSpinner( ) { return spinner; }   public Icon getIcon( ) { return icon; } }

Of course, actual editors that let you modify the value of the spinner without using the up/down buttons require quite a bit more code. But you do have a reference to the spinner for this editor. Once you have a valid value in your custom editor, you just call spinner.setValue( ) to pass the value back to the spinner's model. (The commitEdit( ) method of JSpinner works only on subclasses of JSpinner.DefaultEditor.)

To put your editor into play with a particular spinner, you just call setEditor( ) for the spinner. Here's the code that sets up the simple example shown in Figure 7-17.

// IconSpinner.java // import javax.swing.*; import java.awt.*; public class IconSpinner extends JFrame {   public IconSpinner( ) {     super("JSpinner Icon Test");     setSize(300,80);     setDefaultCloseOperation(EXIT_ON_CLOSE);     Container c = getContentPane( );     c.setLayout(new GridLayout(0,2));     Icon nums[] = new Icon[] {       new ImageIcon("1.gif"),       new ImageIcon("2.gif"),       new ImageIcon("3.gif"),       new ImageIcon("4.gif"),       new ImageIcon("5.gif"),       new ImageIcon("6.gif")     };     JSpinner s1 = new JSpinner(new SpinnerListModel(nums));     s1.setEditor(new IconEditor(s1));     c.add(new JLabel(" Icon Spinner"));     c.add(s1);     setVisible(true);   }   public static void main(String args[]) {     new IconSpinner( );   } }

Notice we didn't have to build a new model for our icons. We certainly could, but the SpinnerListModel does exactly what we need except for rendering the icons. (Try it once without the setEditor( ) line. You should get a standard text field with the name of the image file displayed.) We just set the editor to a new instance of our IconEditor class and we're off and rolling.



Java Swing
Graphic Java 2: Mastering the Jfc, By Geary, 3Rd Edition, Volume 2: Swing
ISBN: 0130796670
EAN: 2147483647
Year: 2001
Pages: 289
Authors: David Geary

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net