如何在超出边界时隐藏JToolTip背景?

时间:2016-12-05 22:38:32

标签: java swing tooltip

我为我的应用程序创建了这个自定义JToolTip。当工具提示完全显示在JFrame中时,没有可见的背景(预期),但是当工具提示显示在JFrame外部时,背景将是可见的。我怎样才能将它删除?

我已尝试setBackground(new Color(255, 255, 255, 0));使用' 0' alpha值,以确保背景是透明的,但没有做到这一点。

框架内的工具提示,正如所料:

tooltip inside frame

工具提示超出JFrame,带有不需要的背景:

tooltip exceeding frame

自定义JTooltip:

 public class DefaultToolTip extends JToolTip {

        public DefaultToolTip() {
            setOpaque(false);
            setPreferredSize(new Dimension(275, 30));
            setBackground(new Color(255, 255, 255, 0));
        }

        @Override
        public void addNotify() {
            super.addNotify();
            setOpaque(false);
            Component parent = this.getParent();
            if (parent != null) {
                if (parent instanceof JComponent) {
                    JComponent jparent = (JComponent) parent;
                    jparent.setOpaque(false);
                }
            }
        }

        @Override
        public void paint(Graphics g) {
            String text = getComponent().getToolTipText();

            addNotify();
            Graphics2D g2d = drawComponent(g);
            drawText(text, g2d);

            g2d.dispose();
        }

        private void drawText(String text, Graphics2D g2d) {
            //Draw the text
            int cHeight = getComponent().getHeight();
            FontMetrics fm = g2d.getFontMetrics();
            g2d.setColor(Color.WHITE);
            if (cHeight > getHeight())
                g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (getHeight() + fm.getAscent()) / 2 + 2);
            else
                g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (cHeight + fm.getAscent()) / 2 + 2);
        }

        private Graphics2D drawComponent(Graphics g) {
            //Create a round rectangle
            Shape round = new RoundRectangle2D.Float(0, 8, getWidth(), getHeight(), 8, 8);

            //Draw the background
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(Color.GRAY);
            g2d.fill(round);

            //Draw the left triangle
            Point p1 = new Point(getWidth() / 2, getHeight() - 30);
            Point p2 = new Point(getWidth() / 2 + 8, getHeight() - 20);
            Point p3 = new Point(getWidth() / 2 - 8, getHeight() - 20);
            int[] xs = {p1.x, p2.x, p3.x};
            int[] ys = {p1.y, p2.y, p3.y};
            Polygon triangle = new Polygon(xs, ys, xs.length);
            g2d.fillPolygon(triangle);
            return g2d;
        }
    }

解决方案

有些事情发生了变化,工具提示的行为与预期一致。 paint方法已被paintComponent方法取代,addNotify调用已被删除,方法已更新以获取组件的窗口并为其提供透明背景。还需要setBorder(BorderFactory.createEmptyBorder());来删除组件默认边框。

public class DefaultToolTip extends JToolTip {

    public DefaultToolTip() {
        setOpaque(false);
        setPreferredSize(new Dimension(275, 30));
        setBackground(new Color(255, 255, 255, 0));
        setBorder(BorderFactory.createEmptyBorder());
    }

    @Override
    public void addNotify() {
        super.addNotify();
        setOpaque(false);
        Component parent = this.getParent();
        if (parent != null) {
            if (parent instanceof JComponent) {
                JComponent jparent = (JComponent) parent;
                jparent.setOpaque(false);
            }
        }
        Window window = SwingUtilities.windowForComponent(this);
        try {
            window.setBackground(new Color(255, 255, 255, 0));
        } catch (IllegalComponentStateException e) {
            //Do nothing
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        //super.paintComponent(g);
        String text = getComponent().getToolTipText();

        Graphics2D g2d = drawComponent(g);
        drawText(text, g2d);

        g2d.dispose();
    }

    private void drawText(String text, Graphics2D g2d) {
        //Draw the text
        int cHeight = getComponent().getHeight();
        FontMetrics fm = g2d.getFontMetrics();
        g2d.setColor(Color.WHITE);
        if (cHeight > getHeight())
            g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (getHeight() + fm.getAscent()) / 2 + 2);
        else
            g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (cHeight + fm.getAscent()) / 2 + 2);
    }

    private Graphics2D drawComponent(Graphics g) {
        //Create a round rectangle
        Shape round = new RoundRectangle2D.Float(0, 8, getWidth(), getHeight(), 8, 8);

        //Draw the background
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.GRAY);
        g2d.fill(round);

        //Draw the left triangle
        Point p1 = new Point(getWidth() / 2, getHeight() - 30);
        Point p2 = new Point(getWidth() / 2 + 8, getHeight() - 20);
        Point p3 = new Point(getWidth() / 2 - 8, getHeight() - 20);
        int[] xs = {p1.x, p2.x, p3.x};
        int[] ys = {p1.y, p2.y, p3.y};
        Polygon triangle = new Polygon(xs, ys, xs.length);
        g2d.fillPolygon(triangle);
        return g2d;
    }
}

但请注意,super.paintComponent(g)已被注释掉,因为它会再次绘制文字。

1 个答案:

答案 0 :(得分:1)

不知道其中任何一项是否会有所帮助,但是:

  1. 不要覆盖绘画(...)。自定义绘画通过覆盖paintComponent(...)

  2. 完成
  3. 调用super.paintComponent(...)作为第一个语句

  4. 不要在绘画方法中调用addNotify()。绘画方法仅适用于绘画。

  5.   

    使用' 0' alpha值以确保背景透明,

    Swing组件不知道如何处理透明背景。只需使组件不透明。

    当工具提示与组件重叠时。工具提示实际上在显示之前添加到JWindow。因此,在addNotify()逻辑中,您可以搜索窗口并使其透明。

    退房:

    Window window = SwingUtilities.windowForComponent(...);