现在的位置: 首页 > 综合 > 正文

不规则窗体形状的ToolTip (二)

2018年01月30日 ⁄ 综合 ⁄ 共 5839字 ⁄ 字号 评论关闭

前一篇利用层实现ToolTip,利用图形组合实现不规则的ToolTip    是实现不规则窗体的ToolTip的方法,该方法虽然实现了要求,但却有两点不足:

第一:该方法太笨拙,每个需要ToolTip的组件都得重新去设置一次新的ToolTip类;

第二:在ToolTip超出窗体边缘时,没法显示超出部分。

   于是乎觉得这样处理是不正确的,定有其他方法来更好的实现。所以在网上找了下。找了N久,还是在google中找到了比较满意的解决方法。而且该方法能解决上面的两点不足。    

这里说下该方法的思想。

第一用到了

01.PopupFactory.setSharedInstance(PopupFactory popu)//方法  

这里为什么要用该方法呢?原来所有的Popup的获取都会从该PopupFactory中获取,所以在这里调用该方法设置用于获取 Popup 的 PopupFactory后系统的调用Popup就在我们的控制范围内了。

所以我们就必须得重新实现PopupFactory类来拦截对JToolTip的处理。

第二用到了实时截图并实时绘制截图,使得我们呈现出来的JToolTip窗体和其周围的内容没有出入。

先看效果:

下面贴出代码:

自己实现的PopupFactory类,这里主要拦截了JToolTip。

 

package com.michael.swingx.tooltip;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JToolTip;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.border.Border;

public class NonRectanglePopupFactory extends PopupFactory {
    private static final int BORDER_PAD = 20;
    private static Robot robot;
    static {
	try {
	    robot = new Robot();
	} catch (Exception e) {
	}
    }

    public NonRectanglePopupFactory() {
    }

    @Override
    public Popup getPopup(Component owner, Component contents, int x, int y)
	    throws IllegalArgumentException {
	if (contents instanceof JToolTip) {
	    ((JToolTip) contents).setBorder(null);
	    Dimension dim = contents.getPreferredSize();
	    Rectangle bound = new Rectangle(x, y, dim.width + 2 * BORDER_PAD,
		    dim.height + 2 * BORDER_PAD);
	    /**
	     * 这是关键创建包含从屏幕中读取的像素的图像。该图像不包括鼠标光标。 
	     */
	    BufferedImage backgroundImage = robot.createScreenCapture(bound);
	    NonRectangleFrame frame = new NonRectangleFrame(owner, contents,
		    backgroundImage);
	    return super.getPopup(owner, frame, x, y);
	} else
	    return super.getPopup(owner, contents, x, y);
    }

    /**
     * 
     * @author mengke
     * @email wqjsir@foxmail.com
     * @version 1.0
     */
    class NonRectangleFrame extends JComponent {
	public NonRectangleFrame(Component owner, Component content,
		BufferedImage backgroundImage) {
	    setLayout(new BorderLayout());
	    add(content, BorderLayout.CENTER);
	    setBorder(new NonRectangleBorder(owner, content, backgroundImage));
	}
    }

    /**
     * @author mengke
     * @email wqjsir@foxmail.com
     * @version 1.0
     */
    class NonRectangleBorder implements Border {
	private BufferedImage leftImage;
	private BufferedImage rightImage;
	private BufferedImage topImage;
	private BufferedImage bottomImage;
	private Component content;
	private Color backColor = new Color(205, 235, 235);
	private Color borderColor = new Color(95, 145, 145);

	NonRectangleBorder(Component owner, Component content,
		BufferedImage backgroundImage) {
	    this.content = content;
	    // backColor = this.content.getBackground();
	    // borderColor  = backColor.darker();
	    generateLeftImage(backgroundImage);
	    generateTopImage(backgroundImage);
	    generateRightImage(backgroundImage);
	    generateBottomImage(backgroundImage);
	}

	@Override
	public void paintBorder(Component c, Graphics g, int x, int y,
		int width, int height) {
	    //绘制图形,这些图形是当前位置的截图图形
	    g.drawImage(leftImage, x, y, c);
	    g.drawImage(rightImage, x + width - BORDER_PAD, y, c);
	    g.drawImage(topImage, x + BORDER_PAD, y, c);
	    g.drawImage(bottomImage, x + BORDER_PAD, y + height - BORDER_PAD, c);
	    Rectangle bounds = new Rectangle(x, y, width, height);
	    Graphics2D g2d = (Graphics2D) g;
	    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
		    RenderingHints.VALUE_ANTIALIAS_ON);
	    g2d.setColor(backColor); // 背景颜色
	    content.setBackground(backColor);//使背景色与填充的多边形颜色一致
	    g2d.fill(getArea(bounds.getSize()));
	    g2d.setColor(borderColor);
	    g2d.draw(getArea(bounds.getSize()));//画边框

	    g.setColor(Color.black);
	}

	/**
	 * 返回画图所需要的区域<br>
	 * 这里主要用到了图形合并共能。通过图形合并我们可以实现各种自定义的图形
	 * 
	 * @param dim
	 * @return
	 */
	private Area getArea(Dimension dim) {
	    int roundX = BORDER_PAD - 2;
	    int roundY = BORDER_PAD - 2;
	    Shape r = new RoundRectangle2D.Float(roundX, roundY, dim.width
		    - roundX * 2, dim.height - roundY * 2, 5, 5); // 圆角矩形
	    Area area = new Area(r);
	    Polygon polygon = new Polygon();// 多边形
	    polygon.addPoint(22, roundY);
	    polygon.addPoint(35, roundY);
	    polygon.addPoint(22, 0);
	    area.add(new Area(polygon)); // 合并图形
	    return area;
	}

	@Override
	public Insets getBorderInsets(Component c) {
	    return new Insets(BORDER_PAD, BORDER_PAD, BORDER_PAD, BORDER_PAD);
	}

	@Override
	public boolean isBorderOpaque() {
	    return true;
	}

	private void generateLeftImage(BufferedImage backgroundImage) {
	    leftImage = backgroundImage.getSubimage(0, 0, BORDER_PAD,
		    backgroundImage.getHeight());
	}

	private void generateTopImage(BufferedImage backgroundImage) {
	    topImage = backgroundImage.getSubimage(BORDER_PAD, 0,
		    backgroundImage.getWidth() - 2 * BORDER_PAD, BORDER_PAD);
	}

	private void generateRightImage(BufferedImage backgroundImage) {
	    rightImage = backgroundImage.getSubimage(backgroundImage.getWidth()
		    - BORDER_PAD, 0, BORDER_PAD, backgroundImage.getHeight());
	}

	private void generateBottomImage(BufferedImage backgroundImage) {
	    bottomImage = backgroundImage.getSubimage(BORDER_PAD,
		    backgroundImage.getHeight() - BORDER_PAD,
		    backgroundImage.getWidth() - 2 * BORDER_PAD, BORDER_PAD);
	}
    }
}

测试类:

package com.michael.swingx.tooltip;

import java.awt.Dimension;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.PopupFactory;
import javax.swing.UIManager;

/**
 *@author michael
 *@email wqjsir@foxmail.com
 *@version 1.0
 */
public class TestToolTip extends JFrame{

    /***/
    private static final long serialVersionUID = 1L;
    
    public TestToolTip(){
	JButton _btn = new JButton("ToolTip测试");
	_btn.setToolTipText(_btn.getText());
	
	JLabel _lb = new JLabel("<html>这是个Label,<br>这里测试ToolTip</html>");
	_lb.setToolTipText(_lb.getText());
	JPanel _plBody = new JPanel();
	_plBody.add(_btn);
	_plBody.add(_lb);
	getContentPane().add(_plBody);
	setLocationRelativeTo(null);
	setSize(new Dimension(100,300));
	setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	setVisible(true);
    }
    
    public static void main(String args[]) {
   	try {
   	    /**
   	     *设置用于获取 Popup 的 PopupFactory。
   	     */
   	    PopupFactory.setSharedInstance(new NonRectanglePopupFactory());
   	    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
   	} catch (Exception ex) {
   	}
   	java.awt.EventQueue.invokeLater(new Runnable() {
   	    public void run() {
   		new TestToolTip().setVisible(true);
   	    }
   	});
       }

}

 

抱歉!评论已关闭.