37 import java.io.ObjectInputStream;
38 import java.io.IOException;
39
40 import javax.swing.plaf.LabelUI;
41 import javax.accessibility.*;
42 import javax.swing.text.*;
43 import javax.swing.text.html.*;
44 import javax.swing.plaf.basic.*;
45 import java.util.*;
46
47
48 /**
49 * A display area for a short text string or an image,
50 * or both.
51 * A label does not react to input events.
52 * As a result, it cannot get the keyboard focus.
53 * A label can, however, display a keyboard alternative
54 * as a convenience for a nearby component
55 * that has a keyboard alternative but can't display it.
56 * <p>
57 * A <code>JLabel</code> object can display
58 * either text, an image, or both.
59 * You can specify where in the label's display area
60 * the label's contents are aligned
61 * by setting the vertical and horizontal alignment.
62 * By default, labels are vertically centered
63 * in their display area.
64 * Text-only labels are leading edge aligned, by default;
65 * image-only labels are horizontally centered, by default.
66 * <p>
67 * You can also specify the position of the text
68 * relative to the image.
69 * By default, text is on the trailing edge of the image,
70 * with the text and image vertically aligned.
71 * <p>
72 * A label's leading and trailing edge are determined from the value of its
73 * {@link java.awt.ComponentOrientation} property. At present, the default
74 * ComponentOrientation setting maps the leading edge to left and the trailing
75 * edge to right.
76 *
77 * <p>
78 * Finally, you can use the <code>setIconTextGap</code> method
79 * to specify how many pixels
80 * should appear between the text and the image.
81 * The default is 4 pixels.
82 * <p>
83 * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/label.html">How to Use Labels</a>
84 * in <em>The Java Tutorial</em>
85 * for further documentation.
86 * <p>
87 * <strong>Warning:</strong> Swing is not thread safe. For more
88 * information see <a
89 * href="package-summary.html#threading">Swing's Threading
90 * Policy</a>.
91 * <p>
92 * <strong>Warning:</strong>
93 * Serialized objects of this class will not be compatible with
94 * future Swing releases. The current serialization support is
95 * appropriate for short term storage or RMI between applications running
96 * the same version of Swing. As of 1.4, support for long term storage
97 * of all JavaBeans™
98 * has been added to the <code>java.beans</code> package.
99 * Please see {@link java.beans.XMLEncoder}.
100 *
101 * @beaninfo
102 * attribute: isContainer false
103 * description: A component that displays a short string and an icon.
104 *
105 * @author Hans Muller
106 * @since 1.2
107 */
108 @SuppressWarnings("serial")
109 public class JLabel extends JComponent implements SwingConstants, Accessible
110 {
111 /**
112 * @see #getUIClassID
113 * @see #readObject
114 */
115 private static final String uiClassID = "LabelUI";
116
117 private int mnemonic = '\0';
118 private int mnemonicIndex = -1;
130
131 /**
132 * The Component this label is for; null if the label
133 * is not the label for a component
134 */
135 protected Component labelFor = null;
136
137 /**
138 * Client property key used to determine what label is labeling the
139 * component. This is generally not used by labels, but is instead
140 * used by components such as text areas that are being labeled by
141 * labels. When the labelFor property of a label is set, it will
142 * automatically set the LABELED_BY_PROPERTY of the component being
143 * labelled.
144 *
145 * @see #setLabelFor
146 */
147 static final String LABELED_BY_PROPERTY = "labeledBy";
148
149 /**
150 * Creates a <code>JLabel</code> instance with the specified
151 * text, image, and horizontal alignment.
152 * The label is centered vertically in its display area.
153 * The text is on the trailing edge of the image.
154 *
155 * @param text The text to be displayed by the label.
156 * @param icon The image to be displayed by the label.
157 * @param horizontalAlignment One of the following constants
158 * defined in <code>SwingConstants</code>:
159 * <code>LEFT</code>,
160 * <code>CENTER</code>,
161 * <code>RIGHT</code>,
162 * <code>LEADING</code> or
163 * <code>TRAILING</code>.
164 */
165 public JLabel(String text, Icon icon, int horizontalAlignment) {
166 setText(text);
167 setIcon(icon);
168 setHorizontalAlignment(horizontalAlignment);
169 updateUI();
170 setAlignmentX(LEFT_ALIGNMENT);
171 }
172
173 /**
174 * Creates a <code>JLabel</code> instance with the specified
175 * text and horizontal alignment.
176 * The label is centered vertically in its display area.
177 *
178 * @param text The text to be displayed by the label.
179 * @param horizontalAlignment One of the following constants
180 * defined in <code>SwingConstants</code>:
181 * <code>LEFT</code>,
182 * <code>CENTER</code>,
183 * <code>RIGHT</code>,
184 * <code>LEADING</code> or
185 * <code>TRAILING</code>.
186 */
187 public JLabel(String text, int horizontalAlignment) {
188 this(text, null, horizontalAlignment);
189 }
190
191 /**
192 * Creates a <code>JLabel</code> instance with the specified text.
193 * The label is aligned against the leading edge of its display area,
194 * and centered vertically.
195 *
196 * @param text The text to be displayed by the label.
197 */
198 public JLabel(String text) {
199 this(text, null, LEADING);
200 }
201
202 /**
203 * Creates a <code>JLabel</code> instance with the specified
204 * image and horizontal alignment.
205 * The label is centered vertically in its display area.
206 *
207 * @param image The image to be displayed by the label.
208 * @param horizontalAlignment One of the following constants
209 * defined in <code>SwingConstants</code>:
210 * <code>LEFT</code>,
211 * <code>CENTER</code>,
212 * <code>RIGHT</code>,
213 * <code>LEADING</code> or
214 * <code>TRAILING</code>.
215 */
216 public JLabel(Icon image, int horizontalAlignment) {
217 this(null, image, horizontalAlignment);
218 }
219
220 /**
221 * Creates a <code>JLabel</code> instance with the specified image.
222 * The label is centered vertically and horizontally
223 * in its display area.
224 *
225 * @param image The image to be displayed by the label.
226 */
227 public JLabel(Icon image) {
228 this(null, image, CENTER);
229 }
230
231 /**
232 * Creates a <code>JLabel</code> instance with
233 * no image and with an empty string for the title.
234 * The label is centered vertically
235 * in its display area.
236 * The label's contents, once set, will be displayed on the leading edge
237 * of the label's display area.
238 */
239 public JLabel() {
240 this("", null, LEADING);
241 }
242
243
244 /**
245 * Returns the L&F object that renders this component.
246 *
247 * @return LabelUI object
248 */
249 public LabelUI getUI() {
250 return (LabelUI)ui;
251 }
252
409 if (defaultIcon != oldValue) {
410 if ((defaultIcon == null) ||
411 (oldValue == null) ||
412 (defaultIcon.getIconWidth() != oldValue.getIconWidth()) ||
413 (defaultIcon.getIconHeight() != oldValue.getIconHeight())) {
414 revalidate();
415 }
416 repaint();
417 }
418 }
419
420
421 /**
422 * Returns the icon used by the label when it's disabled.
423 * If no disabled icon has been set this will forward the call to
424 * the look and feel to construct an appropriate disabled Icon.
425 * <p>
426 * Some look and feels might not render the disabled Icon, in which
427 * case they will ignore this.
428 *
429 * @return the <code>disabledIcon</code> property
430 * @see #setDisabledIcon
431 * @see javax.swing.LookAndFeel#getDisabledIcon
432 * @see ImageIcon
433 */
434 @Transient
435 public Icon getDisabledIcon() {
436 if (!disabledIconSet && disabledIcon == null && defaultIcon != null) {
437 disabledIcon = UIManager.getLookAndFeel().getDisabledIcon(this, defaultIcon);
438 if (disabledIcon != null) {
439 firePropertyChange("disabledIcon", null, disabledIcon);
440 }
441 }
442 return disabledIcon;
443 }
444
445
446 /**
447 * Set the icon to be displayed if this JLabel is "disabled"
448 * (JLabel.setEnabled(false)).
449 * <p>
531 * @see #getLabelFor
532 * @see #setLabelFor
533 */
534 public int getDisplayedMnemonic() {
535 return mnemonic;
536 }
537
538 /**
539 * Provides a hint to the look and feel as to which character in the
540 * text should be decorated to represent the mnemonic. Not all look and
541 * feels may support this. A value of -1 indicates either there is no
542 * mnemonic, the mnemonic character is not contained in the string, or
543 * the developer does not wish the mnemonic to be displayed.
544 * <p>
545 * The value of this is updated as the properties relating to the
546 * mnemonic change (such as the mnemonic itself, the text...).
547 * You should only ever have to call this if
548 * you do not wish the default character to be underlined. For example, if
549 * the text was 'Save As', with a mnemonic of 'a', and you wanted the 'A'
550 * to be decorated, as 'Save <u>A</u>s', you would have to invoke
551 * <code>setDisplayedMnemonicIndex(5)</code> after invoking
552 * <code>setDisplayedMnemonic(KeyEvent.VK_A)</code>.
553 *
554 * @since 1.4
555 * @param index Index into the String to underline
556 * @exception IllegalArgumentException will be thrown if <code>index</code>
557 * is >= length of the text, or < -1
558 *
559 * @beaninfo
560 * bound: true
561 * attribute: visualUpdate true
562 * description: the index into the String to draw the keyboard character
563 * mnemonic at
564 */
565 public void setDisplayedMnemonicIndex(int index)
566 throws IllegalArgumentException {
567 int oldValue = mnemonicIndex;
568 if (index == -1) {
569 mnemonicIndex = -1;
570 } else {
571 String text = getText();
572 int textLength = (text == null) ? 0 : text.length();
573 if (index < -1 || index >= textLength) { // index out of range
574 throw new IllegalArgumentException("index == " + index);
575 }
576 }
670 * attribute: visualUpdate true
671 * description: If both the icon and text properties are set, this
672 * property defines the space between them.
673 */
674 public void setIconTextGap(int iconTextGap) {
675 int oldValue = this.iconTextGap;
676 this.iconTextGap = iconTextGap;
677 firePropertyChange("iconTextGap", oldValue, iconTextGap);
678 if (iconTextGap != oldValue) {
679 revalidate();
680 repaint();
681 }
682 }
683
684
685
686 /**
687 * Returns the alignment of the label's contents along the Y axis.
688 *
689 * @return The value of the verticalAlignment property, one of the
690 * following constants defined in <code>SwingConstants</code>:
691 * <code>TOP</code>,
692 * <code>CENTER</code>, or
693 * <code>BOTTOM</code>.
694 *
695 * @see SwingConstants
696 * @see #setVerticalAlignment
697 */
698 public int getVerticalAlignment() {
699 return verticalAlignment;
700 }
701
702
703 /**
704 * Sets the alignment of the label's contents along the Y axis.
705 * <p>
706 * The default value of this property is CENTER.
707 *
708 * @param alignment One of the following constants
709 * defined in <code>SwingConstants</code>:
710 * <code>TOP</code>,
711 * <code>CENTER</code> (the default), or
712 * <code>BOTTOM</code>.
713 *
714 * @see SwingConstants
715 * @see #getVerticalAlignment
716 * @beaninfo
717 * bound: true
718 * enum: TOP SwingConstants.TOP
719 * CENTER SwingConstants.CENTER
720 * BOTTOM SwingConstants.BOTTOM
721 * attribute: visualUpdate true
722 * description: The alignment of the label's contents along the Y axis.
723 */
724 public void setVerticalAlignment(int alignment) {
725 if (alignment == verticalAlignment) return;
726 int oldValue = verticalAlignment;
727 verticalAlignment = checkVerticalKey(alignment, "verticalAlignment");
728 firePropertyChange("verticalAlignment", oldValue, verticalAlignment);
729 repaint();
730 }
731
732
733 /**
734 * Returns the alignment of the label's contents along the X axis.
735 *
736 * @return The value of the horizontalAlignment property, one of the
737 * following constants defined in <code>SwingConstants</code>:
738 * <code>LEFT</code>,
739 * <code>CENTER</code>,
740 * <code>RIGHT</code>,
741 * <code>LEADING</code> or
742 * <code>TRAILING</code>.
743 *
744 * @see #setHorizontalAlignment
745 * @see SwingConstants
746 */
747 public int getHorizontalAlignment() {
748 return horizontalAlignment;
749 }
750
751 /**
752 * Sets the alignment of the label's contents along the X axis.
753 * <p>
754 * This is a JavaBeans bound property.
755 *
756 * @param alignment One of the following constants
757 * defined in <code>SwingConstants</code>:
758 * <code>LEFT</code>,
759 * <code>CENTER</code> (the default for image-only labels),
760 * <code>RIGHT</code>,
761 * <code>LEADING</code> (the default for text-only labels) or
762 * <code>TRAILING</code>.
763 *
764 * @see SwingConstants
765 * @see #getHorizontalAlignment
766 * @beaninfo
767 * bound: true
768 * enum: LEFT SwingConstants.LEFT
769 * CENTER SwingConstants.CENTER
770 * RIGHT SwingConstants.RIGHT
771 * LEADING SwingConstants.LEADING
772 * TRAILING SwingConstants.TRAILING
773 * attribute: visualUpdate true
774 * description: The alignment of the label's content along the X axis.
775 */
776 public void setHorizontalAlignment(int alignment) {
777 if (alignment == horizontalAlignment) return;
778 int oldValue = horizontalAlignment;
779 horizontalAlignment = checkHorizontalKey(alignment,
780 "horizontalAlignment");
781 firePropertyChange("horizontalAlignment",
782 oldValue, horizontalAlignment);
783 repaint();
784 }
785
786
787 /**
788 * Returns the vertical position of the label's text,
789 * relative to its image.
790 *
791 * @return One of the following constants
792 * defined in <code>SwingConstants</code>:
793 * <code>TOP</code>,
794 * <code>CENTER</code>, or
795 * <code>BOTTOM</code>.
796 *
797 * @see #setVerticalTextPosition
798 * @see SwingConstants
799 */
800 public int getVerticalTextPosition() {
801 return verticalTextPosition;
802 }
803
804
805 /**
806 * Sets the vertical position of the label's text,
807 * relative to its image.
808 * <p>
809 * The default value of this property is CENTER.
810 * <p>
811 * This is a JavaBeans bound property.
812 *
813 * @param textPosition One of the following constants
814 * defined in <code>SwingConstants</code>:
815 * <code>TOP</code>,
816 * <code>CENTER</code> (the default), or
817 * <code>BOTTOM</code>.
818 *
819 * @see SwingConstants
820 * @see #getVerticalTextPosition
821 * @beaninfo
822 * bound: true
823 * enum: TOP SwingConstants.TOP
824 * CENTER SwingConstants.CENTER
825 * BOTTOM SwingConstants.BOTTOM
826 * expert: true
827 * attribute: visualUpdate true
828 * description: The vertical position of the text relative to it's image.
829 */
830 public void setVerticalTextPosition(int textPosition) {
831 if (textPosition == verticalTextPosition) return;
832 int old = verticalTextPosition;
833 verticalTextPosition = checkVerticalKey(textPosition,
834 "verticalTextPosition");
835 firePropertyChange("verticalTextPosition", old, verticalTextPosition);
836 revalidate();
837 repaint();
838 }
839
840
841 /**
842 * Returns the horizontal position of the label's text,
843 * relative to its image.
844 *
845 * @return One of the following constants
846 * defined in <code>SwingConstants</code>:
847 * <code>LEFT</code>,
848 * <code>CENTER</code>,
849 * <code>RIGHT</code>,
850 * <code>LEADING</code> or
851 * <code>TRAILING</code>.
852 *
853 * @see SwingConstants
854 */
855 public int getHorizontalTextPosition() {
856 return horizontalTextPosition;
857 }
858
859
860 /**
861 * Sets the horizontal position of the label's text,
862 * relative to its image.
863 *
864 * @param textPosition One of the following constants
865 * defined in <code>SwingConstants</code>:
866 * <code>LEFT</code>,
867 * <code>CENTER</code>,
868 * <code>RIGHT</code>,
869 * <code>LEADING</code>, or
870 * <code>TRAILING</code> (the default).
871 *
872 * @see SwingConstants
873 * @beaninfo
874 * expert: true
875 * bound: true
876 * enum: LEFT SwingConstants.LEFT
877 * CENTER SwingConstants.CENTER
878 * RIGHT SwingConstants.RIGHT
879 * LEADING SwingConstants.LEADING
880 * TRAILING SwingConstants.TRAILING
881 * attribute: visualUpdate true
882 * description: The horizontal position of the label's text,
883 * relative to its image.
884 */
885 public void setHorizontalTextPosition(int textPosition) {
886 int old = horizontalTextPosition;
887 this.horizontalTextPosition = checkHorizontalKey(textPosition,
888 "horizontalTextPosition");
889 firePropertyChange("horizontalTextPosition",
890 old, horizontalTextPosition);
891 revalidate();
892 repaint();
893 }
894
895
896 /**
897 * This is overridden to return false if the current Icon's Image is
898 * not equal to the passed in Image <code>img</code>.
899 *
900 * @see java.awt.image.ImageObserver
901 * @see java.awt.Component#imageUpdate(java.awt.Image, int, int, int, int, int)
902 */
903 public boolean imageUpdate(Image img, int infoflags,
904 int x, int y, int w, int h) {
905 // Don't use getDisabledIcon, will trigger creation of icon if icon
906 // not set.
907 if (!isShowing() ||
908 !SwingUtilities.doesIconReferenceImage(getIcon(), img) &&
909 !SwingUtilities.doesIconReferenceImage(disabledIcon, img)) {
910
911 return false;
912 }
913 return super.imageUpdate(img, infoflags, x, y, w, h);
914 }
915
916
917 /**
918 * See readObject() and writeObject() in JComponent for more
919 * information about serialization in Swing.
920 */
921 private void writeObject(ObjectOutputStream s) throws IOException {
922 s.defaultWriteObject();
923 if (getUIClassID().equals(uiClassID)) {
924 byte count = JComponent.getWriteObjCounter(this);
925 JComponent.setWriteObjCounter(this, --count);
926 if (count == 0 && ui != null) {
927 ui.installUI(this);
928 }
929 }
930 }
931
932
933 /**
934 * Returns a string representation of this JLabel. This method
935 * is intended to be used only for debugging purposes, and the
936 * content and format of the returned string may vary between
937 * implementations. The returned string may be empty but may not
938 * be <code>null</code>.
939 *
940 * @return a string representation of this JLabel.
941 */
942 protected String paramString() {
943 String textString = (text != null ?
944 text : "");
945 String defaultIconString = ((defaultIcon != null)
946 && (defaultIcon != this) ?
947 defaultIcon.toString() : "");
948 String disabledIconString = ((disabledIcon != null)
949 && (disabledIcon != this) ?
950 disabledIcon.toString() : "");
951 String labelForString = (labelFor != null ?
952 labelFor.toString() : "");
953 String verticalAlignmentString;
954 if (verticalAlignment == TOP) {
955 verticalAlignmentString = "TOP";
956 } else if (verticalAlignment == CENTER) {
957 verticalAlignmentString = "CENTER";
958 } else if (verticalAlignment == BOTTOM) {
1060 * @beaninfo
1061 * expert: true
1062 * description: The AccessibleContext associated with this Label.
1063 */
1064 public AccessibleContext getAccessibleContext() {
1065 if (accessibleContext == null) {
1066 accessibleContext = new AccessibleJLabel();
1067 }
1068 return accessibleContext;
1069 }
1070
1071 /**
1072 * The class used to obtain the accessible role for this object.
1073 * <p>
1074 * <strong>Warning:</strong>
1075 * Serialized objects of this class will not be compatible with
1076 * future Swing releases. The current serialization support is
1077 * appropriate for short term storage or RMI between applications running
1078 * the same version of Swing. As of 1.4, support for long term storage
1079 * of all JavaBeans™
1080 * has been added to the <code>java.beans</code> package.
1081 * Please see {@link java.beans.XMLEncoder}.
1082 */
1083 @SuppressWarnings("serial")
1084 protected class AccessibleJLabel extends AccessibleJComponent
1085 implements AccessibleText, AccessibleExtendedComponent {
1086
1087 /**
1088 * Get the accessible name of this object.
1089 *
1090 * @return the localized name of the object -- can be null if this
1091 * object does not have a name
1092 * @see AccessibleContext#setAccessibleName
1093 */
1094 public String getAccessibleName() {
1095 String name = accessibleName;
1096
1097 if (name == null) {
1098 name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
1099 }
1100 if (name == null) {
1182 */
1183 public int getIndexAtPoint(Point p) {
1184 View view = (View) JLabel.this.getClientProperty("html");
1185 if (view != null) {
1186 Rectangle r = getTextRectangle();
1187 if (r == null) {
1188 return -1;
1189 }
1190 Rectangle2D.Float shape =
1191 new Rectangle2D.Float(r.x, r.y, r.width, r.height);
1192 Position.Bias bias[] = new Position.Bias[1];
1193 return view.viewToModel(p.x, p.y, shape, bias);
1194 } else {
1195 return -1;
1196 }
1197 }
1198
1199 /**
1200 * Returns the bounding box of the character at the given
1201 * index in the string. The bounds are returned in local
1202 * coordinates. If the index is invalid, <code>null</code> is returned.
1203 *
1204 * @param i the index into the String
1205 * @return the screen coordinates of the character's bounding box.
1206 * If the index is invalid, <code>null</code> is returned.
1207 * @since 1.3
1208 */
1209 public Rectangle getCharacterBounds(int i) {
1210 View view = (View) JLabel.this.getClientProperty("html");
1211 if (view != null) {
1212 Rectangle r = getTextRectangle();
1213 if (r == null) {
1214 return null;
1215 }
1216 Rectangle2D.Float shape =
1217 new Rectangle2D.Float(r.x, r.y, r.width, r.height);
1218 try {
1219 Shape charShape =
1220 view.modelToView(i, shape, Position.Bias.Forward);
1221 return charShape.getBounds();
1222 } catch (BadLocationException e) {
1223 return null;
1224 }
1225 } else {
1226 return null;
1600
1601 LabelKeyBinding(int mnemonic) {
1602 this.mnemonic = mnemonic;
1603 }
1604
1605 /**
1606 * Returns the number of key bindings for this object
1607 *
1608 * @return the zero-based number of key bindings for this object
1609 */
1610 public int getAccessibleKeyBindingCount() {
1611 return 1;
1612 }
1613
1614 /**
1615 * Returns a key binding for this object. The value returned is an
1616 * java.lang.Object which must be cast to appropriate type depending
1617 * on the underlying implementation of the key. For example, if the
1618 * Object returned is a javax.swing.KeyStroke, the user of this
1619 * method should do the following:
1620 * <nf><code>
1621 * Component c = <get the component that has the key bindings>
1622 * AccessibleContext ac = c.getAccessibleContext();
1623 * AccessibleKeyBinding akb = ac.getAccessibleKeyBinding();
1624 * for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) {
1625 * Object o = akb.getAccessibleKeyBinding(i);
1626 * if (o instanceof javax.swing.KeyStroke) {
1627 * javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o;
1628 * <do something with the key binding>
1629 * }
1630 * }
1631 * </code></nf>
1632 *
1633 * @param i zero-based index of the key bindings
1634 * @return a javax.lang.Object which specifies the key binding
1635 * @exception IllegalArgumentException if the index is
1636 * out of bounds
1637 * @see #getAccessibleKeyBindingCount
1638 */
1639 public java.lang.Object getAccessibleKeyBinding(int i) {
1640 if (i != 0) {
1641 throw new IllegalArgumentException();
1642 }
1643 return KeyStroke.getKeyStroke(mnemonic, 0);
1644 }
1645 }
1646
1647 } // AccessibleJComponent
1648 }
|
37 import java.io.ObjectInputStream;
38 import java.io.IOException;
39
40 import javax.swing.plaf.LabelUI;
41 import javax.accessibility.*;
42 import javax.swing.text.*;
43 import javax.swing.text.html.*;
44 import javax.swing.plaf.basic.*;
45 import java.util.*;
46
47
48 /**
49 * A display area for a short text string or an image,
50 * or both.
51 * A label does not react to input events.
52 * As a result, it cannot get the keyboard focus.
53 * A label can, however, display a keyboard alternative
54 * as a convenience for a nearby component
55 * that has a keyboard alternative but can't display it.
56 * <p>
57 * A {@code JLabel} object can display
58 * either text, an image, or both.
59 * You can specify where in the label's display area
60 * the label's contents are aligned
61 * by setting the vertical and horizontal alignment.
62 * By default, labels are vertically centered
63 * in their display area.
64 * Text-only labels are leading edge aligned, by default;
65 * image-only labels are horizontally centered, by default.
66 * <p>
67 * You can also specify the position of the text
68 * relative to the image.
69 * By default, text is on the trailing edge of the image,
70 * with the text and image vertically aligned.
71 * <p>
72 * A label's leading and trailing edge are determined from the value of its
73 * {@link java.awt.ComponentOrientation} property. At present, the default
74 * ComponentOrientation setting maps the leading edge to left and the trailing
75 * edge to right.
76 *
77 * <p>
78 * Finally, you can use the {@code setIconTextGap} method
79 * to specify how many pixels
80 * should appear between the text and the image.
81 * The default is 4 pixels.
82 * <p>
83 * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/label.html">How to Use Labels</a>
84 * in <em>The Java Tutorial</em>
85 * for further documentation.
86 * <p>
87 * <strong>Warning:</strong> Swing is not thread safe. For more
88 * information see <a
89 * href="package-summary.html#threading">Swing's Threading
90 * Policy</a>.
91 * <p>
92 * <strong>Warning:</strong>
93 * Serialized objects of this class will not be compatible with
94 * future Swing releases. The current serialization support is
95 * appropriate for short term storage or RMI between applications running
96 * the same version of Swing. As of 1.4, support for long term storage
97 * of all JavaBeans™
98 * has been added to the {@code java.beans} package.
99 * Please see {@link java.beans.XMLEncoder}.
100 *
101 * @beaninfo
102 * attribute: isContainer false
103 * description: A component that displays a short string and an icon.
104 *
105 * @author Hans Muller
106 * @since 1.2
107 */
108 @SuppressWarnings("serial")
109 public class JLabel extends JComponent implements SwingConstants, Accessible
110 {
111 /**
112 * @see #getUIClassID
113 * @see #readObject
114 */
115 private static final String uiClassID = "LabelUI";
116
117 private int mnemonic = '\0';
118 private int mnemonicIndex = -1;
130
131 /**
132 * The Component this label is for; null if the label
133 * is not the label for a component
134 */
135 protected Component labelFor = null;
136
137 /**
138 * Client property key used to determine what label is labeling the
139 * component. This is generally not used by labels, but is instead
140 * used by components such as text areas that are being labeled by
141 * labels. When the labelFor property of a label is set, it will
142 * automatically set the LABELED_BY_PROPERTY of the component being
143 * labelled.
144 *
145 * @see #setLabelFor
146 */
147 static final String LABELED_BY_PROPERTY = "labeledBy";
148
149 /**
150 * Creates a {@code JLabel} instance with the specified
151 * text, image, and horizontal alignment.
152 * The label is centered vertically in its display area.
153 * The text is on the trailing edge of the image.
154 *
155 * @param text The text to be displayed by the label.
156 * @param icon The image to be displayed by the label.
157 * @param horizontalAlignment One of the following constants
158 * defined in {@code SwingConstants}:
159 * {@code LEFT},
160 * {@code CENTER},
161 * {@code RIGHT},
162 * {@code LEADING} or
163 * {@code TRAILING}.
164 */
165 public JLabel(String text, Icon icon, int horizontalAlignment) {
166 setText(text);
167 setIcon(icon);
168 setHorizontalAlignment(horizontalAlignment);
169 updateUI();
170 setAlignmentX(LEFT_ALIGNMENT);
171 }
172
173 /**
174 * Creates a {@code JLabel} instance with the specified
175 * text and horizontal alignment.
176 * The label is centered vertically in its display area.
177 *
178 * @param text The text to be displayed by the label.
179 * @param horizontalAlignment One of the following constants
180 * defined in {@code SwingConstants}:
181 * {@code LEFT},
182 * {@code CENTER},
183 * {@code RIGHT},
184 * {@code LEADING} or
185 * {@code TRAILING}.
186 */
187 public JLabel(String text, int horizontalAlignment) {
188 this(text, null, horizontalAlignment);
189 }
190
191 /**
192 * Creates a {@code JLabel} instance with the specified text.
193 * The label is aligned against the leading edge of its display area,
194 * and centered vertically.
195 *
196 * @param text The text to be displayed by the label.
197 */
198 public JLabel(String text) {
199 this(text, null, LEADING);
200 }
201
202 /**
203 * Creates a {@code JLabel} instance with the specified
204 * image and horizontal alignment.
205 * The label is centered vertically in its display area.
206 *
207 * @param image The image to be displayed by the label.
208 * @param horizontalAlignment One of the following constants
209 * defined in {@code SwingConstants}:
210 * {@code LEFT},
211 * {@code CENTER},
212 * {@code RIGHT},
213 * {@code LEADING} or
214 * {@code TRAILING}.
215 */
216 public JLabel(Icon image, int horizontalAlignment) {
217 this(null, image, horizontalAlignment);
218 }
219
220 /**
221 * Creates a {@code JLabel} instance with the specified image.
222 * The label is centered vertically and horizontally
223 * in its display area.
224 *
225 * @param image The image to be displayed by the label.
226 */
227 public JLabel(Icon image) {
228 this(null, image, CENTER);
229 }
230
231 /**
232 * Creates a {@code JLabel} instance with
233 * no image and with an empty string for the title.
234 * The label is centered vertically
235 * in its display area.
236 * The label's contents, once set, will be displayed on the leading edge
237 * of the label's display area.
238 */
239 public JLabel() {
240 this("", null, LEADING);
241 }
242
243
244 /**
245 * Returns the L&F object that renders this component.
246 *
247 * @return LabelUI object
248 */
249 public LabelUI getUI() {
250 return (LabelUI)ui;
251 }
252
409 if (defaultIcon != oldValue) {
410 if ((defaultIcon == null) ||
411 (oldValue == null) ||
412 (defaultIcon.getIconWidth() != oldValue.getIconWidth()) ||
413 (defaultIcon.getIconHeight() != oldValue.getIconHeight())) {
414 revalidate();
415 }
416 repaint();
417 }
418 }
419
420
421 /**
422 * Returns the icon used by the label when it's disabled.
423 * If no disabled icon has been set this will forward the call to
424 * the look and feel to construct an appropriate disabled Icon.
425 * <p>
426 * Some look and feels might not render the disabled Icon, in which
427 * case they will ignore this.
428 *
429 * @return the {@code disabledIcon} property
430 * @see #setDisabledIcon
431 * @see javax.swing.LookAndFeel#getDisabledIcon
432 * @see ImageIcon
433 */
434 @Transient
435 public Icon getDisabledIcon() {
436 if (!disabledIconSet && disabledIcon == null && defaultIcon != null) {
437 disabledIcon = UIManager.getLookAndFeel().getDisabledIcon(this, defaultIcon);
438 if (disabledIcon != null) {
439 firePropertyChange("disabledIcon", null, disabledIcon);
440 }
441 }
442 return disabledIcon;
443 }
444
445
446 /**
447 * Set the icon to be displayed if this JLabel is "disabled"
448 * (JLabel.setEnabled(false)).
449 * <p>
531 * @see #getLabelFor
532 * @see #setLabelFor
533 */
534 public int getDisplayedMnemonic() {
535 return mnemonic;
536 }
537
538 /**
539 * Provides a hint to the look and feel as to which character in the
540 * text should be decorated to represent the mnemonic. Not all look and
541 * feels may support this. A value of -1 indicates either there is no
542 * mnemonic, the mnemonic character is not contained in the string, or
543 * the developer does not wish the mnemonic to be displayed.
544 * <p>
545 * The value of this is updated as the properties relating to the
546 * mnemonic change (such as the mnemonic itself, the text...).
547 * You should only ever have to call this if
548 * you do not wish the default character to be underlined. For example, if
549 * the text was 'Save As', with a mnemonic of 'a', and you wanted the 'A'
550 * to be decorated, as 'Save <u>A</u>s', you would have to invoke
551 * {@code setDisplayedMnemonicIndex(5)} after invoking
552 * {@code setDisplayedMnemonic(KeyEvent.VK_A)}.
553 *
554 * @since 1.4
555 * @param index Index into the String to underline
556 * @exception IllegalArgumentException will be thrown if {@code index}
557 * is >= length of the text, or < -1
558 *
559 * @beaninfo
560 * bound: true
561 * attribute: visualUpdate true
562 * description: the index into the String to draw the keyboard character
563 * mnemonic at
564 */
565 public void setDisplayedMnemonicIndex(int index)
566 throws IllegalArgumentException {
567 int oldValue = mnemonicIndex;
568 if (index == -1) {
569 mnemonicIndex = -1;
570 } else {
571 String text = getText();
572 int textLength = (text == null) ? 0 : text.length();
573 if (index < -1 || index >= textLength) { // index out of range
574 throw new IllegalArgumentException("index == " + index);
575 }
576 }
670 * attribute: visualUpdate true
671 * description: If both the icon and text properties are set, this
672 * property defines the space between them.
673 */
674 public void setIconTextGap(int iconTextGap) {
675 int oldValue = this.iconTextGap;
676 this.iconTextGap = iconTextGap;
677 firePropertyChange("iconTextGap", oldValue, iconTextGap);
678 if (iconTextGap != oldValue) {
679 revalidate();
680 repaint();
681 }
682 }
683
684
685
686 /**
687 * Returns the alignment of the label's contents along the Y axis.
688 *
689 * @return The value of the verticalAlignment property, one of the
690 * following constants defined in {@code SwingConstants}:
691 * {@code TOP},
692 * {@code CENTER}, or
693 * {@code BOTTOM}.
694 *
695 * @see SwingConstants
696 * @see #setVerticalAlignment
697 */
698 public int getVerticalAlignment() {
699 return verticalAlignment;
700 }
701
702
703 /**
704 * Sets the alignment of the label's contents along the Y axis.
705 * <p>
706 * The default value of this property is CENTER.
707 *
708 * @param alignment One of the following constants
709 * defined in {@code SwingConstants}:
710 * {@code TOP},
711 * {@code CENTER} (the default), or
712 * {@code BOTTOM}.
713 *
714 * @see SwingConstants
715 * @see #getVerticalAlignment
716 * @beaninfo
717 * bound: true
718 * enum: TOP SwingConstants.TOP
719 * CENTER SwingConstants.CENTER
720 * BOTTOM SwingConstants.BOTTOM
721 * attribute: visualUpdate true
722 * description: The alignment of the label's contents along the Y axis.
723 */
724 public void setVerticalAlignment(int alignment) {
725 if (alignment == verticalAlignment) return;
726 int oldValue = verticalAlignment;
727 verticalAlignment = checkVerticalKey(alignment, "verticalAlignment");
728 firePropertyChange("verticalAlignment", oldValue, verticalAlignment);
729 repaint();
730 }
731
732
733 /**
734 * Returns the alignment of the label's contents along the X axis.
735 *
736 * @return The value of the horizontalAlignment property, one of the
737 * following constants defined in {@code SwingConstants}:
738 * {@code LEFT},
739 * {@code CENTER},
740 * {@code RIGHT},
741 * {@code LEADING} or
742 * {@code TRAILING}.
743 *
744 * @see #setHorizontalAlignment
745 * @see SwingConstants
746 */
747 public int getHorizontalAlignment() {
748 return horizontalAlignment;
749 }
750
751 /**
752 * Sets the alignment of the label's contents along the X axis.
753 * <p>
754 * This is a JavaBeans bound property.
755 *
756 * @param alignment One of the following constants
757 * defined in {@code SwingConstants}:
758 * {@code LEFT},
759 * {@code CENTER} (the default for image-only labels),
760 * {@code RIGHT},
761 * {@code LEADING} (the default for text-only labels) or
762 * {@code TRAILING}.
763 *
764 * @see SwingConstants
765 * @see #getHorizontalAlignment
766 * @beaninfo
767 * bound: true
768 * enum: LEFT SwingConstants.LEFT
769 * CENTER SwingConstants.CENTER
770 * RIGHT SwingConstants.RIGHT
771 * LEADING SwingConstants.LEADING
772 * TRAILING SwingConstants.TRAILING
773 * attribute: visualUpdate true
774 * description: The alignment of the label's content along the X axis.
775 */
776 public void setHorizontalAlignment(int alignment) {
777 if (alignment == horizontalAlignment) return;
778 int oldValue = horizontalAlignment;
779 horizontalAlignment = checkHorizontalKey(alignment,
780 "horizontalAlignment");
781 firePropertyChange("horizontalAlignment",
782 oldValue, horizontalAlignment);
783 repaint();
784 }
785
786
787 /**
788 * Returns the vertical position of the label's text,
789 * relative to its image.
790 *
791 * @return One of the following constants
792 * defined in {@code SwingConstants}:
793 * {@code TOP},
794 * {@code CENTER}, or
795 * {@code BOTTOM}.
796 *
797 * @see #setVerticalTextPosition
798 * @see SwingConstants
799 */
800 public int getVerticalTextPosition() {
801 return verticalTextPosition;
802 }
803
804
805 /**
806 * Sets the vertical position of the label's text,
807 * relative to its image.
808 * <p>
809 * The default value of this property is CENTER.
810 * <p>
811 * This is a JavaBeans bound property.
812 *
813 * @param textPosition One of the following constants
814 * defined in {@code SwingConstants}:
815 * {@code TOP},
816 * {@code CENTER} (the default), or
817 * {@code BOTTOM}.
818 *
819 * @see SwingConstants
820 * @see #getVerticalTextPosition
821 * @beaninfo
822 * bound: true
823 * enum: TOP SwingConstants.TOP
824 * CENTER SwingConstants.CENTER
825 * BOTTOM SwingConstants.BOTTOM
826 * expert: true
827 * attribute: visualUpdate true
828 * description: The vertical position of the text relative to it's image.
829 */
830 public void setVerticalTextPosition(int textPosition) {
831 if (textPosition == verticalTextPosition) return;
832 int old = verticalTextPosition;
833 verticalTextPosition = checkVerticalKey(textPosition,
834 "verticalTextPosition");
835 firePropertyChange("verticalTextPosition", old, verticalTextPosition);
836 revalidate();
837 repaint();
838 }
839
840
841 /**
842 * Returns the horizontal position of the label's text,
843 * relative to its image.
844 *
845 * @return One of the following constants
846 * defined in {@code SwingConstants}:
847 * {@code LEFT},
848 * {@code CENTER},
849 * {@code RIGHT},
850 * {@code LEADING} or
851 * {@code TRAILING}.
852 *
853 * @see SwingConstants
854 */
855 public int getHorizontalTextPosition() {
856 return horizontalTextPosition;
857 }
858
859
860 /**
861 * Sets the horizontal position of the label's text,
862 * relative to its image.
863 *
864 * @param textPosition One of the following constants
865 * defined in {@code SwingConstants}:
866 * {@code LEFT},
867 * {@code CENTER},
868 * {@code RIGHT},
869 * {@code LEADING}, or
870 * {@code TRAILING} (the default).
871 *
872 * @see SwingConstants
873 * @beaninfo
874 * expert: true
875 * bound: true
876 * enum: LEFT SwingConstants.LEFT
877 * CENTER SwingConstants.CENTER
878 * RIGHT SwingConstants.RIGHT
879 * LEADING SwingConstants.LEADING
880 * TRAILING SwingConstants.TRAILING
881 * attribute: visualUpdate true
882 * description: The horizontal position of the label's text,
883 * relative to its image.
884 */
885 public void setHorizontalTextPosition(int textPosition) {
886 int old = horizontalTextPosition;
887 this.horizontalTextPosition = checkHorizontalKey(textPosition,
888 "horizontalTextPosition");
889 firePropertyChange("horizontalTextPosition",
890 old, horizontalTextPosition);
891 revalidate();
892 repaint();
893 }
894
895
896 /**
897 * This is overridden to return false if the current Icon's Image is
898 * not equal to the passed in Image {@code img}.
899 *
900 * @see java.awt.image.ImageObserver
901 * @see java.awt.Component#imageUpdate(java.awt.Image, int, int, int, int, int)
902 */
903 public boolean imageUpdate(Image img, int infoflags,
904 int x, int y, int w, int h) {
905 // Don't use getDisabledIcon, will trigger creation of icon if icon
906 // not set.
907 if (!isShowing() ||
908 !SwingUtilities.doesIconReferenceImage(getIcon(), img) &&
909 !SwingUtilities.doesIconReferenceImage(disabledIcon, img)) {
910
911 return false;
912 }
913 return super.imageUpdate(img, infoflags, x, y, w, h);
914 }
915
916
917 /**
918 * See readObject() and writeObject() in JComponent for more
919 * information about serialization in Swing.
920 */
921 private void writeObject(ObjectOutputStream s) throws IOException {
922 s.defaultWriteObject();
923 if (getUIClassID().equals(uiClassID)) {
924 byte count = JComponent.getWriteObjCounter(this);
925 JComponent.setWriteObjCounter(this, --count);
926 if (count == 0 && ui != null) {
927 ui.installUI(this);
928 }
929 }
930 }
931
932
933 /**
934 * Returns a string representation of this JLabel. This method
935 * is intended to be used only for debugging purposes, and the
936 * content and format of the returned string may vary between
937 * implementations. The returned string may be empty but may not
938 * be {@code null}.
939 *
940 * @return a string representation of this JLabel.
941 */
942 protected String paramString() {
943 String textString = (text != null ?
944 text : "");
945 String defaultIconString = ((defaultIcon != null)
946 && (defaultIcon != this) ?
947 defaultIcon.toString() : "");
948 String disabledIconString = ((disabledIcon != null)
949 && (disabledIcon != this) ?
950 disabledIcon.toString() : "");
951 String labelForString = (labelFor != null ?
952 labelFor.toString() : "");
953 String verticalAlignmentString;
954 if (verticalAlignment == TOP) {
955 verticalAlignmentString = "TOP";
956 } else if (verticalAlignment == CENTER) {
957 verticalAlignmentString = "CENTER";
958 } else if (verticalAlignment == BOTTOM) {
1060 * @beaninfo
1061 * expert: true
1062 * description: The AccessibleContext associated with this Label.
1063 */
1064 public AccessibleContext getAccessibleContext() {
1065 if (accessibleContext == null) {
1066 accessibleContext = new AccessibleJLabel();
1067 }
1068 return accessibleContext;
1069 }
1070
1071 /**
1072 * The class used to obtain the accessible role for this object.
1073 * <p>
1074 * <strong>Warning:</strong>
1075 * Serialized objects of this class will not be compatible with
1076 * future Swing releases. The current serialization support is
1077 * appropriate for short term storage or RMI between applications running
1078 * the same version of Swing. As of 1.4, support for long term storage
1079 * of all JavaBeans™
1080 * has been added to the {@code java.beans} package.
1081 * Please see {@link java.beans.XMLEncoder}.
1082 */
1083 @SuppressWarnings("serial")
1084 protected class AccessibleJLabel extends AccessibleJComponent
1085 implements AccessibleText, AccessibleExtendedComponent {
1086
1087 /**
1088 * Get the accessible name of this object.
1089 *
1090 * @return the localized name of the object -- can be null if this
1091 * object does not have a name
1092 * @see AccessibleContext#setAccessibleName
1093 */
1094 public String getAccessibleName() {
1095 String name = accessibleName;
1096
1097 if (name == null) {
1098 name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
1099 }
1100 if (name == null) {
1182 */
1183 public int getIndexAtPoint(Point p) {
1184 View view = (View) JLabel.this.getClientProperty("html");
1185 if (view != null) {
1186 Rectangle r = getTextRectangle();
1187 if (r == null) {
1188 return -1;
1189 }
1190 Rectangle2D.Float shape =
1191 new Rectangle2D.Float(r.x, r.y, r.width, r.height);
1192 Position.Bias bias[] = new Position.Bias[1];
1193 return view.viewToModel(p.x, p.y, shape, bias);
1194 } else {
1195 return -1;
1196 }
1197 }
1198
1199 /**
1200 * Returns the bounding box of the character at the given
1201 * index in the string. The bounds are returned in local
1202 * coordinates. If the index is invalid, {@code null} is returned.
1203 *
1204 * @param i the index into the String
1205 * @return the screen coordinates of the character's bounding box.
1206 * If the index is invalid, {@code null} is returned.
1207 * @since 1.3
1208 */
1209 public Rectangle getCharacterBounds(int i) {
1210 View view = (View) JLabel.this.getClientProperty("html");
1211 if (view != null) {
1212 Rectangle r = getTextRectangle();
1213 if (r == null) {
1214 return null;
1215 }
1216 Rectangle2D.Float shape =
1217 new Rectangle2D.Float(r.x, r.y, r.width, r.height);
1218 try {
1219 Shape charShape =
1220 view.modelToView(i, shape, Position.Bias.Forward);
1221 return charShape.getBounds();
1222 } catch (BadLocationException e) {
1223 return null;
1224 }
1225 } else {
1226 return null;
1600
1601 LabelKeyBinding(int mnemonic) {
1602 this.mnemonic = mnemonic;
1603 }
1604
1605 /**
1606 * Returns the number of key bindings for this object
1607 *
1608 * @return the zero-based number of key bindings for this object
1609 */
1610 public int getAccessibleKeyBindingCount() {
1611 return 1;
1612 }
1613
1614 /**
1615 * Returns a key binding for this object. The value returned is an
1616 * java.lang.Object which must be cast to appropriate type depending
1617 * on the underlying implementation of the key. For example, if the
1618 * Object returned is a javax.swing.KeyStroke, the user of this
1619 * method should do the following:
1620 * <pre>{@code
1621 * Component c = <get the component that has the key bindings>
1622 * AccessibleContext ac = c.getAccessibleContext();
1623 * AccessibleKeyBinding akb = ac.getAccessibleKeyBinding();
1624 * for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) {
1625 * Object o = akb.getAccessibleKeyBinding(i);
1626 * if (o instanceof javax.swing.KeyStroke) {
1627 * javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o;
1628 * <do something with the key binding>
1629 * }
1630 * }
1631 * }</pre>
1632 *
1633 * @param i zero-based index of the key bindings
1634 * @return a javax.lang.Object which specifies the key binding
1635 * @exception IllegalArgumentException if the index is
1636 * out of bounds
1637 * @see #getAccessibleKeyBindingCount
1638 */
1639 public java.lang.Object getAccessibleKeyBinding(int i) {
1640 if (i != 0) {
1641 throw new IllegalArgumentException();
1642 }
1643 return KeyStroke.getKeyStroke(mnemonic, 0);
1644 }
1645 }
1646
1647 } // AccessibleJComponent
1648 }
|