java 异形窗体 学习01

【转】  Java根据图片建立不规则窗体详解
2010-01-24 15:46:29
原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://hexen.blog.51cto.com/1110171/269860
JAVA程序的外表总是一板一眼的,看多了难免审美疲劳,能不能使我们的JAVA程序外观变得更美观更独特呢?答案是肯定的,我们可以让JAVA程序根据图片来生成自定义的不规则窗体。比如下图的这种外观:
IrregularForm

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

    首先要说明一下,本方法是基于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<Integer> x= new ArrayList<Integer>();
    ArrayList<Integer> y= new ArrayList<Integer>();    
     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<height;i++){
       for( int j=0;j<width;j++){
        matrix[i][j]=0;
      }
    }
    
     //导入坐标ArrayList中的不透明坐标信息
     for( int c=0;c<x.size();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<height;i++){
       for( int j=0;j<width;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程序更加美观。现在就去尝试一下吧!

本文出自 “和谐的HeXen” 博客,请务必保留此出处http://hexen.blog.51cto.com/1110171/269860

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值