Java标准教程:Java 2D绘图--第3章 基本几何图形

时间:2023-02-06 21:55:57

在之前的课程中,您已经学习了绘图的基本概念,包括坐标系和graphic对象创建的基本信息。现在,您将了解2D 绘图类的更详细的信息。本科展示如何使用Graphics2D类绘制基本的几何图形和任意的形状,以及如何使用花哨的轮廓和填充风格展示图形。这些主题分为以下几个章节。

l         绘制基本几何图形:本节展示如何创建标准的集合图形,例如点,线,曲线,圆弧,矩形和椭圆。

l         绘制任意图形:本节展示如何直接使用基本几何图形组合绘制任意形状,使用GeneralPath类进行绘制。

l         填充和笔画:本节解释如何设置笔画和打印属性,控制应用到Shape对象和文本的轮廓和填充风格。

 

1.1 绘制基本几何图形

Java 2D API提供很多类,定义了基本的几何对象,例如点,线,弧线和矩形。这些几何类是java.awt.geom包的一部分。

PathIterator接口定义了从路径中获取元素的方法。Shape接口提供了一组描述和解析几何路径的对象。这个接口由GeneralPath类和其他几何类实现。

本节的所有例子中创建的几何图形都使用java.awt.geom,然后使用Graphics2D类进行渲染。要得到Graphics2D对象,可以cast paint()方法的Graphics参数:

 

public void paint (Graphics g) {

    Graphics2D g2 = (Graphics2D) g;

    ...

}

 

1.1.1

Point类创建了位于坐标系中(x, y)位置的点。子类Point2D.FloatPoint2D.Double提供了使用floatdouble精度存储点。

 

//Create Point2D.Double

Point2D.Double point = new Point2D.Double(x, y);

 

要创建位于坐标系(0, 0)的点,使用默认的构造函数Point2D.Double()

您可以使用setLocation方法设按照下面的方法设置点的位置:

l         setLocation(double x, double y):使用double坐标值设置点的位置。

l         setLocation(Point2D p):使用坐标系中的其他点设置位置。

同时,Point2D类中有方法可以计算当前点和给定坐标点之间的距离,或两点之间的距离。

 

1.1.2 线

Line2D表示了(x, y)坐标系空间中的先片段。Line2D.FloatLine2D.Double子类使用floatdouble精度指定了线。例如:

 

 

// draw Line2D.Double

g2.draw(new Line2D.Double(x1, y1, x2, y2));

 

这个类包含一些setLine()方法定义线段的端点。同时,线段的断电可以使用构造函数指定,例如:

 

Line2D.Float(float X1, float Y1, float X2, float Y2)

Line2D.Float(Point2D p1, Point2D p2)

 

Graphics2D类中使用Stroke对象指定线段路径的笔画。

 

1.1.3 曲线

您可以使用java.awt.geom包创建二次和三次曲线片段。

 

1.1.3.1 二次曲线片段

QuadCurve2D类实现了Shape接口。这个类表示了(x, y)坐标空间中的二次参数曲线片段。QuadCurve2D.FloatQuadCurve2D.Double子类使用floatdouble精度指定了二次曲线。

一些setCurve方法用来指定曲线的两个端点和控制点,它们的坐标可以直接指定,通过其他点的坐标或使用给定数组。

setCurve(QuadCurve2D c)是一个非常有用的方法,使用同样的端点和控制点指定曲线,例如:

 

// create new QuadCurve2D.Float

QuadCurve2D q = new QuadCurve2D.Float();

// draw QuadCurve2D.Float with set coordinates

q.setCurve(x1, y1, ctrlx, ctrly, x2, y2);

g2.draw(q);

 

 

 

1.1.3.2 三次曲线片段

CubicCurve2D类也实现了Shape接口。这个类表示了(x, y)坐标空间中的三次参数曲线片段。CubicCurve2D.FloatCubicCurve2D.Double子类使用floatdouble精度指定了三次曲线。

CubicCurve2D类和QuadraticCurve2D类有类似的setting方法。例如:

 

// create new CubicCurve2D.Double

CubicCurve2D c = new CubicCurve2D.Double();

// draw CubicCurve2D.Double with set coordinates

c.setCurve(x1, y1, ctrlx1,

          ctrly1, ctrlx2, ctrly2, x2, y2);

g2.draw(c);

 

 

 

1.1.4 矩形

下面例子中的类扩展了RectangularShape类,它实现了Shape接口,同时自己添加了一些方法。

这些方法让你可以获取图形的位置和大小信息,得到矩形的重点,设置图形的界限。

Rectangle2D类表示由位置(x, y)和维度(w x h)定义的矩形。Rectangle2D.FloatRectangle2D.Double子类使用floatdouble精度指定了一个矩形。例如:

 

// draw Rectangle2D.Double

g2.draw(new Rectangle2D.Double(x, y,

                               rectwidth,

                               rectheight));

 

 

 

RoundRectangle2D类定义了位于(x, y),维度是(w x h),同时定义了圆弧宽度和高度的圆角矩形,RoundRectangle2D.FloatRoundRectangle2D.Double子类指定了floatdouble精度的圆角矩形。

圆角矩形指定了以下参数:

l         位置

l         宽度

l         高度

l         角弧的宽度

l         角弧的高度

要设置RoundRectangle2D对象的位置,大小和弧度,使用方法setRoundRect(double a, double y, double w, double h, double arcWidth, double arcHeight)。例如:

 

// draw RoundRectangle2D.Double

g2.draw(new RoundRectangle2D.Double(x, y,

                                   rectwidth,

                                   rectheight,

                                   10, 10));

 

 

 

 

1.1.5 椭圆

Ellipse2D类表示由圆角矩形定义的椭圆。Ellipse2D.FloatEllipse2D.Double子类使用floatdouble精度指定了椭圆。

椭圆由位置,宽度和高度完全定义。例如:

 

// draw Ellipse2D.Double

g2.draw(new Ellipse2D.Double(x, y,

                             rectwidth,

                             rectheight));

 

 

 

 

 

1.1.6 圆弧

要绘制一片椭圆,您可以使用Arc2D类。这个类表示了由圆角矩形定义的举行,一个开始角度,一个圆弧扩展和一个关闭类型。Arc2D.FloatArc2D.Double子类表示了floatdouble精度的椭圆。

Arc2D类定义了下列三种圆弧类型,由以下常量定义:OPEN, PIECHORD

 

 

 

一些方法设置了圆弧的大小和参数:

l         使用坐标直接设置

l         使用Point2DDimension2D

l         拷贝已经存在的Arc2D

 

同时,您可以使用setArcByCenter方法从中点,通过制定坐标和半径的方式绘制圆弧。

 

// draw Arc2D.Double

g2.draw(new Arc2D.Double(x, y,

                         rectwidth,

                         rectheight,

                         90, 135,

                         Arc2D.OPEN));

 

 

 

ShapesDemo2D.java源代码中包含所有以上描述的基本几何图形的代码。更详细的信息请参考java.awt.geom包的API

 

1.2 绘制任意图形

您已经知道如何绘制java.awt.geom包中的大多数图形。要创建一个更加复杂的集合图形,例如多边形,多边形线段,或者星形。您还可以使用这个包中的另一个类,GeneralPath

这个类实现了Shape接口,同时表示由线段,二次和三次曲线组成的几何路径。这个类中的三个构造函数可以使用默认的弯曲规则(WIND_NON_ZERO),弯曲规则有(WIND_NON_ZERO WIND_EVEN_ODD),或者特殊的初始化坐标功能。弯曲规则表明如何决定内部路径。

 

public void Paint (Graphics g) {

    Graphics2D g2 = (Graphics2D) g;

    ...

}

 

要创建一个空的GeneralPath实例,可以调用new GeneralPath(),然后使用下列方法向图形中添加片段:

l         moveTo(float x, float y):将路径的当前点移动到给定点。

l         lineTo(float x, float y):向当前路径添加线段片段

l         quadTo(float ctrlx, float ctrly, float x2, floaty2):向当前路径中添加二次方曲线片段

l         curveTo(float ctrlx1, float ctrly1, float ctrlx2, float ctrly2, float x3, floaty3):向当前路径添加三次方曲线片段。

l         closePath():关闭当前路径。

下面的例子展示了如何使用GeneralPath绘制多边形线条:

 

// draw GeneralPath (polyline)

int x2Points[] = {0, 100, 0, 100};

int y2Points[] = {0, 50, 50, 0};

GeneralPath polyline =

    new GeneralPath(GeneralPath.WIND_EVEN_ODD, x2Points.length);

 

polyline.moveTo (x2Points[0], y2Points[0]);

 

for (int index = 1; index < x2Points.length; index++) {

     polyline.lineTo(x2Points[index], y2Points[index]);

};

 

g2.draw(polyline);

 

 

这个例子展示了如何使用GeneralPath绘制多边形:

 

// draw GeneralPath (polygon)

int x1Points[] = {0, 100, 0, 100};

int y1Points[] = {0, 50, 50, 0};

GeneralPath polygon =

    new GeneralPath(GeneralPath.WIND_EVEN_ODD, x1Points.length);

polygon.moveTo(x1Points[0], y1Points[0]);

 

for (int index = 1; index < x1Points.length; index++) {

        polygon.lineTo(x1Points[index], y1Points[index]);

};

 

polygon.closePath();

g2.draw(polygon);

 

注意,上面代码的唯一区别在于closePath()方法。这个方法让绘制多边形线条的最后一个点绘制到开始点。

要将特定的路径加到GeneralPath对象之后,可以使用append()方法之一。ShapesDemo2D.java中有任意形状的实现。

 

1.3 基本几何图形的笔画和填充

您已经知道如何创建不同的基本集合图形,以及更复杂的图形。本课介绍如何为您的图形添加颜色和特别的轮廓,以及填充和笔画:

l         填充:是使用实心颜色或渐变色或文本填充图形内部的过程。

l         笔画:是绘制图形轮廓时使用的笔画宽度,线形和颜色属性。

要在Graphics2D上下文渲染前应用特别的线形和填充属性到基本图形中,修改图形的笔画和绘制属性。例如,使用合适的Stroke对象绘制虚线。要在Graphics2D上下文线段被渲染之前调用setStroke方法添加笔画。类似的,要在Shape对象被渲染之前,将渐变色的填充属性Graphics2D上下文中。

以下代码使用填充和笔画上下文丰富了几何图形。

 

// draw RoundRectangle2D.Double

 

final static float dash1[] = {10.0f};

    final static BasicStroke dashed = new BasicStroke(1.0f,

                                          BasicStroke.CAP_BUTT,

                                          BasicStroke.JOIN_MITER,

                                          10.0f, dash1, 0.0f);

g2.setStroke(dashed);

g2.draw(new RoundRectangle2D.Double(x, y,

                                   rectWidth,

                                   rectHeight,

                                   10, 10));

 

 

 

// fill Ellipse2D.Double

redtowhite = new GradientPaint(0,0,color.RED,100, 0,color.WHITE);

g2.setPaint(redtowhite);

g2.fill (new Ellipse2D.Double(0, 0, 100, 50));

 

 

 

1.3.1 定义花哨的线类型和填充方式

使用Java 2D StrokePaint类,您可以定义花哨的线类型和填充方式。

 

1.3.1.1 线类型

线类型由Graphics2D渲染上下文的stroke属性定义。要设置stroke属性,您首先创建一个BasicStroke对象,然后将它传递到Graphics2DsetStroke方法中。

BasicStroke对象中保存着关于线宽,结合类型,端点风格,短线风格。这些信息在Shape使用draw方法渲染时使用。

线宽是线轨迹直角的宽度。线宽在用户坐标系中使用浮点数表示,默认的转换方式是等于一英寸的1/72

连接风格是两个线段片段相交时的处理。BasicStroke支持下面三种相交风格:

 

 

 

端点风格是线段片段端点的装饰。BasicStroke支持以下三种端点风格:

 

 

 

Dash风格定义了线段中透明的和不透明的部分。Dash风格由dash数组和dash阶段定义。Dash数组定义了dash的模式。数组中的每个元素表示了用户坐标系单元中dash长度和空白的长度。元素0表示第一个dash,元素1表示第一个空白,以此类推。Dash阶段是dash模式的补偿,也使用用户坐标系单元指定。Dash阶段表示线段的开始应用哪部分dash模式。

 

1.3.1.2 填充模式

填充模式由Graphics2D渲染上下文的paint属性定义。要设置paint属性,您需要创建一个实现Paint接口的对象,然后将其传入Graphics2DsetPaint方法中。

以下三个类实现了Paint接口:Color, GradientPaintTexturePaint

要创建GradientPaint,你需要指定开始位置和颜色,以及终止位置和颜色。渐变色按比例的在线段连接的两端之间由一种颜色变换成另一种颜色。例如:

 

 

 

TexturePaint类的模式由BufferedImage类定义。要创建TexturePaint对象,您指定包含模式和矩形的图像,其中矩形用来复制和保存模式。下图展示了这种特性: