This example Java source code file (JSlider.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.swing;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.accessibility.*;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.awt.*;
import java.util.*;
import java.beans.*;
/**
* A component that lets the user graphically select a value by sliding
* a knob within a bounded interval. The knob is always positioned
* at the points that match integer values within the specified interval.
* <p>
* The slider can show both
* major tick marks, and minor tick marks between the major ones. The number of
* values between the tick marks is controlled with
* <code>setMajorTickSpacing and setMinorTickSpacing.
* Painting of tick marks is controlled by {@code setPaintTicks}.
* <p>
* Sliders can also print text labels at regular intervals (or at
* arbitrary locations) along the slider track. Painting of labels is
* controlled by {@code setLabelTable} and {@code setPaintLabels}.
* <p>
* For further information and examples see
* <a
href="http://docs.oracle.com/javase/tutorial/uiswing/components/slider.html">How to Use Sliders</a>,
* a section in <em>The Java Tutorial.
* <p>
* <strong>Warning: Swing is not thread safe. For more
* information see <a
* href="package-summary.html#threading">Swing's Threading
* Policy</a>.
* <p>
* <strong>Warning:
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans™
* has been added to the <code>java.beans package.
* Please see {@link java.beans.XMLEncoder}.
*
* @beaninfo
* attribute: isContainer false
* description: A component that supports selecting a integer value from a range.
*
* @author David Kloba
*/
public class JSlider extends JComponent implements SwingConstants, Accessible {
/**
* @see #getUIClassID
* @see #readObject
*/
private static final String uiClassID = "SliderUI";
private boolean paintTicks = false;
private boolean paintTrack = true;
private boolean paintLabels = false;
private boolean isInverted = false;
/**
* The data model that handles the numeric maximum value,
* minimum value, and current-position value for the slider.
*/
protected BoundedRangeModel sliderModel;
/**
* The number of values between the major tick marks -- the
* larger marks that break up the minor tick marks.
*/
protected int majorTickSpacing;
/**
* The number of values between the minor tick marks -- the
* smaller marks that occur between the major tick marks.
* @see #setMinorTickSpacing
*/
protected int minorTickSpacing;
/**
* If true, the knob (and the data value it represents)
* resolve to the closest tick mark next to where the user
* positioned the knob. The default is false.
* @see #setSnapToTicks
*/
protected boolean snapToTicks = false;
/**
* If true, the knob (and the data value it represents)
* resolve to the closest slider value next to where the user
* positioned the knob.
*/
boolean snapToValue = true;
/**
* Whether the slider is horizontal or vertical
* The default is horizontal.
*
* @see #setOrientation
*/
protected int orientation;
/**
* {@code Dictionary} of what labels to draw at which values
*/
private Dictionary labelTable;
/**
* The changeListener (no suffix) is the listener we add to the
* slider's model. This listener is initialized to the
* {@code ChangeListener} returned from {@code createChangeListener},
* which by default just forwards events
* to {@code ChangeListener}s (if any) added directly to the slider.
*
* @see #addChangeListener
* @see #createChangeListener
*/
protected ChangeListener changeListener = createChangeListener();
/**
* Only one <code>ChangeEvent is needed per slider instance since the
* event's only (read-only) state is the source property. The source
* of events generated here is always "this". The event is lazily
* created the first time that an event notification is fired.
*
* @see #fireStateChanged
*/
protected transient ChangeEvent changeEvent = null;
private void checkOrientation(int orientation) {
switch (orientation) {
case VERTICAL:
case HORIZONTAL:
break;
default:
throw new IllegalArgumentException("orientation must be one of: VERTICAL, HORIZONTAL");
}
}
/**
* Creates a horizontal slider with the range 0 to 100 and
* an initial value of 50.
*/
public JSlider() {
this(HORIZONTAL, 0, 100, 50);
}
/**
* Creates a slider using the specified orientation with the
* range {@code 0} to {@code 100} and an initial value of {@code 50}.
* The orientation can be
* either <code>SwingConstants.VERTICAL or
* <code>SwingConstants.HORIZONTAL.
*
* @param orientation the orientation of the slider
* @throws IllegalArgumentException if orientation is not one of {@code VERTICAL}, {@code HORIZONTAL}
* @see #setOrientation
*/
public JSlider(int orientation) {
this(orientation, 0, 100, 50);
}
/**
* Creates a horizontal slider using the specified min and max
* with an initial value equal to the average of the min plus max.
* <p>
* The <code>BoundedRangeModel that holds the slider's data
* handles any issues that may arise from improperly setting the
* minimum and maximum values on the slider. See the
* {@code BoundedRangeModel} documentation for details.
*
* @param min the minimum value of the slider
* @param max the maximum value of the slider
*
* @see BoundedRangeModel
* @see #setMinimum
* @see #setMaximum
*/
public JSlider(int min, int max) {
this(HORIZONTAL, min, max, (min + max) / 2);
}
/**
* Creates a horizontal slider using the specified min, max and value.
* <p>
* The <code>BoundedRangeModel that holds the slider's data
* handles any issues that may arise from improperly setting the
* minimum, initial, and maximum values on the slider. See the
* {@code BoundedRangeModel} documentation for details.
*
* @param min the minimum value of the slider
* @param max the maximum value of the slider
* @param value the initial value of the slider
*
* @see BoundedRangeModel
* @see #setMinimum
* @see #setMaximum
* @see #setValue
*/
public JSlider(int min, int max, int value) {
this(HORIZONTAL, min, max, value);
}
/**
* Creates a slider with the specified orientation and the
* specified minimum, maximum, and initial values.
* The orientation can be
* either <code>SwingConstants.VERTICAL or
* <code>SwingConstants.HORIZONTAL.
* <p>
* The <code>BoundedRangeModel that holds the slider's data
* handles any issues that may arise from improperly setting the
* minimum, initial, and maximum values on the slider. See the
* {@code BoundedRangeModel} documentation for details.
*
* @param orientation the orientation of the slider
* @param min the minimum value of the slider
* @param max the maximum value of the slider
* @param value the initial value of the slider
*
* @throws IllegalArgumentException if orientation is not one of {@code VERTICAL}, {@code HORIZONTAL}
*
* @see BoundedRangeModel
* @see #setOrientation
* @see #setMinimum
* @see #setMaximum
* @see #setValue
*/
public JSlider(int orientation, int min, int max, int value)
{
checkOrientation(orientation);
this.orientation = orientation;
setModel(new DefaultBoundedRangeModel(value, 0, min, max));
updateUI();
}
/**
* Creates a horizontal slider using the specified
* BoundedRangeModel.
*/
public JSlider(BoundedRangeModel brm)
{
this.orientation = JSlider.HORIZONTAL;
setModel(brm);
updateUI();
}
/**
* Gets the UI object which implements the L&F for this component.
*
* @return the SliderUI object that implements the Slider L&F
*/
public SliderUI getUI() {
return(SliderUI)ui;
}
/**
* Sets the UI object which implements the L&F for this component.
*
* @param ui the SliderUI L&F object
* @see UIDefaults#getUI
* @beaninfo
* bound: true
* hidden: true
* attribute: visualUpdate true
* description: The UI object that implements the slider's LookAndFeel.
*/
public void setUI(SliderUI ui) {
super.setUI(ui);
}
/**
* Resets the UI property to a value from the current look and feel.
*
* @see JComponent#updateUI
*/
public void updateUI() {
setUI((SliderUI)UIManager.getUI(this));
// The labels preferred size may be derived from the font
// of the slider, so we must update the UI of the slider first, then
// that of labels. This way when setSize is called the right
// font is used.
updateLabelUIs();
}
/**
* Returns the name of the L&F class that renders this component.
*
* @return "SliderUI"
* @see JComponent#getUIClassID
* @see UIDefaults#getUI
*/
public String getUIClassID() {
return uiClassID;
}
/**
* We pass Change events along to the listeners with the
* the slider (instead of the model itself) as the event source.
*/
private class ModelListener implements ChangeListener, Serializable {
public void stateChanged(ChangeEvent e) {
fireStateChanged();
}
}
/**
* Subclasses that want to handle {@code ChangeEvent}s
* from the model differently
* can override this to return
* an instance of a custom <code>ChangeListener implementation.
* The default {@code ChangeListener} simply calls the
* {@code fireStateChanged} method to forward {@code ChangeEvent}s
* to the {@code ChangeListener}s that have been added directly to the
* slider.
* @see #changeListener
* @see #fireStateChanged
* @see javax.swing.event.ChangeListener
* @see javax.swing.BoundedRangeModel
*/
protected ChangeListener createChangeListener() {
return new ModelListener();
}
/**
* Adds a ChangeListener to the slider.
*
* @param l the ChangeListener to add
* @see #fireStateChanged
* @see #removeChangeListener
*/
public void addChangeListener(ChangeListener l) {
listenerList.add(ChangeListener.class, l);
}
/**
* Removes a ChangeListener from the slider.
*
* @param l the ChangeListener to remove
* @see #fireStateChanged
* @see #addChangeListener
*/
public void removeChangeListener(ChangeListener l) {
listenerList.remove(ChangeListener.class, l);
}
/**
* Returns an array of all the <code>ChangeListeners added
* to this JSlider with addChangeListener().
*
* @return all of the <code>ChangeListeners added or an empty
* array if no listeners have been added
* @since 1.4
*/
public ChangeListener[] getChangeListeners() {
return listenerList.getListeners(ChangeListener.class);
}
/**
* Send a {@code ChangeEvent}, whose source is this {@code JSlider}, to
* all {@code ChangeListener}s that have registered interest in
* {@code ChangeEvent}s.
* This method is called each time a {@code ChangeEvent} is received from
* the model.
* <p>
* The event instance is created if necessary, and stored in
* {@code changeEvent}.
*
* @see #addChangeListener
* @see EventListenerList
*/
protected void fireStateChanged() {
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i]==ChangeListener.class) {
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
}
}
}
/**
* Returns the {@code BoundedRangeModel} that handles the slider's three
* fundamental properties: minimum, maximum, value.
*
* @return the data model for this component
* @see #setModel
* @see BoundedRangeModel
*/
public BoundedRangeModel getModel() {
return sliderModel;
}
/**
* Sets the {@code BoundedRangeModel} that handles the slider's three
* fundamental properties: minimum, maximum, value.
*<p>
* Attempts to pass a {@code null} model to this method result in
* undefined behavior, and, most likely, exceptions.
*
* @param newModel the new, {@code non-null} <code>BoundedRangeModel to use
*
* @see #getModel
* @see BoundedRangeModel
* @beaninfo
* bound: true
* description: The sliders BoundedRangeModel.
*/
public void setModel(BoundedRangeModel newModel)
{
BoundedRangeModel oldModel = getModel();
if (oldModel != null) {
oldModel.removeChangeListener(changeListener);
}
sliderModel = newModel;
if (newModel != null) {
newModel.addChangeListener(changeListener);
}
if (accessibleContext != null) {
accessibleContext.firePropertyChange(
AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
(oldModel == null
? null : Integer.valueOf(oldModel.getValue())),
(newModel == null
? null : Integer.valueOf(newModel.getValue())));
}
firePropertyChange("model", oldModel, sliderModel);
}
/**
* Returns the slider's current value
* from the {@code BoundedRangeModel}.
*
* @return the current value of the slider
* @see #setValue
* @see BoundedRangeModel#getValue
*/
public int getValue() {
return getModel().getValue();
}
/**
* Sets the slider's current value to {@code n}. This method
* forwards the new value to the model.
* <p>
* The data model (an instance of {@code BoundedRangeModel})
* handles any mathematical
* issues arising from assigning faulty values. See the
* {@code BoundedRangeModel} documentation for details.
* <p>
* If the new value is different from the previous value,
* all change listeners are notified.
*
* @param n the new value
* @see #getValue
* @see #addChangeListener
* @see BoundedRangeModel#setValue
* @beaninfo
* preferred: true
* description: The sliders current value.
*/
public void setValue(int n) {
BoundedRangeModel m = getModel();
int oldValue = m.getValue();
if (oldValue == n) {
return;
}
m.setValue(n);
if (accessibleContext != null) {
accessibleContext.firePropertyChange(
AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
Integer.valueOf(oldValue),
Integer.valueOf(m.getValue()));
}
}
/**
* Returns the minimum value supported by the slider
* from the <code>BoundedRangeModel.
*
* @return the value of the model's minimum property
* @see #setMinimum
* @see BoundedRangeModel#getMinimum
*/
public int getMinimum() {
return getModel().getMinimum();
}
/**
* Sets the slider's minimum value to {@code minimum}. This method
* forwards the new minimum value to the model.
* <p>
* The data model (an instance of {@code BoundedRangeModel})
* handles any mathematical
* issues arising from assigning faulty values. See the
* {@code BoundedRangeModel} documentation for details.
* <p>
* If the new minimum value is different from the previous minimum value,
* all change listeners are notified.
*
* @param minimum the new minimum
* @see #getMinimum
* @see #addChangeListener
* @see BoundedRangeModel#setMinimum
* @beaninfo
* bound: true
* preferred: true
* description: The sliders minimum value.
*/
public void setMinimum(int minimum) {
int oldMin = getModel().getMinimum();
getModel().setMinimum(minimum);
firePropertyChange( "minimum", Integer.valueOf( oldMin ), Integer.valueOf( minimum ) );
}
/**
* Returns the maximum value supported by the slider
* from the <code>BoundedRangeModel.
*
* @return the value of the model's maximum property
* @see #setMaximum
* @see BoundedRangeModel#getMaximum
*/
public int getMaximum() {
return getModel().getMaximum();
}
/**
* Sets the slider's maximum value to {@code maximum}. This method
* forwards the new maximum value to the model.
* <p>
* The data model (an instance of {@code BoundedRangeModel})
* handles any mathematical
* issues arising from assigning faulty values. See the
* {@code BoundedRangeModel} documentation for details.
* <p>
* If the new maximum value is different from the previous maximum value,
* all change listeners are notified.
*
* @param maximum the new maximum
* @see #getMaximum
* @see #addChangeListener
* @see BoundedRangeModel#setMaximum
* @beaninfo
* bound: true
* preferred: true
* description: The sliders maximum value.
*/
public void setMaximum(int maximum) {
int oldMax = getModel().getMaximum();
getModel().setMaximum(maximum);
firePropertyChange( "maximum", Integer.valueOf( oldMax ), Integer.valueOf( maximum ) );
}
/**
* Returns the {@code valueIsAdjusting} property from the model. For
* details on how this is used, see the {@code setValueIsAdjusting}
* documentation.
*
* @return the value of the model's {@code valueIsAdjusting} property
* @see #setValueIsAdjusting
*/
public boolean getValueIsAdjusting() {
return getModel().getValueIsAdjusting();
}
/**
* Sets the model's {@code valueIsAdjusting} property. Slider look and
* feel implementations should set this property to {@code true} when
* a knob drag begins, and to {@code false} when the drag ends.
*
* @param b the new value for the {@code valueIsAdjusting} property
* @see #getValueIsAdjusting
* @see BoundedRangeModel#setValueIsAdjusting
* @beaninfo
* expert: true
* description: True if the slider knob is being dragged.
*/
public void setValueIsAdjusting(boolean b) {
BoundedRangeModel m = getModel();
boolean oldValue = m.getValueIsAdjusting();
m.setValueIsAdjusting(b);
if ((oldValue != b) && (accessibleContext != null)) {
accessibleContext.firePropertyChange(
AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
((oldValue) ? AccessibleState.BUSY : null),
((b) ? AccessibleState.BUSY : null));
}
}
/**
* Returns the "extent" from the <code>BoundedRangeModel.
* This represents the range of values "covered" by the knob.
*
* @return an int representing the extent
* @see #setExtent
* @see BoundedRangeModel#getExtent
*/
public int getExtent() {
return getModel().getExtent();
}
/**
* Sets the size of the range "covered" by the knob. Most look
* and feel implementations will change the value by this amount
* if the user clicks on either side of the knob. This method just
* forwards the new extent value to the model.
* <p>
* The data model (an instance of {@code BoundedRangeModel})
* handles any mathematical
* issues arising from assigning faulty values. See the
* {@code BoundedRangeModel} documentation for details.
* <p>
* If the new extent value is different from the previous extent value,
* all change listeners are notified.
*
* @param extent the new extent
* @see #getExtent
* @see BoundedRangeModel#setExtent
* @beaninfo
* expert: true
* description: Size of the range covered by the knob.
*/
public void setExtent(int extent) {
getModel().setExtent(extent);
}
/**
* Return this slider's vertical or horizontal orientation.
* @return {@code SwingConstants.VERTICAL} or
* {@code SwingConstants.HORIZONTAL}
* @see #setOrientation
*/
public int getOrientation() {
return orientation;
}
/**
* Set the slider's orientation to either {@code SwingConstants.VERTICAL} or
* {@code SwingConstants.HORIZONTAL}.
*
* @param orientation {@code HORIZONTAL} or {@code VERTICAL}
* @throws IllegalArgumentException if orientation is not one of {@code VERTICAL}, {@code HORIZONTAL}
* @see #getOrientation
* @beaninfo
* preferred: true
* bound: true
* attribute: visualUpdate true
* description: Set the scrollbars orientation to either VERTICAL or HORIZONTAL.
* enum: VERTICAL JSlider.VERTICAL
* HORIZONTAL JSlider.HORIZONTAL
*
*/
public void setOrientation(int orientation)
{
checkOrientation(orientation);
int oldValue = this.orientation;
this.orientation = orientation;
firePropertyChange("orientation", oldValue, orientation);
if ((oldValue != orientation) && (accessibleContext != null)) {
accessibleContext.firePropertyChange(
AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
((oldValue == VERTICAL)
? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL),
((orientation == VERTICAL)
? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL));
}
if (orientation != oldValue) {
revalidate();
}
}
/**
* {@inheritDoc}
*
* @since 1.6
*/
public void setFont(Font font) {
super.setFont(font);
updateLabelSizes();
}
/**
* {@inheritDoc}
* @since 1.7
*/
public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
if (!isShowing()) {
return false;
}
// Check that there is a label with such image
Enumeration elements = labelTable.elements();
while (elements.hasMoreElements()) {
Component component = (Component) elements.nextElement();
if (component instanceof JLabel) {
JLabel label = (JLabel) component;
if (SwingUtilities.doesIconReferenceImage(label.getIcon(), img) ||
SwingUtilities.doesIconReferenceImage(label.getDisabledIcon(), img)) {
return super.imageUpdate(img, infoflags, x, y, w, h);
}
}
}
return false;
}
/**
* Returns the dictionary of what labels to draw at which values.
*
* @return the <code>Dictionary containing labels and
* where to draw them
*/
public Dictionary getLabelTable() {
/*
if ( labelTable == null && getMajorTickSpacing() > 0 ) {
setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
}
*/
return labelTable;
}
/**
* Used to specify what label will be drawn at any given value.
* The key-value pairs are of this format:
* <code>{ Integer value, java.swing.JComponent label }.
* <p>
* An easy way to generate a standard table of value labels is by using the
* {@code createStandardLabels} method.
* <p>
* Once the labels have been set, this method calls {@link #updateLabelUIs}.
* Note that the labels are only painted if the {@code paintLabels}
* property is {@code true}.
*
* @param labels new {@code Dictionary} of labels, or {@code null} to
* remove all labels
* @see #createStandardLabels(int)
* @see #getLabelTable
* @see #setPaintLabels
* @beaninfo
* hidden: true
* bound: true
* attribute: visualUpdate true
* description: Specifies what labels will be drawn for any given value.
*/
public void setLabelTable( Dictionary labels ) {
Dictionary oldTable = labelTable;
labelTable = labels;
updateLabelUIs();
firePropertyChange("labelTable", oldTable, labelTable );
if (labels != oldTable) {
revalidate();
repaint();
}
}
/**
* Updates the UIs for the labels in the label table by calling
* {@code updateUI} on each label. The UIs are updated from
* the current look and feel. The labels are also set to their
* preferred size.
*
* @see #setLabelTable
* @see JComponent#updateUI
*/
protected void updateLabelUIs() {
Dictionary labelTable = getLabelTable();
if (labelTable == null) {
return;
}
Enumeration labels = labelTable.keys();
while ( labels.hasMoreElements() ) {
JComponent component = (JComponent) labelTable.get(labels.nextElement());
component.updateUI();
component.setSize(component.getPreferredSize());
}
}
private void updateLabelSizes() {
Dictionary labelTable = getLabelTable();
if (labelTable != null) {
Enumeration labels = labelTable.elements();
while (labels.hasMoreElements()) {
JComponent component = (JComponent) labels.nextElement();
component.setSize(component.getPreferredSize());
}
}
}
/**
* Creates a {@code Hashtable} of numerical text labels, starting at the
* slider minimum, and using the increment specified.
* For example, if you call <code>createStandardLabels( 10 )
* and the slider minimum is zero,
* then labels will be created for the values 0, 10, 20, 30, and so on.
* <p>
* For the labels to be drawn on the slider, the returned {@code Hashtable}
* must be passed into {@code setLabelTable}, and {@code setPaintLabels}
* must be set to {@code true}.
* <p>
* For further details on the makeup of the returned {@code Hashtable}, see
* the {@code setLabelTable} documentation.
*
* @param increment distance between labels in the generated hashtable
* @return a new {@code Hashtable} of labels
* @see #setLabelTable
* @see #setPaintLabels
* @throws IllegalArgumentException if {@code increment} is less than or
* equal to zero
*/
public Hashtable createStandardLabels( int increment ) {
return createStandardLabels( increment, getMinimum() );
}
/**
* Creates a {@code Hashtable} of numerical text labels, starting at the
* starting point specified, and using the increment specified.
* For example, if you call
* <code>createStandardLabels( 10, 2 ),
* then labels will be created for the values 2, 12, 22, 32, and so on.
* <p>
* For the labels to be drawn on the slider, the returned {@code Hashtable}
* must be passed into {@code setLabelTable}, and {@code setPaintLabels}
* must be set to {@code true}.
* <p>
* For further details on the makeup of the returned {@code Hashtable}, see
* the {@code setLabelTable} documentation.
*
* @param increment distance between labels in the generated hashtable
* @param start value at which the labels will begin
* @return a new {@code Hashtable} of labels
* @see #setLabelTable
* @see #setPaintLabels
* @exception IllegalArgumentException if {@code start} is
* out of range, or if {@code increment} is less than or equal
* to zero
*/
public Hashtable createStandardLabels( int increment, int start ) {
if ( start > getMaximum() || start < getMinimum() ) {
throw new IllegalArgumentException( "Slider label start point out of range." );
}
if ( increment <= 0 ) {
throw new IllegalArgumentException( "Label incremement must be > 0" );
}
class SmartHashtable extends Hashtable<Object, Object> implements PropertyChangeListener {
int increment = 0;
int start = 0;
boolean startAtMin = false;
class LabelUIResource extends JLabel implements UIResource {
public LabelUIResource( String text, int alignment ) {
super( text, alignment );
setName("Slider.label");
}
public Font getFont() {
Font font = super.getFont();
if (font != null && !(font instanceof UIResource)) {
return font;
}
return JSlider.this.getFont();
}
public Color getForeground() {
Color fg = super.getForeground();
if (fg != null && !(fg instanceof UIResource)) {
return fg;
}
if (!(JSlider.this.getForeground() instanceof UIResource)) {
return JSlider.this.getForeground();
}
return fg;
}
}
public SmartHashtable( int increment, int start ) {
super();
this.increment = increment;
this.start = start;
startAtMin = start == getMinimum();
createLabels();
}
public void propertyChange( PropertyChangeEvent e ) {
if ( e.getPropertyName().equals( "minimum" ) && startAtMin ) {
start = getMinimum();
}
if ( e.getPropertyName().equals( "minimum" ) ||
e.getPropertyName().equals( "maximum" ) ) {
Enumeration keys = getLabelTable().keys();
Hashtable<Object, Object> hashtable = new Hashtable
Other Java examples (source code examples)
Here is a short list of links related to this Java JSlider.java source code file: