65.9K
CodeProject 正在变化。 阅读更多。
Home

Java 2D API 入门

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (5投票s)

2009 年 3 月 12 日

CPOL

6分钟阅读

viewsIcon

36884

一篇面向Java GUI编程学生的文章。

Java 2D API 入门

本文将重点介绍Java 2D API。在直接深入介绍该API之前,本文将首先介绍Java GUI编程和Applet的一些基本知识,然后详细介绍Java 2D API。在Java中,图形学始于AWT。抽象窗口工具包(AWT)一直并且仍然用于Java语言中创建图形用户界面程序,这些程序可以作为独立应用程序或在浏览器加载时加载的Applet。在AWT推出后,Sun和Netscape联合设计并开发了Swing工具包。Swing被证明是使用“小部件”或组件的应用程序的更强大的GUI机制。下面是一些示例代码。

import javax.swing.*;
public class CheckGrade {
 public static void main(String[]  args) {
   String strScore = JOptionPane.showInputDialog(null, "Enter your grade");
   int score = Integer.parseInt(strScore);
   String comment;
   if ( score >= 60) {
     comment = "You have passed";
   }else{
     comment = "You have failed";
   }
   JOptionPane.showMessageDialog(null, comment);
 }
}

编译它

C:\Sun\SDK\JDK\bin>javac.exe CheckGrade.java

C:\Sun\SDK\JDK\bin>java CheckGrade

1.JPG

2.JPG

几乎所有对JOptionPane类的使用都是对下面所示的静态showXxxDialog方法之一的单行调用。

  • showConfirmDialog用于询问是/否/取消的确认问题。
  • showInputDialog用于提示输入一些内容。
  • showMessageDialog用于告知用户已发生某事。
  • showOptionDialog是上述三个对话框的统一。

代码解释:JVM以String格式读取每种数据类型,因此如果我们输入一个原始整数类型,那么我们就必须使用类似这样的格式:int x = Integer.parseInt(“Some string”),因为输入的值是整数,但会被解释为字符串。因此,我们将其从字符串更改为整数。这里,Integer是内置java.lang包中定义的类名,而parseInt()Integer类中用于将String转换为Integer的方法。if语句的目的是做出决策,并根据布尔值true/false执行程序的部分。

Applet基础

Applet没有作为代码执行起点的main()方法。它们也不会被Java编译器解释。它们由init()方法初始化。与任何Java程序一样,文件名是您声明的类的名称,但该声明的类扩展了定义在java.awt包中的Applet类。下面是一些基本的(可能已过时)Applet代码。请注意,系统会调用paint()方法。还要注意,我们正在绘制线条,并且为了绘制这些线条,我们需要迭代作为Applet维度一部分的变量i

import java.applet.*;
import java.awt.*;
public class CreateLines extends Applet {
 int width, height;
 public void init() {
      width = getSize().width;
      height = getSize().height;
      setBackground( Color.black);
 }
 public void paint( Graphics g ) {
      g.setColor( Color.red );
      for ( int i = 0; i < 10; ++i ) {
         g.drawLine( width, height, i * width / 10, 0 );
      }
 }
}

必须使用javac.exe编译器编译此代码才能创建类文件。

C:\Sun\SDK\JDK\bin>javac.exe CreateLines.java 

3.JPG

C:\Sun\SDK\JDK\bin> type con > somefile.html

输出

<html> 
<body>
<applet code="CreateLines.class" width = 400 height = 400></applet>
</body>
<html>

现在,输入somefile.html

要查看Applet的强大功能,本文作者建议您参考http://www.echoecho.com。该网页有一个令人惊叹的Applet及其对应的类文件可供下载。只需确保将图像文件、HTML文件和类文件保存在同一个工作目录中。

Java 2D API概述

在Java 1.2及更高版本中,paintComponent方法会提供一个Graphics2D对象(Graphics的子类),该对象包含更丰富的一系列绘图操作。它包括笔的宽度、虚线、图像和渐变色填充模式、任意本地字体的使用、浮点坐标系统以及许多坐标变换操作。Java 2D API为程序员提供了先进的二维图形功能。该API包含了在java.awtjava.awt.imagejava.awt.colorjava.awt.fontjava.awt.geomjava.awt.printjava.awt.image.renderable包中处理线条、文本和图像的功能。使用Java 2D API进行绘图需要一个Graphics2D引用(java.awt包)。Graphics2DGraphics类的抽象子类,因此它拥有前面提到的所有图形功能。事实上,用于在每个paintComponent方法中绘图的实际对象是Graphics2D子类的实例,该实例被传递给paintComponent方法,并通过超类Graphics进行访问。要访问Graphics2D功能,我们必须将传递给paintComponentGraphics引用(g)转换为Graphics2D引用,使用如下语句:

//Cast the Graphics object to a Graphics2D object
public void paintComponent(Graphics g) {
  super.paintComponent(g);  
  Graphics2D g2d = (Graphics2D)g;
  g2d.doSomework(...);
  ...
}

创建Shape对象

  • Rectangle2D.Double rect = ...;
  • Ellipse2D.Double ellipse = ...;
  • Polygon poly = ...;
  • GeneralPath path = ...;
  • ...

绘制Shape的轮廓或实心版本

  • g2d.draw(someShape);
  • g2d.fill(someShape);

使用以下方法之一修改绘图参数。

  • g2d.setPaint(fillColorOrPattern);
  • g2d.setStroke(penThicknessOrPattern);
  • g2d.setComposite(someAlphaComposite);
  • g2d.setFont(someFont);
  • g2d.translate(...);
  • g2d.rotate(...);
  • g2d.scale(...);
  • g2d.shear(...);
  • g2d.setTransform(someAffineTransform);Rectangle2D.Double rect = ...;
  • Ellipse2D.Double ellipse = ...;
  • Polygon poly = ...;
  • GeneralPath path = ...;

绘制Shape的轮廓或实心版本

  • g2d.draw(someShape);
  • g2d.fill(someShape);

修改绘图参数

  • g2d.setPaint(fillColorOrPattern);
  • g2d.setStroke(penThicknessOrPattern);
  • g2d.setComposite(someAlphaComposite);
  • g2d.setFont(someFont);
  • g2d.translate(...);
  • g2d.rotate(...);
  • g2d.scale(...);
  • g2d.shear(...);
  • g2d.setTransform(someAffineTransform);

此示例将绘制一个在窗口内的椭圆。暗色椭圆包含在一个窗口或容器内,最顶层的称为JFrame。下面是主文件,请注意,在main()方法中包含了一个名为OSTools的未定义类。因此,Example.java文件依赖于类文件OSTools.java。查看OSTools.java可知,OSTools依赖于ExitListener.java文件。OSTools.javaExitListener.java仅编译成字节码以使其类文件充当应用程序的“蓝图”。这是主文件,Example.java

import javax.swing.*;        
import java.awt.*;           
import java.awt.geom.*;      
public class Example extends JPanel {
  private Ellipse2D.Double circle =
    new Ellipse2D.Double(10, 10, 350, 350);
  private Rectangle2D.Double square =
    new Rectangle2D.Double(10, 10, 350, 350);
    public void paintComponent(Graphics g) {    
    clear(g);
    Graphics2D g2d = (Graphics2D)g;            
    g2d.fill(circle);
    g2d.draw(square);
  }
    protected void clear(Graphics g) {
    super.paintComponent(g);
  }
    protected Ellipse2D.Double getCircle() {
    return(circle);
  }
   public static void main(String[] args) {
    OSTools.openInJFrame(new Example(), 380, 400);
  }
}

我们看到了OSTools类,并知道它没有在任何导入的包中定义。这是一个类文件,必须将其源代码编译成类文件。回想一下,Swing中最顶层的容器(或窗口)是JFrame。然而,如果没有在JFrame上添加组件,它将只是一个空白的用户界面。JPanel被称为内容窗格,我们将组件放在窗口上。

import java.awt.*;
public class OSTools {
 public static JFrame openInJFrame(Container content,
                                    int width,
                                    int height,
                                    String title,
                                    Color bgColor) {
    JFrame frame = new JFrame(title);
    frame.setBackground(bgColor);
    content.setBackground(bgColor);
    frame.setSize(width, height);
    frame.setContentPane(content);
    frame.addWindowListener(new ExitListener());
    frame.setVisible(true);
    return(frame);
  }
  public static JFrame openInJFrame(Container content,
                                    int width,
                                    int height,
                                    String title) {
    return(openInJFrame(content, width, height, title, Color.white));
  }

 public static JFrame openInJFrame(Container content,
                                    int width,
                                    int height) {
    return(openInJFrame(content, width, height,
                        content.getClass().getName(),
                        Color.white));
  }
}

请注意,创建了一个新的ExitListener对象,这意味着我们必须定义该类。

import java.awt.*;
import java.awt.event.*;
public class ExitListener extends WindowAdapter {
  public void windowClosing(WindowEvent event) {
    System.exit(0);
  }
}

6.JPG

编译类文件和主文件会产生此图像。

5.JPG

透明绘图

Java 2D允许您为绘图操作分配透明度(Alpha)值,以便在绘制形状或图像时,底层图形会部分显示出来。您可以通过创建一个AlphaComposite对象,然后将AlphaComposite对象传递给Graphics2D对象的setComposite方法来设置透明度。通过调用AlphaComposite.getInstance来创建AlphaCompositeAlphaComposite API提供了八种内置混合规则,但通常用于设置透明度绘图的是AlphaComposite.SRC_OVER,这是一种源叠底混合规则,它将源(形状)叠放在目标(背景)之上。Alpha值可以从0.0f(完全透明)到1.0f(完全不透明)不等。部分重叠是一个红色正方形,在最左侧以初始alpha值为0.0f绘制。红色正方形在面板上以新的位置重复绘制,alpha值逐渐增加,步长为0.1f,直到最右侧达到完全不透明,alpha值为1.0f。

以下是一些演示此示例的代码。同样,此主文件依赖于OSTools.java类文件。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Transparent extends JPanel {
    private static int gap=10, width=60, offset=20,
    deltaX=gap+width+offset;
    private Rectangle
    blueSquare = new Rectangle(gap+offset, gap+offset, width,
    width),
    redSquare = new Rectangle(gap, gap, width, width);
    
    private AlphaComposite makeComposite(float alpha) {
        int type = AlphaComposite.SRC_OVER;
        return(AlphaComposite.getInstance(type, alpha));
    }

    private void drawSquares(Graphics2D g2d, float alpha) {
        Composite originalComposite = g2d.getComposite();
        g2d.setPaint(Color.blue);
        g2d.fill(blueSquare);
        g2d.setComposite(makeComposite(alpha));
        g2d.setPaint(Color.red);
        g2d.fill(redSquare);
        g2d.setComposite(originalComposite);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        for(int i=0; i<11; i++) {
            drawSquares(g2d, i*0.1F);
            g2d.translate(deltaX, 0);
        }
    }

    public static void main(String[] args) {
        String title = "Transparency example: alpha of the top " +
        "(red) square ranges from 0.0 at the left " +
        "to 1.0 at the right. Bottom (blue) square " +
        "is opaque.";
        OSTools.openInJFrame(new Transparent(),
        11*deltaX + 2*gap,
        deltaX + 3*gap,
        title, Color.lightGray);
     }
}

推荐阅读

  • David J. Eck 著《Java编程入门》
  • Bruce Eckel 著《Java编程思想》
© . All rights reserved.