Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 998|回复: 0

根据图片建立不规则窗体详解 java实例

[复制链接]

该用户从未签到

发表于 2011-9-21 20:51:44 | 显示全部楼层 |阅读模式
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
  1. import java.awt.Graphics;
  2. import java.awt.Image;
  3. import java.awt.MediaTracker;
  4. import java.awt.Point;
  5. import java.awt.Rectangle;
  6. import java.awt.Shape;
  7. import java.awt.Toolkit;
  8. import java.awt.event.MouseAdapter;
  9. import java.awt.event.MouseEvent;
  10. import java.awt.event.MouseMotionAdapter;
  11. import java.awt.geom.Area;
  12. import java.awt.image.PixelGrabber;
  13. import java.io.IOException;
  14. import java.util.ArrayList;
  15. import javax.swing.JFrame;
  16. import com.sun.awt.AWTUtilities;
  17. /**
  18. * 不规则窗体示例
  19. * @author Hexen
  20. */
  21. public class IrregularFormSample extends JFrame {
  22.   private static final long serialVersionUID = 1L;
  23.   private Point origin; //用于移动窗体
  24.   private Image img; //用来设定窗体不规则样式的图片
  25.   public IrregularFormSample() {
  26.     super();
  27.    
  28.     /* 首先初始化一张图片,我们可以选择一张有透明部分的不规则图片
  29.      * (当然我们要选择支持Alpha(透明)层的图片格式,如PNG),这张
  30.      * 图片将被用来生成与其形状相同的不规则窗体
  31.     */
  32.     MediaTracker mt=new MediaTracker(this);
  33.     img=Toolkit.getDefaultToolkit().createImage("remi.png");
  34.     mt.addImage(img, 0);
  35.     try {
  36.       mt.waitForAll();
  37.     } catch (InterruptedException e) {
  38.       e.printStackTrace();
  39.     }
  40.    
  41.     try {
  42.       initialize();//窗体初始化
  43.     } catch (IOException e) {
  44.       e.printStackTrace();
  45.     }   
  46.   }
  47.   
  48.   /**
  49.     * 窗体初始化
  50.     * @throws IOException
  51.     */
  52.   private void initialize() throws IOException {
  53.     //设定窗体大小和图片一样大
  54.     this.setSize(img.getWidth(null), img.getHeight(null));
  55.     //设定禁用窗体装饰,这样就取消了默认的窗体结构
  56.     this.setUndecorated(true);
  57.     //初始化用于移动窗体的原点
  58.     this.origin=new Point();
  59.    
  60.     //调用AWTUtilities的setWindowShape方法设定本窗体为制定的Shape形状
  61.     AWTUtilities.setWindowShape(this,getImageShape(img));        
  62.     //设定窗体可见度
  63.     AWTUtilities.setWindowOpacity(this, 0.8f);
  64.    
  65.     this.setLocationRelativeTo(null);
  66.    
  67.     //由于取消了默认的窗体结构,所以我们要手动设置一下移动窗体的方法
  68.     addMouseListener(
  69.         new MouseAdapter(){
  70.           public void mousePressed(MouseEvent e){
  71.             origin.x = e.getX();
  72.             origin.y = e.getY();
  73.           }
  74.           //窗体上单击鼠标右键关闭程序
  75.           public void mouseClicked(MouseEvent e) {
  76.             if(e.getButton()==MouseEvent.BUTTON3)
  77.               System.exit(0);
  78.           }
  79.           public void mouseReleased(MouseEvent e) {
  80.             super.mouseReleased(e);
  81.           }
  82.           @Override
  83.           public void mouseEntered(MouseEvent e) {
  84.             repaint();              
  85.           }            
  86.         }
  87.     );
  88.     addMouseMotionListener(
  89.         new MouseMotionAdapter(){
  90.           public void mouseDragged(MouseEvent e){
  91.             Point p =    getLocation();
  92.             setLocation(p.x + e.getX() - origin.x, p.y + e.getY() - origin.y );
  93.           }         
  94.         }
  95.     );   
  96.   }
  97.   
  98.   /**
  99.     * 将Image图像转换为Shape图形
  100.     * @param img
  101.     * @param isFiltrate
  102.     * @return Image图像的Shape图形表示
  103.     * @author Hexen
  104.     */
  105.   public Shape getImageShape(Image img) {
  106.     ArrayList<Integer> x=new ArrayList<Integer>();
  107.     ArrayList<Integer> y=new ArrayList<Integer>();   
  108.     int width=img.getWidth(null);//图像宽度
  109.     int height=img.getHeight(null);//图像高度
  110.     //筛选像素
  111.     //首先获取图像所有的像素信息
  112.     PixelGrabber pgr = new PixelGrabber(img, 0, 0, -1, -1, true);
  113.     try {
  114.       pgr.grabPixels();
  115.     } catch (InterruptedException ex) {
  116.       ex.getStackTrace();
  117.     }
  118.     int pixels[] = (int[]) pgr.getPixels();
  119.    
  120.     //循环像素
  121.     for (int i = 0; i < pixels.length; i++) {
  122.       //筛选,将不透明的像素的坐标加入到坐标ArrayList x和y中      
  123.       int alpha = getAlpha(pixels[i]);
  124.       if (alpha == 0){
  125.         continue;        
  126.       }else{
  127.         x.add(i%width>0 ? i%width-1:0);
  128.         y.add(i%width==0 ? (i==0 ? 0:i/width-1):i/width);
  129.       }      
  130.     }
  131.    
  132.     //建立图像矩阵并初始化(0为透明,1为不透明)
  133.     int[][] matrix=new int[height][width];   
  134.     for(int i=0;i<height;i++){
  135.       for(int j=0;j<width;j++){
  136.         matrix[i][j]=0;
  137.       }
  138.     }
  139.    
  140.     //导入坐标ArrayList中的不透明坐标信息
  141.     for(int c=0;c<x.size();c++){
  142.       matrix[y.get(c)][x.get(c)]=1;
  143.     }
  144.    
  145.     /* 由于Area类所表示区域可以进行合并,我们逐一水平"扫描"图像矩阵的每一行,
  146.      * 将不透明的像素生成为Rectangle,再将每一行的Rectangle通过Area类的rec
  147.      * 对象进行合并,最后形成一个完整的Shape图形
  148.      */
  149.     Area rec=new Area();
  150.     int temp=0;
  151.    
  152.     for(int i=0;i<height;i++){
  153.       for(int j=0;j<width;j++){
  154.         if(matrix[i][j]==1){
  155.           if(temp==0)
  156.             temp=j;  
  157.           else if(j==width){
  158.             if(temp==0){
  159.               Rectangle rectemp=new Rectangle(j,i,1,1);
  160.               rec.add(new Area(rectemp));
  161.             }else{
  162.               Rectangle rectemp=new Rectangle(temp,i,j-temp,1);
  163.               rec.add(new Area(rectemp));
  164.               temp=0;
  165.             }
  166.           }
  167.         }else{
  168.           if(temp!=0){
  169.             Rectangle rectemp=new Rectangle(temp,i,j-temp,1);
  170.             rec.add(new Area(rectemp));
  171.             temp=0;
  172.           }
  173.         }
  174.       }
  175.       temp=0;
  176.     }
  177.     return rec;
  178.   }
  179.   
  180.   /**
  181.     * 获取像素的Alpha值
  182.     * @param pixel
  183.     * @return 像素的Alpha值
  184.     */
  185.   private int getAlpha(int pixel) {
  186.     return (pixel >> 24) & 0xff;
  187.   }
  188.   
  189.   
  190.   /* 我们可以选择在窗体上绘制图片,是窗体完全呈现出图片的样式,
  191.     * 当然我们也可以根据需要不绘制它,而采取其他操作
  192.     */
  193.   @Override
  194.   public void paint(Graphics g) {
  195.     super.paint(g);
  196.     g.drawImage(img, 0, 0, null);
  197.   }
  198.   
  199.   public static void main(String[] args) {
  200.         IrregularFormSample sample = new IrregularFormSample();
  201.         sample.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  202.         sample.setVisible(true);
  203.   }  
  204. }
复制代码

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

使用道具 举报

该用户从未签到

发表于 2011-9-26 12:35:24 | 显示全部楼层
[s:7]
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-10 19:30 , Processed in 0.327818 second(s), 37 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表