src/share/classes/javax/swing/JSlider.java

Print this page




 121 
 122     /**
 123      * If true, the knob (and the data value it represents)
 124      * resolve to the closest slider value next to where the user
 125      * positioned the knob.
 126      */
 127     boolean snapToValue = true;
 128 
 129     /**
 130      * Whether the slider is horizontal or vertical
 131      * The default is horizontal.
 132      *
 133      * @see #setOrientation
 134      */
 135     protected int orientation;
 136 
 137 
 138     /**
 139      * {@code Dictionary} of what labels to draw at which values
 140      */
 141     private Dictionary labelTable;
 142 
 143 
 144     /**
 145      * The changeListener (no suffix) is the listener we add to the
 146      * slider's model.  This listener is initialized to the
 147      * {@code ChangeListener} returned from {@code createChangeListener},
 148      * which by default just forwards events
 149      * to {@code ChangeListener}s (if any) added directly to the slider.
 150      *
 151      * @see #addChangeListener
 152      * @see #createChangeListener
 153      */
 154     protected ChangeListener changeListener = createChangeListener();
 155 
 156 
 157     /**
 158      * Only one <code>ChangeEvent</code> is needed per slider instance since the
 159      * event's only (read-only) state is the source property.  The source
 160      * of events generated here is always "this". The event is lazily
 161      * created the first time that an event notification is fired.


 752     /**
 753      * {@inheritDoc}
 754      *
 755      * @since 1.6
 756      */
 757     public void setFont(Font font) {
 758         super.setFont(font);
 759         updateLabelSizes();
 760     }
 761 
 762     /**
 763      * {@inheritDoc}
 764      * @since 1.7
 765      */
 766     public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
 767         if (!isShowing()) {
 768             return false;
 769         }
 770 
 771         // Check that there is a label with such image
 772         Enumeration elements = labelTable.elements();
 773 
 774         while (elements.hasMoreElements()) {
 775             Component component = (Component) elements.nextElement();
 776 
 777             if (component instanceof JLabel) {
 778                 JLabel label = (JLabel) component;
 779 
 780                 if (SwingUtilities.doesIconReferenceImage(label.getIcon(), img) ||
 781                         SwingUtilities.doesIconReferenceImage(label.getDisabledIcon(), img)) {
 782                     return super.imageUpdate(img, infoflags, x, y, w, h);
 783                 }
 784             }
 785         }
 786 
 787         return false;
 788     }
 789 
 790     /**
 791      * Returns the dictionary of what labels to draw at which values.
 792      *
 793      * @return the <code>Dictionary</code> containing labels and
 794      *    where to draw them
 795      */
 796     public Dictionary getLabelTable() {
 797 /*
 798         if ( labelTable == null && getMajorTickSpacing() > 0 ) {
 799             setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
 800         }
 801 */
 802         return labelTable;
 803     }
 804 
 805 
 806     /**
 807      * Used to specify what label will be drawn at any given value.
 808      * The key-value pairs are of this format:
 809      * <code>{ Integer value, java.swing.JComponent label }</code>.
 810      * <p>
 811      * An easy way to generate a standard table of value labels is by using the
 812      * {@code createStandardLabels} method.
 813      * <p>
 814      * Once the labels have been set, this method calls {@link #updateLabelUIs}.
 815      * Note that the labels are only painted if the {@code paintLabels}
 816      * property is {@code true}.
 817      *
 818      * @param labels new {@code Dictionary} of labels, or {@code null} to
 819      *        remove all labels
 820      * @see #createStandardLabels(int)
 821      * @see #getLabelTable
 822      * @see #setPaintLabels
 823      * @beaninfo
 824      *       hidden: true
 825      *        bound: true
 826      *    attribute: visualUpdate true
 827      *  description: Specifies what labels will be drawn for any given value.
 828      */
 829     public void setLabelTable( Dictionary labels ) {
 830         Dictionary oldTable = labelTable;
 831         labelTable = labels;
 832         updateLabelUIs();
 833         firePropertyChange("labelTable", oldTable, labelTable );
 834         if (labels != oldTable) {
 835             revalidate();
 836             repaint();
 837         }
 838     }
 839 
 840 
 841     /**
 842      * Updates the UIs for the labels in the label table by calling
 843      * {@code updateUI} on each label.  The UIs are updated from
 844      * the current look and feel.  The labels are also set to their
 845      * preferred size.
 846      *
 847      * @see #setLabelTable
 848      * @see JComponent#updateUI
 849      */
 850     protected void updateLabelUIs() {
 851         Dictionary labelTable = getLabelTable();
 852 
 853         if (labelTable == null) {
 854             return;
 855         }
 856         Enumeration labels = labelTable.keys();
 857         while ( labels.hasMoreElements() ) {
 858             JComponent component = (JComponent) labelTable.get(labels.nextElement());
 859             component.updateUI();
 860             component.setSize(component.getPreferredSize());
 861         }
 862     }
 863 
 864     private void updateLabelSizes() {
 865         Dictionary labelTable = getLabelTable();
 866         if (labelTable != null) {
 867             Enumeration labels = labelTable.elements();
 868             while (labels.hasMoreElements()) {
 869                 JComponent component = (JComponent) labels.nextElement();
 870                 component.setSize(component.getPreferredSize());
 871             }
 872         }
 873     }
 874 
 875 
 876     /**
 877      * Creates a {@code Hashtable} of numerical text labels, starting at the
 878      * slider minimum, and using the increment specified.
 879      * For example, if you call <code>createStandardLabels( 10 )</code>
 880      * and the slider minimum is zero,
 881      * then labels will be created for the values 0, 10, 20, 30, and so on.
 882      * <p>
 883      * For the labels to be drawn on the slider, the returned {@code Hashtable}
 884      * must be passed into {@code setLabelTable}, and {@code setPaintLabels}
 885      * must be set to {@code true}.
 886      * <p>
 887      * For further details on the makeup of the returned {@code Hashtable}, see
 888      * the {@code setLabelTable} documentation.
 889      *
 890      * @param  increment  distance between labels in the generated hashtable
 891      * @return a new {@code Hashtable} of labels
 892      * @see #setLabelTable
 893      * @see #setPaintLabels
 894      * @throws IllegalArgumentException if {@code increment} is less than or
 895      *          equal to zero
 896      */
 897     public Hashtable createStandardLabels( int increment ) {
 898         return createStandardLabels( increment, getMinimum() );
 899     }
 900 
 901 
 902     /**
 903      * Creates a {@code Hashtable} of numerical text labels, starting at the
 904      * starting point specified, and using the increment specified.
 905      * For example, if you call
 906      * <code>createStandardLabels( 10, 2 )</code>,
 907      * then labels will be created for the values 2, 12, 22, 32, and so on.
 908      * <p>
 909      * For the labels to be drawn on the slider, the returned {@code Hashtable}
 910      * must be passed into {@code setLabelTable}, and {@code setPaintLabels}
 911      * must be set to {@code true}.
 912      * <p>
 913      * For further details on the makeup of the returned {@code Hashtable}, see
 914      * the {@code setLabelTable} documentation.
 915      *
 916      * @param  increment  distance between labels in the generated hashtable
 917      * @param  start      value at which the labels will begin
 918      * @return a new {@code Hashtable} of labels
 919      * @see #setLabelTable
 920      * @see #setPaintLabels
 921      * @exception IllegalArgumentException if {@code start} is
 922      *          out of range, or if {@code increment} is less than or equal
 923      *          to zero
 924      */
 925     public Hashtable createStandardLabels( int increment, int start ) {
 926         if ( start > getMaximum() || start < getMinimum() ) {
 927             throw new IllegalArgumentException( "Slider label start point out of range." );
 928         }
 929 
 930         if ( increment <= 0 ) {
 931             throw new IllegalArgumentException( "Label incremement must be > 0" );
 932         }
 933 
 934         class SmartHashtable extends Hashtable<Object, Object> implements PropertyChangeListener {
 935             int increment = 0;
 936             int start = 0;
 937             boolean startAtMin = false;
 938 
 939             class LabelUIResource extends JLabel implements UIResource {
 940                 public LabelUIResource( String text, int alignment ) {
 941                     super( text, alignment );
 942                     setName("Slider.label");
 943                 }
 944 
 945                 public Font getFont() {
 946                     Font font = super.getFont();
 947                     if (font != null && !(font instanceof UIResource)) {
 948                         return font;
 949                     }
 950                     return JSlider.this.getFont();
 951                 }
 952 
 953                 public Color getForeground() {
 954                     Color fg = super.getForeground();


 961                     return fg;
 962                 }
 963             }
 964 
 965             public SmartHashtable( int increment, int start ) {
 966                 super();
 967                 this.increment = increment;
 968                 this.start = start;
 969                 startAtMin = start == getMinimum();
 970                 createLabels();
 971             }
 972 
 973             public void propertyChange( PropertyChangeEvent e ) {
 974                 if ( e.getPropertyName().equals( "minimum" ) && startAtMin ) {
 975                     start = getMinimum();
 976                 }
 977 
 978                 if ( e.getPropertyName().equals( "minimum" ) ||
 979                      e.getPropertyName().equals( "maximum" ) ) {
 980 
 981                     Enumeration keys = getLabelTable().keys();
 982                     Hashtable<Object, Object> hashtable = new Hashtable<Object, Object>();
 983 
 984                     // Save the labels that were added by the developer
 985                     while ( keys.hasMoreElements() ) {
 986                         Object key = keys.nextElement();
 987                         Object value = labelTable.get(key);
 988                         if ( !(value instanceof LabelUIResource) ) {
 989                             hashtable.put( key, value );
 990                         }
 991                     }
 992 
 993                     clear();
 994                     createLabels();
 995 
 996                     // Add the saved labels
 997                     keys = hashtable.keys();
 998                     while ( keys.hasMoreElements() ) {
 999                         Object key = keys.nextElement();
1000                         put( key, hashtable.get( key ) );
1001                     }
1002 
1003                     ((JSlider)e.getSource()).setLabelTable( this );
1004                 }
1005             }
1006 
1007             void createLabels() {
1008                 for ( int labelIndex = start; labelIndex <= getMaximum(); labelIndex += increment ) {
1009                     put( Integer.valueOf( labelIndex ), new LabelUIResource( ""+labelIndex, JLabel.CENTER ) );
1010                 }
1011             }
1012         }
1013 
1014         SmartHashtable table = new SmartHashtable( increment, start );
1015 
1016         Dictionary labelTable = getLabelTable();
1017 
1018         if (labelTable != null && (labelTable instanceof PropertyChangeListener)) {
1019             removePropertyChangeListener((PropertyChangeListener) labelTable);
1020         }
1021 
1022         addPropertyChangeListener( table );
1023 
1024         return table;
1025     }
1026 
1027 
1028     /**
1029      * Returns true if the value-range shown for the slider is reversed,
1030      *
1031      * @return true if the slider values are reversed from their normal order
1032      * @see #setInverted
1033      */
1034     public boolean getInverted() {
1035         return isInverted;
1036     }




 121 
 122     /**
 123      * If true, the knob (and the data value it represents)
 124      * resolve to the closest slider value next to where the user
 125      * positioned the knob.
 126      */
 127     boolean snapToValue = true;
 128 
 129     /**
 130      * Whether the slider is horizontal or vertical
 131      * The default is horizontal.
 132      *
 133      * @see #setOrientation
 134      */
 135     protected int orientation;
 136 
 137 
 138     /**
 139      * {@code Dictionary} of what labels to draw at which values
 140      */
 141     private Dictionary<Integer, JComponent> labelTable;
 142 
 143 
 144     /**
 145      * The changeListener (no suffix) is the listener we add to the
 146      * slider's model.  This listener is initialized to the
 147      * {@code ChangeListener} returned from {@code createChangeListener},
 148      * which by default just forwards events
 149      * to {@code ChangeListener}s (if any) added directly to the slider.
 150      *
 151      * @see #addChangeListener
 152      * @see #createChangeListener
 153      */
 154     protected ChangeListener changeListener = createChangeListener();
 155 
 156 
 157     /**
 158      * Only one <code>ChangeEvent</code> is needed per slider instance since the
 159      * event's only (read-only) state is the source property.  The source
 160      * of events generated here is always "this". The event is lazily
 161      * created the first time that an event notification is fired.


 752     /**
 753      * {@inheritDoc}
 754      *
 755      * @since 1.6
 756      */
 757     public void setFont(Font font) {
 758         super.setFont(font);
 759         updateLabelSizes();
 760     }
 761 
 762     /**
 763      * {@inheritDoc}
 764      * @since 1.7
 765      */
 766     public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
 767         if (!isShowing()) {
 768             return false;
 769         }
 770 
 771         // Check that there is a label with such image
 772         Enumeration<JComponent> elements = labelTable.elements();
 773 
 774         while (elements.hasMoreElements()) {
 775             JComponent component = elements.nextElement();
 776 
 777             if (component instanceof JLabel) {
 778                 JLabel label = (JLabel) component;
 779 
 780                 if (SwingUtilities.doesIconReferenceImage(label.getIcon(), img) ||
 781                         SwingUtilities.doesIconReferenceImage(label.getDisabledIcon(), img)) {
 782                     return super.imageUpdate(img, infoflags, x, y, w, h);
 783                 }
 784             }
 785         }
 786 
 787         return false;
 788     }
 789 
 790     /**
 791      * Returns the dictionary of what labels to draw at which values.
 792      *
 793      * @return the <code>Dictionary</code> containing labels and
 794      *    where to draw them
 795      */
 796     public Dictionary<Integer, JComponent> getLabelTable() {
 797 /*
 798         if ( labelTable == null && getMajorTickSpacing() > 0 ) {
 799             setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
 800         }
 801 */
 802         return labelTable;
 803     }
 804 
 805 
 806     /**
 807      * Used to specify what label will be drawn at any given value.
 808      * The key-value pairs are of this format:
 809      * <code>{ Integer value, java.swing.JComponent label }</code>.
 810      * <p>
 811      * An easy way to generate a standard table of value labels is by using the
 812      * {@code createStandardLabels} method.
 813      * <p>
 814      * Once the labels have been set, this method calls {@link #updateLabelUIs}.
 815      * Note that the labels are only painted if the {@code paintLabels}
 816      * property is {@code true}.
 817      *
 818      * @param labels new {@code Dictionary} of labels, or {@code null} to
 819      *        remove all labels
 820      * @see #createStandardLabels(int)
 821      * @see #getLabelTable
 822      * @see #setPaintLabels
 823      * @beaninfo
 824      *       hidden: true
 825      *        bound: true
 826      *    attribute: visualUpdate true
 827      *  description: Specifies what labels will be drawn for any given value.
 828      */
 829     public void setLabelTable( Dictionary<Integer, JComponent> labels ) {
 830         Dictionary<Integer, JComponent> oldTable = labelTable;
 831         labelTable = labels;
 832         updateLabelUIs();
 833         firePropertyChange("labelTable", oldTable, labelTable );
 834         if (labels != oldTable) {
 835             revalidate();
 836             repaint();
 837         }
 838     }
 839 
 840 
 841     /**
 842      * Updates the UIs for the labels in the label table by calling
 843      * {@code updateUI} on each label.  The UIs are updated from
 844      * the current look and feel.  The labels are also set to their
 845      * preferred size.
 846      *
 847      * @see #setLabelTable
 848      * @see JComponent#updateUI
 849      */
 850     protected void updateLabelUIs() {
 851         Dictionary<Integer, JComponent> labelTable = getLabelTable();
 852 
 853         if (labelTable == null) {
 854             return;
 855         }
 856         Enumeration<Integer> labels = labelTable.keys();
 857         while ( labels.hasMoreElements() ) {
 858             JComponent component = labelTable.get(labels.nextElement());
 859             component.updateUI();
 860             component.setSize(component.getPreferredSize());
 861         }
 862     }
 863 
 864     private void updateLabelSizes() {
 865         Dictionary<Integer, JComponent> labelTable = getLabelTable();
 866         if (labelTable != null) {
 867             Enumeration<JComponent> labels = labelTable.elements();
 868             while (labels.hasMoreElements()) {
 869                 JComponent component = labels.nextElement();
 870                 component.setSize(component.getPreferredSize());
 871             }
 872         }
 873     }
 874 
 875 
 876     /**
 877      * Creates a {@code Hashtable} of numerical text labels, starting at the
 878      * slider minimum, and using the increment specified.
 879      * For example, if you call <code>createStandardLabels( 10 )</code>
 880      * and the slider minimum is zero,
 881      * then labels will be created for the values 0, 10, 20, 30, and so on.
 882      * <p>
 883      * For the labels to be drawn on the slider, the returned {@code Hashtable}
 884      * must be passed into {@code setLabelTable}, and {@code setPaintLabels}
 885      * must be set to {@code true}.
 886      * <p>
 887      * For further details on the makeup of the returned {@code Hashtable}, see
 888      * the {@code setLabelTable} documentation.
 889      *
 890      * @param  increment  distance between labels in the generated hashtable
 891      * @return a new {@code Hashtable} of labels
 892      * @see #setLabelTable
 893      * @see #setPaintLabels
 894      * @throws IllegalArgumentException if {@code increment} is less than or
 895      *          equal to zero
 896      */
 897     public Hashtable<Integer, JComponent> createStandardLabels( int increment ) {
 898         return createStandardLabels( increment, getMinimum() );
 899     }
 900 
 901 
 902     /**
 903      * Creates a {@code Hashtable} of numerical text labels, starting at the
 904      * starting point specified, and using the increment specified.
 905      * For example, if you call
 906      * <code>createStandardLabels( 10, 2 )</code>,
 907      * then labels will be created for the values 2, 12, 22, 32, and so on.
 908      * <p>
 909      * For the labels to be drawn on the slider, the returned {@code Hashtable}
 910      * must be passed into {@code setLabelTable}, and {@code setPaintLabels}
 911      * must be set to {@code true}.
 912      * <p>
 913      * For further details on the makeup of the returned {@code Hashtable}, see
 914      * the {@code setLabelTable} documentation.
 915      *
 916      * @param  increment  distance between labels in the generated hashtable
 917      * @param  start      value at which the labels will begin
 918      * @return a new {@code Hashtable} of labels
 919      * @see #setLabelTable
 920      * @see #setPaintLabels
 921      * @exception IllegalArgumentException if {@code start} is
 922      *          out of range, or if {@code increment} is less than or equal
 923      *          to zero
 924      */
 925     public Hashtable<Integer, JComponent> createStandardLabels( int increment, int start ) {
 926         if ( start > getMaximum() || start < getMinimum() ) {
 927             throw new IllegalArgumentException( "Slider label start point out of range." );
 928         }
 929 
 930         if ( increment <= 0 ) {
 931             throw new IllegalArgumentException( "Label incremement must be > 0" );
 932         }
 933 
 934         class SmartHashtable extends Hashtable<Integer, JComponent> implements PropertyChangeListener {
 935             int increment = 0;
 936             int start = 0;
 937             boolean startAtMin = false;
 938 
 939             class LabelUIResource extends JLabel implements UIResource {
 940                 public LabelUIResource( String text, int alignment ) {
 941                     super( text, alignment );
 942                     setName("Slider.label");
 943                 }
 944 
 945                 public Font getFont() {
 946                     Font font = super.getFont();
 947                     if (font != null && !(font instanceof UIResource)) {
 948                         return font;
 949                     }
 950                     return JSlider.this.getFont();
 951                 }
 952 
 953                 public Color getForeground() {
 954                     Color fg = super.getForeground();


 961                     return fg;
 962                 }
 963             }
 964 
 965             public SmartHashtable( int increment, int start ) {
 966                 super();
 967                 this.increment = increment;
 968                 this.start = start;
 969                 startAtMin = start == getMinimum();
 970                 createLabels();
 971             }
 972 
 973             public void propertyChange( PropertyChangeEvent e ) {
 974                 if ( e.getPropertyName().equals( "minimum" ) && startAtMin ) {
 975                     start = getMinimum();
 976                 }
 977 
 978                 if ( e.getPropertyName().equals( "minimum" ) ||
 979                      e.getPropertyName().equals( "maximum" ) ) {
 980 
 981                     Enumeration<Integer> keys = getLabelTable().keys();
 982                     Hashtable<Integer, JComponent> hashtable = new Hashtable<>();
 983 
 984                     // Save the labels that were added by the developer
 985                     while ( keys.hasMoreElements() ) {
 986                         Integer key = keys.nextElement();
 987                         JComponent value = labelTable.get(key);
 988                         if ( !(value instanceof LabelUIResource) ) {
 989                             hashtable.put( key, value );
 990                         }
 991                     }
 992 
 993                     clear();
 994                     createLabels();
 995 
 996                     // Add the saved labels
 997                     keys = hashtable.keys();
 998                     while ( keys.hasMoreElements() ) {
 999                         Integer key = keys.nextElement();
1000                         put( key, hashtable.get( key ) );
1001                     }
1002 
1003                     ((JSlider)e.getSource()).setLabelTable( this );
1004                 }
1005             }
1006 
1007             void createLabels() {
1008                 for ( int labelIndex = start; labelIndex <= getMaximum(); labelIndex += increment ) {
1009                     put( Integer.valueOf( labelIndex ), new LabelUIResource( ""+labelIndex, JLabel.CENTER ) );
1010                 }
1011             }
1012         }
1013 
1014         SmartHashtable table = new SmartHashtable( increment, start );
1015 
1016         Dictionary<Integer, JComponent> labelTable = getLabelTable();
1017 
1018         if (labelTable != null && (labelTable instanceof PropertyChangeListener)) {
1019             removePropertyChangeListener((PropertyChangeListener) labelTable);
1020         }
1021 
1022         addPropertyChangeListener( table );
1023 
1024         return table;
1025     }
1026 
1027 
1028     /**
1029      * Returns true if the value-range shown for the slider is reversed,
1030      *
1031      * @return true if the slider values are reversed from their normal order
1032      * @see #setInverted
1033      */
1034     public boolean getInverted() {
1035         return isInverted;
1036     }