简体   繁体   English

标题中的图标和顺序标题

[英]Icon in titledBorder title

Hi is it possible to place an icon in the title of a titledBorder for example the following code:嗨,是否可以在 titledBorder 的标题中放置一个图标,例如以下代码:


import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

public class TitledExample extends JPanel {

  public TitledExample() {
    super(true);

    this.setLayout(new GridLayout(1, 1, 5, 5));

    JLabel label = new JLabel("Titled Border");
    label.setHorizontalAlignment(JLabel.CENTER);

    TitledBorder titled = new TitledBorder("Image here ?? Title");
    label.setBorder(titled);

    add(label);
  }

Thanks , Cheers谢谢,干杯

Try subclassing TitledBorder , and override the paintBorder method:尝试TitledBorder ,并覆盖paintBorder方法:

 @Override
 public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) 
 {
     super.paintBorder(c, g, x, y, width, height);

     // Now use the graphics context to draw whatever needed
     g.drawImage(img, xImageOffset, yImageOffset, imgWidth, imgHeight, observer);
 }

Not desperately sure that this is entirely right method call, but you get the idea;不太确定这是完全正确的方法调用,但你明白了; once you have access to the Graphics object, you can paint pretty much whatever you need.一旦您可以访问Graphics对象,您几乎可以绘制任何您需要的东西。

It's probably not what you want, but maybe a nice Unicode™ glyph or two would do.这可能不是您想要的,但也许一两个不错的Unicode™ 字形就可以了。

Addendum: @rhu's approach is preferable, but I couldn't resist trying this:附录: @rhu 的方法更可取,但我忍不住尝试了这个:

在此处输入图片说明

TitledBorder titled = BorderFactory.createTitledBorder("\u2615");
titled.setTitleFont(new Font(Font.Dialog, Font.PLAIN, 32));
titled.setTitleColor(Color.blue);
label.setBorder(titled);

You can use reflection to get access to the JLabel used by the TitledBorder.您可以使用反射来访问 TitledBorder 使用的 JLabel。

try
{
    // Get the field declaration
    Field f = TitledBorder.class.getDeclaredField("label");
    // Make it accessible (it normally is private)
    f.setAccessible(true);
    // Get the label
    JLabel borderLabel = (JLabel)f.get(titledBorder);
    // Put the field accessibility back to default
    f.setAccessible(false);
    // Set the icon and do whatever you want with your label
    borderLabel.setIcon(myIcon);
}
catch(Exception e)
{
    e.printStackTrace();
}

It is important to note that this will not work in Java 10, as it will have stricter rules on the use of setAccessible重要的是要注意这在 Java 10 中不起作用,因为它对setAccessible的使用有更严格的规则

Another approach is to use html formatting.另一种方法是使用 html 格式。

Use the img component to visualize your graphic.使用img组件来可视化您的图形。

结果

Here is a full working example:这是一个完整的工作示例:

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.border.TitledBorder;

public class TitledBorderIcon {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            
            // Setup GUI
            JFrame mdi = new JFrame("Test Titled Border with Icon");
            mdi.setSize(600, 400);
            mdi.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

            JLabel label = new JLabel("My Component");
            label.setHorizontalAlignment(JLabel.CENTER);
            mdi.add(label);
            
            // Build the html formatted text
            StringBuilder sb = new StringBuilder();           
            sb.append("<html>");
                sb.append("<img src=\"https://via.placeholder.com/24/007AAE/\">");
                sb.append("&nbsp;My Title");
            sb.append("</html>");
            
            TitledBorder titled = new TitledBorder(sb.toString());
            label.setBorder(titled);
            
            mdi.setVisible(true);
        });
    }    
}

The TitledBorder uses a JLabel to paint the text on the border. TitledBorder 使用 JLabel 在边框上绘制文本。 Unfortunately, the JLabel is a private field.不幸的是,JLabel 是一个私有字段。 There are two ways you can add the icon:有两种方法可以添加图标:

  • access the private JLabel field, and set the icon on the JLabel.访问私有 JLabel 字段,并在 JLabel 上设置图标。

  • subclass TitledBorder and re-implement the paintBorder method.子类 TitledBorder 并重新实现paintBorder方法。 I'd ID
    probably also add a constructor that takes a JLabel so one can可能还添加一个带有 JLabel 的构造函数,这样就可以
    control what is painted on the border.控制在边框上绘制的内容。

You can simply copy TitledBorder to your class path and customize it as you want:您可以简单地将TitledBorder复制到您的类路径并根据需要对其进行自定义:

For example:例如:

public class IconTitleBorderFactory {

    public static Border create(Consumer<JLabel> leftLabelDecorator, Consumer<JLabel> rightLabelDecorator) {

        CustomTitledBorder border = new CustomTitledBorder(" ");
        border.getLabel().setHorizontalTextPosition(SwingConstants.LEFT);
        leftLabelDecorator.accept(border.getLabel());

        CustomTitledBorder border2 = new CustomTitledBorder(" ");
        border2.setTitleJustification(TitledBorder.RIGHT);
        rightLabelDecorator.accept(border2.getLabel());

        border.setBorder(border2);

        return border;
    }

    private static class CustomTitledBorder extends AbstractBorder {
        protected String title;
        protected Border border;
        protected int titlePosition;
        protected int titleJustification;
        protected Font titleFont;
        protected Color titleColor;

        private final JLabel label;

        /**
         * Use the default vertical orientation for the title text.
         */
        static public final int DEFAULT_POSITION = 0;
        /** Position the title above the border's top line. */
        static public final int ABOVE_TOP = 1;
        /** Position the title in the middle of the border's top line. */
        static public final int TOP = 2;
        /** Position the title below the border's top line. */
        static public final int BELOW_TOP = 3;
        /** Position the title above the border's bottom line. */
        static public final int ABOVE_BOTTOM = 4;
        /** Position the title in the middle of the border's bottom line. */
        static public final int BOTTOM = 5;
        /** Position the title below the border's bottom line. */
        static public final int BELOW_BOTTOM = 6;

        /**
         * Use the default justification for the title text.
         */
        static public final int DEFAULT_JUSTIFICATION = 0;
        /** Position title text at the left side of the border line. */
        static public final int LEFT = 1;
        /** Position title text in the center of the border line. */
        static public final int CENTER = 2;
        /** Position title text at the right side of the border line. */
        static public final int RIGHT = 3;
        /**
         * Position title text at the left side of the border line for left to right
         * orientation, at the right side of the border line for right to left
         * orientation.
         */
        static public final int LEADING = 4;
        /**
         * Position title text at the right side of the border line for left to right
         * orientation, at the left side of the border line for right to left
         * orientation.
         */
        static public final int TRAILING = 5;

        // Space between the border and the component's edge
        static protected final int EDGE_SPACING = 2;

        // Space between the border and text
        static protected final int TEXT_SPACING = 2;

        // Horizontal inset of text that is left or right justified
        static protected final int TEXT_INSET_H = 5;

        /**
         * Creates a TitledBorder instance.
         *
         * @param title the title the border should display
         */
        public CustomTitledBorder(String title) {
            this(null, title, LEADING, DEFAULT_POSITION, null, null);
        }

        /**
         * Creates a TitledBorder instance with the specified border and an empty title.
         *
         * @param border the border
         */
        public CustomTitledBorder(Border border) {
            this(border, "", LEADING, DEFAULT_POSITION, null, null);
        }

        /**
         * Creates a TitledBorder instance with the specified border and title.
         *
         * @param border the border
         * @param title  the title the border should display
         */
        public CustomTitledBorder(Border border, String title) {
            this(border, title, LEADING, DEFAULT_POSITION, null, null);
        }

        /**
         * Creates a TitledBorder instance with the specified border, title,
         * title-justification, and title-position.
         *
         * @param border             the border
         * @param title              the title the border should display
         * @param titleJustification the justification for the title
         * @param titlePosition      the position for the title
         */
        public CustomTitledBorder(Border border, String title, int titleJustification, int titlePosition) {
            this(border, title, titleJustification, titlePosition, null, null);
        }

        /**
         * Creates a TitledBorder instance with the specified border, title,
         * title-justification, title-position, and title-font.
         *
         * @param border             the border
         * @param title              the title the border should display
         * @param titleJustification the justification for the title
         * @param titlePosition      the position for the title
         * @param titleFont          the font for rendering the title
         */
        public CustomTitledBorder(Border border, String title, int titleJustification, int titlePosition, Font titleFont) {
            this(border, title, titleJustification, titlePosition, titleFont, null);
        }

        /**
         * Creates a TitledBorder instance with the specified border, title,
         * title-justification, title-position, title-font, and title-color.
         *
         * @param border             the border
         * @param title              the title the border should display
         * @param titleJustification the justification for the title
         * @param titlePosition      the position for the title
         * @param titleFont          the font of the title
         * @param titleColor         the color of the title
         */
        @ConstructorProperties({ "border", "title", "titleJustification", "titlePosition", "titleFont", "titleColor" })
        public CustomTitledBorder(Border border, String title, int titleJustification, int titlePosition, Font titleFont,
                Color titleColor) {
            this.title = title;
            this.border = border;
            this.titleFont = titleFont;
            this.titleColor = titleColor;

            setTitleJustification(titleJustification);
            setTitlePosition(titlePosition);

            this.label = new JLabel();
            this.label.setOpaque(false);
            this.label.putClientProperty(BasicHTML.propertyKey, null);
        }

        public JLabel getLabel() {
            return label;
        }

        /**
         * Paints the border for the specified component with the specified position and
         * size.
         * 
         * @param c      the component for which this border is being painted
         * @param g      the paint graphics
         * @param x      the x position of the painted border
         * @param y      the y position of the painted border
         * @param width  the width of the painted border
         * @param height the height of the painted border
         */
        @Override
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            Border border = getBorder();
            String title = getTitle();
            if ((title != null) && !title.isEmpty()) {
                int edge = (border instanceof CustomTitledBorder) ? 0 : EDGE_SPACING;
                JLabel label = getLabel(c);
                Dimension size = label.getPreferredSize();
                Insets insets = getBorderInsets(border, c, new Insets(0, 0, 0, 0));

                int borderX = x + edge;
                int borderY = y + edge;
                int borderW = width - edge - edge;
                int borderH = height - edge - edge;

                int labelY = y;
                int labelH = size.height;
                int position = getPosition();
                switch (position) {
                case ABOVE_TOP:
                    insets.left = 0;
                    insets.right = 0;
                    borderY += labelH - edge;
                    borderH -= labelH - edge;
                    break;
                case TOP:
                    insets.top = edge + insets.top / 2 - labelH / 2;
                    if (insets.top < edge) {
                        borderY -= insets.top;
                        borderH += insets.top;
                    } else {
                        labelY += insets.top;
                    }
                    break;
                case BELOW_TOP:
                    labelY += insets.top + edge;
                    break;
                case ABOVE_BOTTOM:
                    labelY += height - labelH - insets.bottom - edge;
                    break;
                case BOTTOM:
                    labelY += height - labelH;
                    insets.bottom = edge + (insets.bottom - labelH) / 2;
                    if (insets.bottom < edge) {
                        borderH += insets.bottom;
                    } else {
                        labelY -= insets.bottom;
                    }
                    break;
                case BELOW_BOTTOM:
                    insets.left = 0;
                    insets.right = 0;
                    labelY += height - labelH;
                    borderH -= labelH - edge;
                    break;
                }
                insets.left += edge + TEXT_INSET_H;
                insets.right += edge + TEXT_INSET_H;

                int labelX = x;
                int labelW = width - insets.left - insets.right;
                if (labelW > size.width) {
                    labelW = size.width;
                }
                switch (getJustification(c)) {
                case LEFT:
                    labelX += insets.left;
                    break;
                case RIGHT:
                    labelX += width - insets.right - labelW;
                    break;
                case CENTER:
                    labelX += (width - labelW) / 2;
                    break;
                }

                if (border != null) {
                    if ((position != TOP) && (position != BOTTOM)) {
                        border.paintBorder(c, g, borderX, borderY, borderW, borderH);
                    } else {
                        Graphics g2 = g.create();
                        if (g2 instanceof Graphics2D) {
                            Graphics2D g2d = (Graphics2D) g2;
                            Path2D path = new Path2D.Float();
                            path.append(new Rectangle(borderX, borderY, borderW, labelY - borderY), false);
                            path.append(new Rectangle(borderX, labelY, labelX - borderX - TEXT_SPACING, labelH), false);
                            path.append(new Rectangle(labelX + labelW + TEXT_SPACING, labelY,
                                    borderX - labelX + borderW - labelW - TEXT_SPACING, labelH), false);
                            path.append(new Rectangle(borderX, labelY + labelH, borderW,
                                    borderY - labelY + borderH - labelH), false);
                            g2d.clip(path);
                        }
                        border.paintBorder(c, g2, borderX, borderY, borderW, borderH);
                        g2.dispose();
                    }
                }
                g.translate(labelX, labelY);
                label.setSize(labelW, labelH);
                label.paint(g);
                g.translate(-labelX, -labelY);
            } else if (border != null) {
                border.paintBorder(c, g, x, y, width, height);
            }
        }

        /**
         * Reinitialize the insets parameter with this Border's current Insets.
         * 
         * @param c      the component for which this border insets value applies
         * @param insets the object to be reinitialized
         */
        @Override
        public Insets getBorderInsets(Component c, Insets insets) {
            Border border = getBorder();
            insets = getBorderInsets(border, c, insets);

            String title = getTitle();
            if ((title != null) && !title.isEmpty()) {
                int edge = (border instanceof CustomTitledBorder) ? 0 : EDGE_SPACING;
                JLabel label = getLabel(c);
                Dimension size = label.getPreferredSize();

                switch (getPosition()) {
                case ABOVE_TOP:
                    insets.top += size.height - edge;
                    break;
                case TOP: {
                    if (insets.top < size.height) {
                        insets.top = size.height - edge;
                    }
                    break;
                }
                case BELOW_TOP:
                    insets.top += size.height;
                    break;
                case ABOVE_BOTTOM:
                    insets.bottom += size.height;
                    break;
                case BOTTOM: {
                    if (insets.bottom < size.height) {
                        insets.bottom = size.height - edge;
                    }
                    break;
                }
                case BELOW_BOTTOM:
                    insets.bottom += size.height - edge;
                    break;
                }
                insets.top += edge + TEXT_SPACING;
                insets.left += edge + TEXT_SPACING;
                insets.right += edge + TEXT_SPACING;
                insets.bottom += edge + TEXT_SPACING;
            }
            return insets;
        }

        /**
         * Returns whether or not the border is opaque.
         */
        @Override
        public boolean isBorderOpaque() {
            return false;
        }

        /**
         * Returns the title of the titled border.
         *
         * @return the title of the titled border
         */
        public String getTitle() {
            return title;
        }

        /**
         * Returns the border of the titled border.
         *
         * @return the border of the titled border
         */
        public Border getBorder() {
            return border != null ? border : UIManager.getBorder("TitledBorder.border");
        }

        /**
         * Returns the title-position of the titled border.
         *
         * @return the title-position of the titled border
         */
        public int getTitlePosition() {
            return titlePosition;
        }

        /**
         * Returns the title-justification of the titled border.
         *
         * @return the title-justification of the titled border
         */
        public int getTitleJustification() {
            return titleJustification;
        }

        /**
         * Returns the title-font of the titled border.
         *
         * @return the title-font of the titled border
         */
        public Font getTitleFont() {
            return titleFont == null ? UIManager.getFont("TitledBorder.font") : titleFont;
        }

        /**
         * Returns the title-color of the titled border.
         *
         * @return the title-color of the titled border
         */
        public Color getTitleColor() {
            return titleColor == null ? UIManager.getColor("TitledBorder.titleColor") : titleColor;
        }

        // REMIND(aim): remove all or some of these set methods?

        /**
         * Sets the title of the titled border.
         * 
         * @param title the title for the border
         */
        public void setTitle(String title) {
            this.title = title;
        }

        /**
         * Sets the border of the titled border.
         * 
         * @param border the border
         */
        public void setBorder(Border border) {
            this.border = border;
        }

        /**
         * Sets the title-position of the titled border.
         * 
         * @param titlePosition the position for the border
         */
        public void setTitlePosition(int titlePosition) {
            switch (titlePosition) {
            case ABOVE_TOP:
            case TOP:
            case BELOW_TOP:
            case ABOVE_BOTTOM:
            case BOTTOM:
            case BELOW_BOTTOM:
            case DEFAULT_POSITION:
                this.titlePosition = titlePosition;
                break;
            default:
                throw new IllegalArgumentException(titlePosition + " is not a valid title position.");
            }
        }

        /**
         * Sets the title-justification of the titled border.
         * 
         * @param titleJustification the justification for the border
         */
        public void setTitleJustification(int titleJustification) {
            switch (titleJustification) {
            case DEFAULT_JUSTIFICATION:
            case LEFT:
            case CENTER:
            case RIGHT:
            case LEADING:
            case TRAILING:
                this.titleJustification = titleJustification;
                break;
            default:
                throw new IllegalArgumentException(titleJustification + " is not a valid title justification.");
            }
        }

        /**
         * Sets the title-font of the titled border.
         * 
         * @param titleFont the font for the border title
         */
        public void setTitleFont(Font titleFont) {
            this.titleFont = titleFont;
        }

        /**
         * Sets the title-color of the titled border.
         * 
         * @param titleColor the color for the border title
         */
        public void setTitleColor(Color titleColor) {
            this.titleColor = titleColor;
        }

        /**
         * Returns the minimum dimensions this border requires in order to fully display
         * the border and title.
         * 
         * @param c the component where this border will be drawn
         * @return the {@code Dimension} object
         */
        public Dimension getMinimumSize(Component c) {
            Insets insets = getBorderInsets(c);
            Dimension minSize = new Dimension(insets.right + insets.left, insets.top + insets.bottom);
            String title = getTitle();
            if ((title != null) && !title.isEmpty()) {
                JLabel label = getLabel(c);
                Dimension size = label.getPreferredSize();

                int position = getPosition();
                if ((position != ABOVE_TOP) && (position != BELOW_BOTTOM)) {
                    minSize.width += size.width;
                } else if (minSize.width < size.width) {
                    minSize.width += size.width;
                }
            }
            return minSize;
        }

        /**
         * Returns the baseline.
         *
         * @throws NullPointerException     {@inheritDoc}
         * @throws IllegalArgumentException {@inheritDoc}
         * @see javax.swing.JComponent#getBaseline(int, int)
         * @since 1.6
         */
        @Override
        public int getBaseline(Component c, int width, int height) {
            if (c == null) {
                throw new NullPointerException("Must supply non-null component");
            }
            if (width < 0) {
                throw new IllegalArgumentException("Width must be >= 0");
            }
            if (height < 0) {
                throw new IllegalArgumentException("Height must be >= 0");
            }
            Border border = getBorder();
            String title = getTitle();
            if ((title != null) && !title.isEmpty()) {
                int edge = (border instanceof CustomTitledBorder) ? 0 : EDGE_SPACING;
                JLabel label = getLabel(c);
                Dimension size = label.getPreferredSize();
                Insets insets = getBorderInsets(border, c, new Insets(0, 0, 0, 0));

                int baseline = label.getBaseline(size.width, size.height);
                switch (getPosition()) {
                case ABOVE_TOP:
                    return baseline;
                case TOP:
                    insets.top = edge + (insets.top - size.height) / 2;
                    return (insets.top < edge) ? baseline : baseline + insets.top;
                case BELOW_TOP:
                    return baseline + insets.top + edge;
                case ABOVE_BOTTOM:
                    return baseline + height - size.height - insets.bottom - edge;
                case BOTTOM:
                    insets.bottom = edge + (insets.bottom - size.height) / 2;
                    return (insets.bottom < edge) ? baseline + height - size.height
                            : baseline + height - size.height + insets.bottom;
                case BELOW_BOTTOM:
                    return baseline + height - size.height;
                }
            }
            return -1;
        }

        /**
         * Returns an enum indicating how the baseline of the border changes as the size
         * changes.
         *
         * @throws NullPointerException {@inheritDoc}
         * @see javax.swing.JComponent#getBaseline(int, int)
         * @since 1.6
         */
        @Override
        public Component.BaselineResizeBehavior getBaselineResizeBehavior(Component c) {
            super.getBaselineResizeBehavior(c);
            switch (getPosition()) {
            case CustomTitledBorder.ABOVE_TOP:
            case CustomTitledBorder.TOP:
            case CustomTitledBorder.BELOW_TOP:
                return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
            case CustomTitledBorder.ABOVE_BOTTOM:
            case CustomTitledBorder.BOTTOM:
            case CustomTitledBorder.BELOW_BOTTOM:
                return JComponent.BaselineResizeBehavior.CONSTANT_DESCENT;
            }
            return Component.BaselineResizeBehavior.OTHER;
        }

        private int getPosition() {
            int position = getTitlePosition();
            if (position != DEFAULT_POSITION) {
                return position;
            }
            Object value = UIManager.get("TitledBorder.position");
            if (value instanceof Integer) {
                int i = (Integer) value;
                if ((0 < i) && (i <= 6)) {
                    return i;
                }
            } else if (value instanceof String) {
                String s = (String) value;
                if (s.equalsIgnoreCase("ABOVE_TOP")) {
                    return ABOVE_TOP;
                }
                if (s.equalsIgnoreCase("TOP")) {
                    return TOP;
                }
                if (s.equalsIgnoreCase("BELOW_TOP")) {
                    return BELOW_TOP;
                }
                if (s.equalsIgnoreCase("ABOVE_BOTTOM")) {
                    return ABOVE_BOTTOM;
                }
                if (s.equalsIgnoreCase("BOTTOM")) {
                    return BOTTOM;
                }
                if (s.equalsIgnoreCase("BELOW_BOTTOM")) {
                    return BELOW_BOTTOM;
                }
            }
            return TOP;
        }

        private int getJustification(Component c) {
            int justification = getTitleJustification();
            if ((justification == LEADING) || (justification == DEFAULT_JUSTIFICATION)) {
                return c.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT;
            }
            if (justification == TRAILING) {
                return c.getComponentOrientation().isLeftToRight() ? RIGHT : LEFT;
            }
            return justification;
        }

        protected Font getFont(Component c) {
            Font font = getTitleFont();
            if (font != null) {
                return font;
            }
            if (c != null) {
                font = c.getFont();
                if (font != null) {
                    return font;
                }
            }
            return new Font(Font.DIALOG, Font.PLAIN, 12);
        }

        private Color getColor(Component c) {
            Color color = getTitleColor();
            if (color != null) {
                return color;
            }
            return (c != null) ? c.getForeground() : null;
        }

        private JLabel getLabel(Component c) {
            // this.label.setText(getTitle());
            this.label.setFont(getFont(c));
            this.label.setForeground(getColor(c));
            this.label.setComponentOrientation(c.getComponentOrientation());
            this.label.setEnabled(c.isEnabled());
            return this.label;
        }

        private static Insets getBorderInsets(Border border, Component c, Insets insets) {
            if (border == null) {
                insets.set(0, 0, 0, 0);
            } else if (border instanceof AbstractBorder) {
                AbstractBorder ab = (AbstractBorder) border;
                insets = ab.getBorderInsets(c, insets);
            } else {
                Insets i = border.getBorderInsets(c);
                insets.set(i.top, i.left, i.bottom, i.right);
            }
            return insets;
        }

    }

}

Then:然后:

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {

        JFrame frame = new JFrame("Example");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel container = new JPanel();

        container.add(new JButton("A"));
        container.setBorder(IconTitleBorderFactory.create(leftLabel -> {
            leftLabel.setText("Information");
        }, rightLabel -> {
            rightLabel.setIcon(UIManager.getIcon("Tree.openIcon"));
        }));

        frame.setContentPane(container);

        frame.pack();
        frame.setSize(300, 300);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    });
}

Produces:产生:

在此处输入图片说明

Note: The labels are used only for painting.注意:标签仅用于绘画。 They are not on the screen.他们不在屏幕上。 Adding listeners, tooltip, or getLocation() will not work on them.添加侦听器、工具提示或getLocation()对它们不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM