用层来模拟ToolTip的部分功能,可以做出不规则形状

CSDN中一位XD想要一个类似QQ上的ToolTip效果(就像有人发言那样的不规则形状)

我一开始用继承JToolTip的方法做了一个,但是由于JToolTip不能设置透明,所以不规则形状做不出来,只好放弃,现在是继承JPanel后用层来实现的。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.text.View;

import com.sun.java.swing.SwingUtilities2;

/**
 * 用层来模拟ToolTip的部分功能,可以做出非规则形状
 * @author 五斗米 <如转载请保留作者和出处>
 * @blog http://blog.csdn.net/mq612
 */
public class Test {
 private JFrame frame = null;

 private Box box = null; // 为了将MyButton放到一个合适的位置,采用这个比较麻烦的Box来管理

 private MyButton button = null;

 private MyToolTip tip = null;

 public Test() {
  frame = new JFrame("MyToolTip");
  box = Box.createVerticalBox();
  button = new MyButton("Button");
  tip = new MyToolTip(frame.getLayeredPane(), "向Java战友问好!");
  button.setMyToolTip(tip);
  box.add(Box.createVerticalGlue());
  Box box_ = Box.createHorizontalBox();
  box_.add(Box.createHorizontalGlue());
  box_.add(button);
  box_.add(Box.createHorizontalGlue());
  box.add(box_);
  box.add(Box.createVerticalGlue());
  frame.getContentPane().add(box, BorderLayout.CENTER);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setSize(360, 220);
  frame.setLocationRelativeTo(null);
  frame.setVisible(true);
 }

 public static void main(String args[]) {
  new Test();
 }

 /**
  * 继承JButton,实现了MouseListener接口,当鼠标移动到该按钮上,显示MyToolTip
  * @author 五斗米
  * http://blog.csdn.net/mq612
  */
 class MyButton extends JButton implements MouseListener {
  private static final long serialVersionUID = -6373246716080645309L;

  private MyToolTip tip = null;

  // JButton的构造很多,都可以适用
  public MyButton(String text) {
   super(text);
   this.addMouseListener(this);
  }

  // 设置MyToolTip
  public void setMyToolTip(MyToolTip tip) {
   this.tip = tip;
  }

  public MyToolTip getMyToolTip() {
   return tip;
  }

  public void mouseClicked(MouseEvent e) {
  }

  // 当鼠标进入时显示,也可以加一个定时器来延时显示
  public void mouseEntered(MouseEvent e) {
   Point p = getLocationOnScreen();
   SwingUtilities.convertPointFromScreen(p, frame.getContentPane());
   tip.setLocation(new Point(p.x - tip.getWidth() + 10, p.y - tip.getHeight() + 10));
   tip.setVisible(true);
  }

  // 鼠标离开即消失
  public void mouseExited(MouseEvent e) {
   tip.setVisible(false);
  }

  public void mousePressed(MouseEvent e) {
  }

  public void mouseReleased(MouseEvent e) {
  }

 }

 /**
  * 继承JPanel,因为可以设置透明,所以我们很容易就可以做出不规则形状来,但是很遗憾,它的缺点是位置不能超出JFrame,否则超出部分无法显示
  * @author 五斗米
  * http://blog.csdn.net/mq612
  */
 class MyToolTip extends JPanel {

  private static final long serialVersionUID = -1405474493135741335L;

  private String text = null; // 将要显示的字符串

  private JLayeredPane lp = null; // 我们要用到的层

  public MyToolTip(JLayeredPane lp, String text) {
   this.lp = lp;
   this.text = text;
   this.setOpaque(false);
   lp.add(this, new Integer(JLayeredPane.POPUP_LAYER)); // 将组件放在弹出层中,这样就可以浮现在其它组件之上
   this.setSize(this.getPreferredSize());
   this.setVisible(false); // 设置组件不可视
  }

  public void setText(String text) {
   this.text = text;
   this.setSize(this.getPreferredSize()); // 改变文字后需要重新计算Size
  }

  public String getText() {
   return text;
  }

  public JLayeredPane getLp() {
   return lp;
  }

  public void setLp(JLayeredPane lp) {
   this.lp = lp;
  }

  // 画背景和文字
  protected void paintComponent(Graphics g) {
   super.paintComponent(g);
   Graphics2D g2d = (Graphics2D) g;
   g2d
     .setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   g2d.setColor(new Color(205, 235, 235)); // 背景颜色
   g2d.fill(this.getArea(this.getSize()));
   g2d.setColor(new Color(40, 130, 180)); // 文字颜色
   g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
     RenderingHints.VALUE_ANTIALIAS_OFF);
   g2d.drawString(text, 25 / 2, (getHeight() - 10) / 2 + 5);
  }

  // 画边框
  protected void paintBorder(Graphics g) {
   super.paintBorder(g);
   Graphics2D g2d = (Graphics2D) g;
   g2d
     .setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   g2d.setColor(new Color(95, 145, 145)); // 边线颜色
   g2d.draw(this.getArea(this.getSize()));
  }

  /**
   * 返回适合的Size
   */
  public Dimension getPreferredSize() {
   Font font = getFont();
   FontMetrics fm = getFontMetrics(font);
   Insets insets = getInsets();
   Dimension prefSize = new Dimension(insets.left + insets.right, insets.top
     + insets.bottom);
   if ((text == null) || text.equals("")) {
    text = "";
   } else {
    View v = (this != null) ? (View) getClientProperty("html") : null;
    if (v != null) {
     prefSize.width += (int) v.getPreferredSpan(View.X_AXIS);
     prefSize.height += (int) v.getPreferredSpan(View.Y_AXIS);
    } else {
     prefSize.width += SwingUtilities2.stringWidth(this, fm, text) + 25; // 25为多加的部分
     prefSize.height += fm.getHeight() + 10; // 10为多加的部分
    }
   }
   return prefSize;
  }

  // 返回画图所需要的区域
  private Area getArea(Dimension dim) {
   Shape r = new RoundRectangle2D.Float(0, 0, dim.width - 1, dim.height - 10, 5, 5); // 圆角矩形
   Area area = new Area(r);
   Polygon polygon = new Polygon(); // 多边形
   polygon.addPoint(dim.width - 15, dim.height - 10);
   polygon.addPoint(dim.width - 5, dim.height - 10);
   polygon.addPoint(dim.width, dim.height);
   area.add(new Area(polygon)); // 合并
   return area; // 返回
  }

 }

}

 

最新修改(2007-03-09):

一、上面代码中鼠标一进入按钮就会显示MyToolTip,当初没有加延时显示功能,现在补上,替换MyButton类的代码:

class MyButton extends JButton implements MouseListener, ActionListener {
        private static final long serialVersionUID = -6373246716080645309L;
        private Timer timer = null;
        private MyToolTip tip = null;
       
        // JButton的构造很多,都可以适用
        public MyButton(String text) {
            super(text);
            timer = new Timer(1000, this); // 构造定时器,这里使用的是javax.swing.Timer
            this.addMouseListener(this);
        }
       
        // 设置MyToolTip
        public void setMyToolTip(MyToolTip tip) {
            this.tip = tip;
        }
       
        public MyToolTip getMyToolTip() {
            return tip;
        }
       
        public void mouseClicked(MouseEvent e) {
        }
       
        // 当鼠标进入时显示,也可以加一个定时器来延时显示
        public void mouseEntered(MouseEvent e) {
            timer.start(); // 启动定时器
        }
       
        // 鼠标离开即消失
        public void mouseExited(MouseEvent e) {
            tip.setVisible(false);
            timer.stop();
        }
       
        public void mousePressed(MouseEvent e) {
        }
       
        public void mouseReleased(MouseEvent e) {
        }
       
        public void actionPerformed(ActionEvent e) {
            timer.stop();
            Point p = getLocationOnScreen();
            SwingUtilities.convertPointFromScreen(p, frame.getContentPane());
            tip.setLocation(new Point(p.x - tip.getWidth() + 10, p.y - tip.getHeight() + 10));
            tip.setVisible(true);
        }
       
    }

 

二、上面的代码中使用了com.sun.java.swing包中的SwingUtilities2类,使用1.6版本JDK可以使用下面方法替代:

SwingUtilities.computeStringWidth(fm, text) + 25; // 25为多加的部分

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
双层tooltip是一种常见的JavaScript技术,用于在网页中创建具有多个层级的工具提示。它可以在用户将鼠标悬停在某个元素上时显示一个浮动的信息框,通常用于提供更详细的说明或额外的内容。 实现双层tooltip的方法有很多种,下面是一种简单的实现方式: 首先,在HTML中创建一个包含两个层级的元素,例如一个父元素和一个子元素。父元素用于触发tooltip的显示,子元素用于显示tooltip的内容。 ```html <div class="tooltip"> <span class="trigger">Hover me</span> <div class="tooltip-content">Tooltip content</div> </div> ``` 接下来,使用CSS样式来定义tooltip的外观和位置: ```css .tooltip { position: relative; display: inline-block; } .tooltip .tooltip-content { display: none; position: absolute; top: 100%; left: 0; background-color: #f9f9f9; padding: 5px; border: 1px solid #ccc; } .tooltip:hover .tooltip-content { display: block; } ``` 最后,使用JavaScript来处理鼠标事件,以实现tooltip的显示和隐藏: ```javascript const tooltipTrigger = document.querySelector('.trigger'); const tooltipContent = document.querySelector('.tooltip-content'); tooltipTrigger.addEventListener('mouseover', () => { tooltipContent.style.display = 'block'; }); tooltipTrigger.addEventListener('mouseout', () => { tooltipContent.style.display = 'none'; }); ``` 这样,当鼠标悬停在触发元素上时,tooltip内容会显示出来;当鼠标移出触发元素时,tooltip内容会隐藏起来。 这只是一种简单的实现方式,你可以根据自己的需求进行修改和扩展。另外,还有很多现成的JavaScript库和框架可以帮助你更方便地实现双层tooltip效果,例如Bootstrap、jQuery等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值