Extending JSlider
The previous section showed how to configure the label table for a slider. This was adequate for one-shot configurations. However, to create a general-purpose formatted text slider, an extension to the JSlider class is called for. Luckily, the JSlider class provides the necessary hooks to make this an easy task. The JSlider class calls the createStandardLabels method to create the labels displayed in the slider. Our extension can override this method to create the formatted labels.
Listing 10.19 shows the PercentSlider class, which extends the JSlider class. Its public API is identical to the JSlider class, with the exception of the setLabelTable method. This method is not available in the PercentSlider class. This is because creating the label table for the class is the primary purpose of the PercentSlider class. Allowing users to set this table could remove the percent signs on the labels. Another enhancement of the PercentSlider is that the labels are created whenever the major tick spacing changes. This allows an existing percent slider to be reconfigured. The current implementation of the JSlider class does not allow thisonce the labels are created, they are used for the duration of the classs lifetime, unless the user explicitly sets or recreates the table.
Listing 10.19 The PercentSlider Class
package com.foley.utility;
import java.text.NumberFormat;
import java.util.Hashtable;
import javax.swing.*;
/**
* The PercentSlider class is a slider that formats its
* labels using the % sign.
* <p>
* @author Mike Foley
**/
public class PercentSlider extends JSlider
{
/**
* PercentSlider, constructor
* <p>
* Configure the slider for normal percent range,
* 0100 and a current value of 0. The default major
* tick spacing is set to 25 and minor tick spacing
* to 5. Both labels and ticks are painted.
* <p>
* These values may be changed by the client using the
* public API.
*
* @see JSlider
**/
public PercentSlider() {
setMinimum( 0 );
setMaximum( 100 );
setValue( 0 );
setMajorTickSpacing( 25 );
setMinorTickSpacing( 5 );
setPaintTicks( true );
setPaintLabels( true );
}
/**
* Create labels for the slider. Format each label
* to contain a percent sign. A label is created
* for each value from:
* <p>
* start + x * increment
* <p>
* until the maximum value is reached.
* <p>
* @param increment The delta between labels.
* @param start The value of the first label.
* @return The table of labels for the slider.
**/
public Hashtable createStandardLabels( int increment, int start ) {
if ( start > getMaximum() || start < getMinimum() ) {
throw new IllegalArgumentException(
Slider label start point out of range. );
}
NumberFormat percent = NumberFormat.getPercentInstance();
Hashtable table = new Hashtable();
for ( int i = start; i <= getMaximum(); i += increment ) {
JLabel l = new JLabel(
percent.format( ( double )i / 100.0 ) );
table.put( new Integer( i ), l );
}
return table;
}
/**
* The label table is created by this class. Do not
* allow it to be set from the outside.
* <p>
* @exception RuntimeException If this method is called.
**/
public void setLabelTable() {
throw new RuntimeException(
Cannot set the label table for the PercentSlider );
}
/**
* setMajorTickSpacing
* <p>
* This method in the JSlider class does not create
* labels if the label table has been created once.
* This may cause the labels to be drawn in areas that
* do not correspond to the major ticks. This is fixed
* here by creating the label table whenever a new
* major tick spacing is specified.
* <p>
* @param n The new major tick spacing.
**/
public void setMajorTickSpacing( int n ) {
if( getMajorTickSpacing() != n )
setLabelTable( createStandardLabels( n ) );
super.setMajorTickSpacing( n );
}
} // PercentSlider
The PercentSliderTest application can be modified to display an instance of the PercentSlider class. The following code can be used instead of the code to create and configure the JSlider. The modified PercentSliderTest application produces a slider that looks identical to the previous version of the application, shown in Figure 10.14.
JSlider percentSlider = new PercentSlider();
percentSlider.setBorder( BorderFactory.createLoweredBevelBorder() );
frame.getContentPane().add( percentSlider, BorderLayout.CENTER );
|