Java根据图片建立不规则窗体详解

精贴 置顶
1587 0

  JAVA程序的外表总是一板一眼的,看多了难免审美疲劳,能不能使我们的JAVA程序外观变得更美观更独特呢?答案是肯定的,我们可以让JAVA程序根据图片来生成自定义的不规则窗体。比如下图的这种外观:

  

  图中的这个人物(蕾米莉亚)便是定义好的不规则窗体,怎么样?很漂亮吧!那么让我们开始学习吧。

  首先要说明一下,本方法是基于com.sun.awt.AWTUtilities这个类实现的,而这个类只能在jdk-6u10版本以后的版本才能体现出来的,在本文中讨论的所有 API 在新 com.sun.awt.AWTUtilities 类中出现,该类不是官方支持的部分 API。它在 Java SE 7 中的位置最有可能发生改变,签名方法可能在现在和最终的 Consumer JRE 发行之间发生轻微变化。

  所以当你的JDK版本不匹配的时候需要你将JDK插件更新。

  地址: http://java.sun.com/javase/downloads/index.jsp

  =================================================================

  好了,准备工作妥当,下面就让我们通过代码来学习根据图片制作不规则窗体的方法。


   IrregularFormSample.java
  import java.awt.Graphics;
  import java.awt.Image;
  import java.awt.MediaTracker;
  import java.awt.Point;
  import java.awt.Rectangle;
  import java.awt.Shape;
  import java.awt.Toolkit;
  import java.awt.event.MouseAdapter;
  import java.awt.event.MouseEvent;
  import java.awt.event.MouseMotionAdapter;
  import java.awt.geom.Area;
  import java.awt.image.PixelGrabber;
  import java.io.IOException;
  import java.util.ArrayList;
  import javax.swing.JFrame;
  import com.sun.awt.AWTUtilities;
  /**
  * 不规则窗体示例
  * @author Hexen
  */
  public class IrregularFormSample extends JFrame {
  private static final long serialVersionUID = 1L;
  private Point origin; //用于移动窗体
  private Image img; //用来设定窗体不规则样式的图片
  public IrregularFormSample() {
  super();
  /* 首先初始化一张图片,我们可以选择一张有透明部分的不规则图片
  * (当然我们要选择支持Alpha(透明)层的图片格式,如PNG),这张
  * 图片将被用来生成与其形状相同的不规则窗体
  */
  MediaTracker mt=new MediaTracker(this);
  img=Toolkit.getDefaultToolkit().createImage("remi.png");
  mt.addImage(img, 0);
  try {
  mt.waitForAll();
  } catch (InterruptedException e) {
  e.printStackTrace();
  }
  try {
  initialize();//窗体初始化
  } catch (IOException e) {
  e.printStackTrace();
  }
  }
  /**
  * 窗体初始化
  * @throws IOException
  */
  private void initialize() throws IOException {
  //设定窗体大小和图片一样大
  this.setSize(img.getWidth(null), img.getHeight(null));
  //设定禁用窗体装饰,这样就取消了默认的窗体结构
  this.setUndecorated(true);
  //初始化用于移动窗体的原点
  this.origin=new Point();
  //调用AWTUtilities的setWindowShape方法设定本窗体为制定的Shape形状
  AWTUtilities.setWindowShape(this,getImageShape(img));
  //设定窗体可见度
  AWTUtilities.setWindowOpacity(this, 0.8f);
  this.setLocationRelativeTo(null);
  //由于取消了默认的窗体结构,所以我们要手动设置一下移动窗体的方法
  addMouseListener(
  new MouseAdapter(){
  public void mousePressed(MouseEvent e){
  origin.x = e.getX();
  origin.y = e.getY();
  }
  //窗体上单击鼠标右键关闭程序
  public void mouseClicked(MouseEvent e) {
  if(e.getButton()==MouseEvent.BUTTON3)
  System.exit(0);
  }
  public void mouseReleased(MouseEvent e) {
  super.mouseReleased(e);
  }
  @Override
  public void mouseEntered(MouseEvent e) {
  repaint();
  }
  }
  );
  addMouseMotionListener(
  new MouseMotionAdapter(){
  public void mouseDragged(MouseEvent e){
  Point p = getLocation();
  setLocation(p.x + e.getX() - origin.x, p.y + e.getY() - origin.y );
  }
  }
  );
  }
  /**
  * 将Image图像转换为Shape图形
  * @param img
  * @param isFiltrate
  * @return Image图像的Shape图形表示
  * @author Hexen
  */
public Shape getImageShape(Image img) {
  ArrayList x=new ArrayList();
  ArrayList y=new ArrayList();
  int width=img.getWidth(null);//图像宽度
  int height=img.getHeight(null);//图像高度
  //筛选像素
  //首先获取图像所有的像素信息
  PixelGrabber pgr = new PixelGrabber(img, 0, 0, -1, -1, true);
  try {
  pgr.grabPixels();
  } catch (InterruptedException ex) {
  ex.getStackTrace();
  }
  int pixels[] = (int[]) pgr.getPixels();
  //循环像素
  for (int i = 0; i < pixels.length; i++) {
  //筛选,将不透明的像素的坐标加入到坐标ArrayList x和y中
  int alpha = getAlpha(pixels[i]);
  if (alpha == 0){
  continue;
  }else{
  x.add(i%width>0 ? i%width-1:0);
  y.add(i%width==0 ? (i==0 ? 0:i/width-1):i/width);
  }
  }
  //建立图像矩阵并初始化(0为透明,1为不透明)
  int[][] matrix=new int[height][width];
  for(int i=0;i 
  for(int j=0;j 
  matrix[i][j]=0;
  }
  }
  //导入坐标ArrayList中的不透明坐标信息
  for(int c=0;c 
  matrix[y.get(c)][x.get(c)]=1;
  }
  /* 由于Area类所表示区域可以进行合并,我们逐一水平"扫描"图像矩阵的每一行,
  * 将不透明的像素生成为Rectangle,再将每一行的Rectangle通过Area类的rec
  * 对象进行合并,最后形成一个完整的Shape图形
  */
  Area rec=new Area();
  int temp=0;
  for(int i=0;i 
  for(int j=0;j 
  if(matrix[i][j]==1){
  if(temp==0)
  temp=j;
  else if(j==width){
  if(temp==0){
  Rectangle rectemp=new Rectangle(j,i,1,1);
  rec.add(new Area(rectemp));
  }else{
  Rectangle rectemp=new Rectangle(temp,i,j-temp,1);
  rec.add(new Area(rectemp));
  temp=0;
  }
  }
  }else{
  if(temp!=0){
  Rectangle rectemp=new Rectangle(temp,i,j-temp,1);
  rec.add(new Area(rectemp));
  temp=0;
  }
  }
  }
  temp=0;
  }
  return rec;
  }
  /**
  * 获取像素的Alpha值
  * @param pixel
  * @return 像素的Alpha值
  */
  private int getAlpha(int pixel) {
  return (pixel >> 24) & 0xff;
  }
  /* 我们可以选择在窗体上绘制图片,是窗体完全呈现出图片的样式,
  * 当然我们也可以根据需要不绘制它,而采取其他操作
  */
  @Override
  public void paint(Graphics g) {
  super.paint(g);
  g.drawImage(img, 0, 0, null);
  }
  public static void main(String[] args) {
  IrregularFormSample sample = new IrregularFormSample();
  sample.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  sample.setVisible(true);
  }
  }

  使用这种方法,我们可以自由的定义窗体外观,使我们的JAVA程序更加美观。现在就去尝试一下吧!

  • 没有任何评论
今日天气 ···

···

···

···

热门排行
用ASP实现网页BBS 2010-11-01
CSS cursor鼠标样式一览表 2012-06-25
.NET后台写JS代码 2011-11-03
网站地址多出jdfwkey的问题解析及... 2010-08-25
数据库xxx的日志已满,请备份该数... 2013-07-19
百度、google、Yahoo网站地图制作... 2011-01-30
<a>标签的伪类书写顺序问题... 2010-09-04
什么是长尾关键词? 2010-09-24
CEO名言 2010-08-31
Mysql 主从数据库同步 2010-09-12
博主推荐
本个人博客微信公众平台上线啦~~... 2013-10-13
饼哥网络互联上线啦~~要买域名空... 2013-09-20
网站title标题如何正确修改不会被... 2013-08-26
饼哥通讯录系统上线啦,欢迎大家... 2013-08-24
ASP .NET MYSQL 的简单分页 并不... 2013-08-19
网站有弹窗广告这样的站点,百度... 2013-08-17
做淘宝SEO优化需要注意的8大问题 2013-08-17
淘宝网怎么做SEO优化 2013-08-17
站长们要学习的“苍井空精神” 2013-08-17
苹果公司今日发布了iOS 7第五个开... 2013-08-07
随便看看
xp进程全解 2010-08-31
sql常用函数大全 2010-12-07
6个你必须用到AJAX的地方与6个不... 2010-09-07
ASP中实现分页显示的七种武器 2010-11-01
存储位置优化——把视图状态信息... 2013-11-15
Asp.net 2.0 Treeview 无限级无刷... 2010-09-11
.net用工厂模式开发多数据库连接... 2010-09-10
JS复制文本到剪贴板代码 2010-09-13
目前中文互联网上有少量spider冒... 2013-06-23
iis .net framework 1.0 2.0 4.0... 2013-11-16
RSS新闻
传媒新闻
CSDN
八卦新闻
女性新闻
台湾新闻
互联网
军事-新浪博客
IT-新浪博客
汽车新闻
游戏新闻
国际新闻
国内新闻
体育新闻
我的微博
北京 上海 杭州 深圳 广州 成都