< Day Day Up > |
Use a JSlider [133] to let the user easily enter a numeric value bounded by a minimum and maximum value. If the ability to specify precise numbers is important, a slider can be coupled with a formatted text field. If space is limited, a spinner is a possible alternative to a slider.
Try This:
The following code from SliderDemo.java creates the slider in Figure 61. static final int FPS_MIN = 0; static final int FPS_MAX = 30; static final int FPS_INIT = 15; //initial frames per second . . . JSlider framesPerSecond = new JSlider(JSlider.HORIZONTAL, FPS_MIN, FPS_MAX, FPS_INIT); framesPerSecond.addChangeListener(this); //Turn on labels at major tick marks. framesPerSecond.setMajorTickSpacing(10); framesPerSecond.setMinorTickSpacing(1); framesPerSecond.setPaintTicks(true); framesPerSecond.setPaintLabels(true); Figure 61. A picture of an application that uses a slider to control animation speed.
By default, spacing for major and minor tick marks is zero. To see tick marks, you must explicitly set the spacing for either major or minor tick marks (or both) to a nonzero value and call setPaintTicks(true) . Just calling setPaintTicks(true) is not enough. To display standard, numeric labels at major tick mark locations, set the major tick spacing, then call setPaintLabels(true) . The example program provides labels for its slider this way. But you don't have to settle for these labels. The next section, Customizing Labels on a Slider, shows you how to customize slider labels. When you move the slider's knob, the stateChanged method of the slider's ChangeListener is called. For information about change listeners, refer to How to Write a Change Listener (page 652). Here's the change listener code that reacts to slider value changes: public void stateChanged(ChangeEvent e) { JSlider source = (JSlider)e.getSource(); if (!source.getValueIsAdjusting()) { int fps = (int)source.getValue(); if (fps == 0) { if (!frozen) stopAnimation(); } else { delay = 1000 / fps; timer.setDelay(delay); timer.setInitialDelay(delay * 10); if (frozen) startAnimation(); } } } Notice that our stateChanged method changes the animation speed only if getValueIs-Adjusting returns false. Many change events are fired as the user moves the slider knob. This program is interested only in the final result of the user's action. Customizing Labels on a SliderFigure 62 shows a modified version of the previous program that uses a slider with custom labels. Figure 62. The SliderDemo2 example, which uses three custom labels: Fast, Slow , and Stop .
//Create the slider JSlider framesPerSecond = new JSlider(JSlider.VERTICAL, FPS_MIN, FPS_MAX, FPS_INIT); framesPerSecond.addChangeListener(this); framesPerSecond.setMajorTickSpacing(10); framesPerSecond.setPaintTicks(true); //Create the label table Hashtable labelTable = new Hashtable(); labelTable.put( new Integer( 0 ), new JLabel("Stop") ); labelTable.put( new Integer( FPS_MAX/10 ), new JLabel("Slow") ); labelTable.put( new Integer( FPS_MAX ), new JLabel("Fast") ); framesPerSecond.setLabelTable( labelTable ); framesPerSecond.setPaintLabels(true); Each key-value pair in the hashtable specified with setLabelTable gives the position and the value of one label. The hashtable key must be an Integer and a value within the slider's range at which to place the label. The hashtable value associated with each key must be a Component . This program uses JLabel instances with text only. An interesting variation would be to use JLabel instances with icons, or perhaps buttons that move the knob to the label's position. If you want a set of numeric labels positioned at a specific interval, you can use JSlider 's createStandardLabels method to create the Hashtable for you. You can also modify the table returned by createStandardLabels to then customize it. Using a Formatted Text Field with a Slider
Figure 63. A screenshot of SliderDemo3 , which uses a formatted text field that lets the user enter the number of frames per second.
The next few code snippets show the code in SliderDemo3.java that supports the formatted text field. If you find it hard to understand, you might want to refer to How to Use Formatted Text Fields (page 221). The following snippet creates the text field and its formatter. The formatter is created using an integer NumberFormat , and the number formatter's minimum and maximum are set to the same values used for the slider. JFormattedTextField textField; ... //Where the components are created: java.text.NumberFormat numberFormat = java.text.NumberFormat.getIntegerInstance(); NumberFormatter formatter = new NumberFormatter(numberFormat); formatter.setMinimum(new Integer(FPS_MIN)); formatter.setMaximum(new Integer(FPS_MAX)); textField = new JFormattedTextField(formatter); textField.setValue(new Integer(FPS_INIT)); textField.setColumns(5); //get some space The rest of the code we'll show you sets up the event handling for the text field. But first you need to know that changing a formatted text field's text property (which always holds data of type String ) doesn't directly change the formatted text field's value property (which, in this example, is a Number ). The value property is set only after a method called commitEdit is invoked on the text field, which typically happens when the text field contains valid text and either the user presses Enter or the text field loses focus. The following code creates a key binding for the Enter key so that whenever the user puts valid text in the text field and presses Enter, the text field's value (a Number ) is set accordingly . (If the text is invalid, the system beeps and selects all the text.) The key binding is created by adding entries to the text field's input and action maps. More information on input and action maps is in How to Use Key Bindings (page 623). textField.getInputMap().put(KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0), "check"); textField.getActionMap().put("check", anAction); ... //Where anAction is implemented (as a subclass of AbstractAction): public void actionPerformed(ActionEvent e) { if (!textField.isEditValid()) { //The text is invalid. Toolkit.getDefaultToolkit().beep(); textField.selectAll(); } else try { //The text is valid, textField.commitEdit(); //so use it. } catch (java.text.ParseException exc) { } } The next snippet shows how we make the slider's value change whenever the text field's value changes. Recall that framesPerSecond is the variable that refers to the JSlider . textField.addPropertyChangeListener(this); ... public void propertyChange(PropertyChangeEvent e) { if ("value".equals(e.getPropertyName())) { Number value = (Number)e.getNewValue(); if (framesPerSecond != null && value != null) { framesPerSecond.setValue(value.intValue()); } } } Finally, adding bit of code to the slider's change listener updates the formatted text field whenever the slider's value changes. While the user is dragging the slider, we update the text field's text not its value to prevent the text field's property-change listener from trying to update the slider (which might then try to update the text field, which would try to update the slider, and so on, in an unnecessary and perhaps unending cycle). Once the user has finished dragging the slider, we update the text field's value . public void stateChanged(ChangeEvent e) { JSlider source = (JSlider)e.getSource(); int fps = (int)source.getValue(); if (!source.getValueIsAdjusting()) { //done adjusting textField.setValue(new Integer(fps)); //update ftf value ... } else { //value is adjusting; just set the text textField.setText(String.valueOf(fps)); } } You have seen one possible way of implementing a text field tied to a slider. Other ways are possible, but keep the following rules in mind:
For more information, see How to Use Formatted Text Fields (page 221). The Slider APITables 72 through 75 list the commonly used JSlider constructors and methods. See The JComponent Class (page 53) for tables of commonly used inherited methods . Also refer to the JSlider API documentation at: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JSlider.html. Table 72. Creating the Slider
Table 73. Fine-Tuning the Slider's Appearance
Table 74. Watching the Slider Operate
Table 75. Working Directly with the Data Model
Examples That Use SlidersThis table shows examples that use JSlider and where those examples are described.
|
< Day Day Up > |