33.7. Key Terms

 
[Page 1018 ( continued )]

30.6. Spinner Models and Editors

SpinnerModel is an interface for all spinner models. AbstractSpinnerModel is a convenient abstract class that implements SpinnerModel and provides the implementation for its registration/deregistration methods . SpinnerListModel , SpinnerNumberModel , and SpinnerDateModel are concrete implementations of SpinnerModel . The relationship among them is illustrated in Figure 30.10. Besides these models, you can create a custom spinner model that extends AbstractSpinnerModel or directly implements SpinnerModel .

Figure 30.10. SpinnerListModel , SpinnerNumberModel , and SpinnerDateModel are concrete implementations of SpinnerModel .
(This item is displayed on page 1019 in the print version)

30.6.1. SpinnerListModel

SpinnerListModel (see Figure 30.11) is a simple implementation of SpinnerModel whose values are stored in a java.util.List .


[Page 1019]
Figure 30.11. SpinnerListModel uses a java.util.List to store a sequence of data in the model.

You can create a SpinnerListModel using an array or a list. For example, the following code creates a model that consists of the values Freshman, Sophomore, Junior, Senior, and Graduate in an array:

  // Create an array  String[] grades = {   "Freshman"   ,   "Sophomore"   ,   "Junior"   ,   "Senior"   ,   "Graduate"   };  // Create a model from an array  model =   new   SpinnerListModel(grades); 

Alternatively, the following code creates a model using a list:

  // Create an array  String[] grades = {   "Freshman"   ,   "Sophomore"   ,   "Junior"   ,   "Senior"   ,   "Graduate"   };  // Create an array list from the array  list =   new   ArrayList(  Arrays.asList(grades)  );  // Create a model from list  model =   new   SpinnerListModel(list); 

The alternative code seems unnecessary. However, it is useful if you need to add or remove elements from the model. The size of an array is fixed once an array is created. The list is a flexible data structure that enables you to add or remove elements dynamically.


[Page 1020]

30.6.2. SpinnerNumberModel

SpinnerNumberModel (see Figure 30.12) is a concrete implementation of SpinnerModel that represents a sequence of numbers . It contains the properties maximum , minimum , and stepSize . The maximum and minimum properties specify the upper and lower bounds of the sequence. The stepSize specifies the size of the increase or decrease computed by the nextValue and previousValue methods defined in SpinnerModel . The minimum and maximum properties can be null to indicate that the sequence has no lower or upper limit. All of the properties in this class are defined in terms of two generic types, Number and Comparable , so that all Java numeric types may be accommodated. Internally, only the values with type Double , Float , Long , Integer , Short , or Byte are supported.

Figure 30.12. SpinnerNumberModel represents a sequence of numbers.

You can create a SpinnerNumberModel with integers or double. For example, the following code creates a model that represents a sequence of numbers from to 3000 with initial value 2004 and interval 1 :

  // Create a spinner number model  SpinnerNumberModel model =   new   SpinnerNumberModel(   2004   ,     ,   3000   ,   1   ); 

The following code creates a model that represents a sequence of numbers from to 120 with initial value 50 and interval 0.1 :

  // Create a spinner number model  SpinnerNumberModel model =   new   SpinnerNumberModel(   50   ,     ,   120   ,   0.1   ); 

30.6.3. SpinnerDateModel

SpinnerDateModel (see Figure 30.13) is a concrete implementation of SpinnerModel that represents a sequence of dates. The upper and lower bounds of the sequence are defined by properties called start and end , and the size of the increase or decrease computed by the nextValue and previousValue methods is defined by a property called calendarField .


[Page 1021]
Figure 30.13. SpinnerDateModel represents a sequence of dates.

The start and end properties can be null to indicate that the sequence has no lower or upper limit. The value of the calendarField property must be one of the java.util.Calendar constants that specify a field within a Calendar. The getNextValue and getPreviousValue methods change the date forward or backward by this amount. For example, if calendarField is Calendar.DAY_OF_WEEK , then nextValue produces a date that is twenty-four hours after the current value, and previousValue produces a date that is twenty-four hours earlier.

For example, the following code creates a spinner model that represents a sequence of dates, starting from the current date without a lower or upper limit and with calendar field on month.

 SpinnerDateModel model =   new   SpinnerDateModel(   new   Date(),   null   ,   null   , Calendar.MONTH); 

30.6.4. Spinner Editors

A JSpinner has a single child component, called the editor , which is responsible for displaying the current element or value of the model. Four editors are defined as static inner classes inside JSpinner .

  • JSpinner.DefaultEditor is a simple base class for all other specialized editors to display a read-only view of the model's current value with a JFormattedTextField . JFormattedTextField extends JTextField adding support for formatting arbitrary values, as well as retrieving a particular object once the user has edited the text.

  • JSpinner.NumberEditor is a specialized editor for a JSpinner whose model is a SpinnerNumberModel . The value of the editor is displayed with a JFormattedTextField whose format is defined by a NumberFormatter instance.

  • JSpinner.DateEditor is a specialized editor for a JSpinner whose model is a SpinnerDateModel . The value of the editor is displayed with a JFormattedTextField whose format is defined by a DateFormatter instance.

  • JSpinner.ListEditor is a specialized editor for a JSpinner whose model is a SpinnerListModel . The value of the editor is displayed with a JFormattedTextField .


[Page 1022]

The JSpinner 's constructor creates a NumberEditor for SpinnerNumberModel , a DateEditor for SpinnerDateModel , a ListEditor for SpinnerListModel , and a DefaultEditor for all other models. The editor can also be changed using the setEditor method. The JSpinner 's editor stays in sync with the model by listening for ChangeEvent s. The commitEdit() method should be used to commit the currently edited value to the model.

30.6.5. Example: Using Spinner Models and Editors

This example uses a JSpinner component to display the date and three other JSpinner components to display the day in a sequence of numbers, the month in a sequence of strings, and the year in a sequence of numbers, as shown in Figure 30.14. All four components are synchronized. For example, if you change the year in the spinner for year, the date value in the date spinner is updated accordingly . The source code of the example is given in Listing 30.6.

Figure 30.14. The four spinner components are synchronized to display the date in one field and the day, month, and year in three separate fields.


Listing 30.6. SpinnerModelEditorDemo.java
(This item is displayed on pages 1022 - 1024 in the print version)
 1   import   javax.swing.*; 2   import   javax.swing.event.*; 3   import   java.util.*; 4   import   java.text.*; 5   import   java.awt.*; 6 7   public class   SpinnerModelEditorDemo   extends   JApplet { 8  // Create four spinners for date, day, month, and year  9   private   JSpinner spinnerDate = 10    new   JSpinner(   new   SpinnerDateModel())  ; 11   private   JSpinner spinnerDay = 12    new   JSpinner(   new   SpinnerNumberModel(   1   ,   1   ,   31   ,   1   ))  ; 13   private   String[] monthNames =   new   DateFormatSymbols().getMonths(); 14   private   JSpinner spinnerMonth =   new   JSpinner 15 (    new   SpinnerListModel(Arrays.asList(monthNames).subList(     ,   12   ))  ); 16   private   JSpinner spinnerYear = 17    new   JSpinner(  new  SpinnerNumberModel(   2004   ,   1   ,   3000   ,   1   ))  ; 18 19   public   SpinnerModelEditorDemo() { 20  // Group labels  21 JPanel panel1 =   new   JPanel(); 22 panel1.setLayout(   new   GridLayout(   4   ,   1   )); 23 panel1.add(   new   JLabel(   "Date"   )); 24 panel1.add(   new   JLabel(   "Day"   )); 25 panel1.add(   new   JLabel(   "Month"   )); 26 panel1.add(   new   JLabel(   "Year"   )); 27 28  // Group spinners  29 JPanel panel2 =   new   JPanel(); 30 panel2.setLayout(   new   GridLayout(   4   ,   1   )); 31  panel2.add(spinnerDate);  32  panel2.add(spinnerDay);  33  panel2.add(spinnerMonth);  

[Page 1023]
 34  panel2.add(spinnerYear);  35 36  // Add spinner and label to the UI  37 add(panel1, BorderLayout.WEST); 38 add(panel2, BorderLayout.CENTER); 39 40  // Set editor for date  41 JSpinner.DateEditor dateEditor = 42    new   JSpinner.DateEditor(spinnerDate,   "MMM dd, yyyy"   )  ; 43 spinnerDate.setEditor(dateEditor); 44 45  // Set editor for year  46 JSpinner.NumberEditor yearEditor = 47    new   JSpinner.NumberEditor(spinnerYear,   "####"   )  ; 48 spinnerYear.setEditor(yearEditor); 49 50  // Update date to synchronize with the day, month, and year  51 updateDate(); 52 53  // Register and create a listener for spinnerDay  54  spinnerDay.addChangeListener(   new   ChangeListener()  { 55    public void   stateChanged(javax.swing.event.ChangeEvent e)  { 56 updateDate(); 57 } 58 }); 59 60  // Register and create a listener for spinnerMonth  61  spinnerDay.addChangeListener(   new   ChangeListener()  { 62    public void   stateChanged(javax.swing.event.ChangeEvent e)  { 63 updateDate(); 64 } 65 }); 66 67  // Register and create a listener for spinnerYear  68 spinnerMonth.addChangeListener(   new   ChangeListener() { 69   public void   stateChanged(javax.swing.event.ChangeEvent e) { 70 updateDate(); 71 } 72 }); 73 } 74 75  // Update date spinner to synchronize with the other three spinners  76   private void   updateDate() { 77  // Get current month and year in int  78   int   month = ((SpinnerListModel)  spinnerMonth.getModel()  ). 79 getList().indexOf(  spinnerMonth.getValue()  ); 80   int   year = ((Integer)  spinnerYear.getValue()  ).intValue(); 81 82  // Set a new maximum number of days for the new month and year  83 SpinnerNumberModel numberModel = 84 (SpinnerNumberModel);  spinnerDay.getModel()  85  numberModel.setMaximum  (   new   Integer(maxDaysInMonth(year, month))); 86 87  // Set a new current day if it exceeds the maximum  88   if   (((Integer)(  numberModel.getValue()  )).intValue() > 89 maxDaysInMonth(year, month)) 90  numberModel.setValue  (   new   Integer(maxDaysInMonth(year, month))); 91 92  // Get the current day  93   int   day = ((Integer)spinnerDay.getValue()).intValue(); 

[Page 1024]
 94 95  // Set a new date in the date spinner  96 spinnerDate.setValue( 97   new   GregorianCalendar(year, month, day).getTime()); 98 } 99 100  /** Return the maximum number of days in a month. For example,  101  Feb 2004 has 29 days. */  102   private int   maxDaysInMonth(   int   year,   int   month) { 103 Calendar calendar =   new   GregorianCalendar(year, month,   1   ); 104   return   calendar.getActualMaximum(Calendar.DAY_OF_MONTH); 105 } 106 } 

A JSpinner object for dates, spinnerDate , is created with a default SpinnerDateModel (lines 9 “10). The format of the date displayed in the spinner is MMM dd, yyyy (e.g., Feb 01, 2006). This format is created using the JSpinner 's inner class constructor DateEditor (lines 41 “42) and is set as spinnerDate 's editor (line 43).

A JSpinner object for days, spinnerDay , is created with a SpinnerNumberModel with a sequence of integers between 1 and 31 in which the initial value is 1 and the interval is 1 (lines 11 “12). The maximum number is reset in the updateDate() method based on the current month and year (lines 88 “90). For example, February 2004 has twenty-nine days, so the maximum in spinnerDay is set to 29 for February 2004.

A JSpinner object for months, spinnerMonth , is created with a SpinnerListModel with a list of month names (lines 14 “15). Month names are locale-specific and can be obtained using the new DateFormatSymbols().getMonths() (line 13). Some calendars can have thirteen months. Arrays.asList(monthNames) creates a list from an array of strings, and subList(0, 12) returns the first twelve elements in the list.

A JSpinner object for years , spinnerYear , is created with a SpinnerNumberModel with a sequence of integers between 1 and 3000 in which the initial value is 2004 and the interval is 1 (lines 16 “17). By default, locale-specific number separators are used. For example, 2004 would be displayed as 2,004 in the spinner. To display the number without separators, the number pattern #### is specified to construct a new NumberEditor for spinnerYear (lines 46 “47). The editor is set as spinnerYear 's editor (line 48).

The updateDate() method synchronizes the date spinner with the day, month, and year spinners. Whenever a new value is selected in the day, month, or year spinner, a new date is set in the date spinner. The maxDaysInMonth method (lines 102 “105) returns the maximum number of days in a month. For example, February 2004 has twenty nine days.

A JSpinner object can fire javax.swing.event.ChangeEvent to notify the listeners of the state change in the spinner. The anonymous event adapters are created to process spinner state changes for the day, month, and year spinners (lines 53 “72). Whenever a new value is selected in one of these three spinners, the date spinner value is updated accordingly. In Exercise 30.3, you will improve the example to synchronize the day, month, and year spinners with the date spinner. Then, when a new value is selected in the date spinner, the values in the day, month, and year spinners will be updated accordingly.

This example uses SpinnerNumberModel , SpinnerDateModel , and SpinnerListModel . They are predefined concrete spinner models in the API. You can also create custom spinner models (see Exercise 30.4).

 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

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