`
coolszy
  • 浏览: 1411233 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

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

 
阅读更多

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<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” 博客

  • 大小: 51.4 KB
分享到:
评论

相关推荐

    java窗体飞机大战(仿微信转)

    《Java实现的窗体飞机大战游戏详解》 Java作为一种跨平台、面向对象的编程语言,其丰富的类库和强大的功能使其在游戏开发领域也有广泛的应用。本篇文章将深入解析一个基于Java开发的“飞机大战”游戏,这款游戏高度...

    java通用测试用例

    ### Java通用测试用例详解 #### 一、功能测试 功能测试是软件测试的重要组成部分,主要目的是验证软件的各项功能是否符合需求规格说明。对于Java应用而言,功能测试尤为重要,因为它直接关系到用户能否正常使用该...

    java图书管理系统

    《Java图书管理系统详解》 Java图书管理系统是一款基于Java编程语言和SQL数据库技术开发的应用软件,主要用于图书馆日常的图书管理操作。这个系统展示了Java在实际应用中的强大功能,尤其是在窗体界面设计和数据库...

    java简单的工资管理系统odbc

    在这个系统中,Java代码通过ODBC与Access数据库建立连接,执行SQL语句来读写数据。 3. **Access数据库**:Access数据库提供了表格、查询、窗体、报表等组件,便于管理和操作数据。t1表存储了工资管理系统的数据,...

    JAVA贪吃蛇课程设计报告.pdf

    【Java贪吃蛇游戏开发详解】 本篇报告主要围绕使用Java语言实现的贪吃蛇小游戏进行深入探讨。这款Java程序通过响应用户输入的方向键控制蛇的运动,游戏规则简单明了:蛇通过吃食物增长,碰撞到墙壁或自身则游戏结束...

    2021-2022计算机二级等级考试试题及答案No.13135.docx

    - **详解**: `WindowState` 属性可以控制窗体的显示状态,将其设置为 `Maximized` 可使窗体最大化显示,即充满整个屏幕。 - **应用场景**: Windows应用程序开发中,用于实现全屏显示效果。 ### 3. 非线性数据结构 -...

    2021-2022计算机二级等级考试试题及答案No.17668.docx

    11. 窗体级变量访问规则:窗体级变量在定义的窗体及其子程序中均可见,包括用Private定义的变量。其他窗体的子程序不能直接访问这些变量。 12. URL的含义:URL(Uniform Resource Locator)是统一资源定位符,用于...

    2021-2022计算机二级等级考试试题及答案No.9398.docx

    【知识点详解】 ...总结,本文涵盖了窗体设计、Java 异常处理、VBA 函数、数字运算规则、数据库管理、Excel 数据处理等多个计算机二级等级考试的关键知识点,这些都是在准备此类考试时需要重点掌握的内容。

    2021-2022计算机二级等级考试试题及答案No.10733.docx

    - **编译规则**:Java 编译器允许类头定义跨多行,只要语法正确即可。 ### 2. 窗体的功能 **题目内容:** - A. 可以接收用户输入的数据或命令 - B. 可以编辑、显示数据库中的数据 - C. 可以构造方便美观的输入/...

    2021-2022计算机二级等级考试试题及答案No.19050.docx

    - **知识点详解**:窗体控件包括标签、文本框、组合框等,但不包括表(选项A)。 ### 14. 复制表结构 - **知识点概述**:在数据库操作中,有时需要复制表的结构。 - **知识点详解**:`copy structure to boy ...

    2021-2022计算机二级等级考试试题及答案No.2841.docx

    9. 主窗体和子窗体的链接:主窗体和子窗体之间的链接字段可能不在界面中直接显示,但必须包含在主窗体/子窗体的数据源中,以保持数据的关联。 10. 数据库系统特性:数据库技术的目标之一是解决数据共享问题,选项C...

    2021-2022计算机二级等级考试试题及答案No.15697.docx

    10. 参照完整性是数据库设计的重要概念,保证了数据在关系型数据库管理系统中的安全与完整,允许设定表间关系,但用户不能随意更改用于建立关系的字段。所以 (2) 和 (3) 描述正确。 11. 若有以下程序段,c3 中的值...

    2021-2022计算机二级等级考试试题及答案No.15921.docx

    6.Cls 方法:在 Visual Basic 等编程环境中,Cls 方法用于清除窗体或图片框中的运行阶段产生的图形和文字,不包括设计阶段的内容。 7. 数据库联系:在学校与校长的关系中,通常是一所学校对应一位校长,因此这种...

    2021-2022计算机二级等级考试试题及答案No.9859.docx

    【知识点详解】 1. Python 中实现栈和队列: Python 中可以通过列表(list)来实现栈和队列。栈是一种后进先出(LIFO)的数据结构,而队列则是先进先出(FIFO)的结构。在提供的代码中,`Stack` 类实现了栈的基本...

    2021-2022计算机二级等级考试试题及答案No.3801.docx

    10. 变量命名规则:在许多编程语言中,变量名不能以数字开头,所以T12%是不合法的。 11. 数据库表:表是数据库的基础,存储着数据库的所有数据。 12. Java布局管理器:Java.awt包提供了多种布局管理器,如...

    2021-2022计算机二级等级考试试题及答案No.12977.docx

    4. 标识符规则:在 Java 或其他编程语言中,标识符可以由字母、数字或下划线组成,且必须以字母或下划线开头。 5. 主关键字(主键):主键是数据库表中一个或一组字段,用于唯一标识一条记录。主关键字段不允许有...

Global site tag (gtag.js) - Google Analytics