坐标
原文:
docs.oracle.com/javase/tutorial/2d/overview/coordinate.html
Java 2D API 维护两个坐标空间:
- 用户空间 – 指定图形基元的空间
- 设备空间 – 输出设备(如屏幕、窗口或打印机)的坐标系统
用户空间是一个设备无关的逻辑坐标系统,即您的程序使用的坐标空间。传递给 Java 2D 渲染例程的所有几何图形都是使用用户空间坐标指定的。
当使用从用户空间到设备空间的默认转换时,用户空间的原点是组件绘图区域的左上角。x坐标向右增加,y坐标向下增加,如下图所示。窗口的左上角是 0,0。所有坐标都使用整数指定,通常足够。但是,有些情况需要浮点数甚至双精度,这也是支持的。
设备空间是一个依赖设备的坐标系统,根据目标渲染设备而变化。虽然窗口或屏幕的坐标系统可能与打印机的坐标系统非常不同,但这些差异对 Java 程序是不可见的。在渲染过程中,用户空间和设备空间之间的必要转换是自动执行的。
Java 2D 渲染
原文:
docs.oracle.com/javase/tutorial/2d/overview/rendering.html
Java 2D API 在不同类型设备上提供统一的渲染模型。在应用程序级别,无论目标渲染设备是屏幕还是打印机,渲染过程都是相同的。当需要显示组件时,其paint
或update
方法会自动使用适当的Graphics
上下文调用。
Java 2D API 包括java.awt.Graphics2D
类,该类扩展了Graphics
类,以提供对 Java 2D API 增强图形和渲染功能的访问。这些功能包括:
- 渲染任何几何原语的轮廓,使用笔画和填充属性(
draw
方法)。 - 通过使用颜色或图案指定的填充属性(
fill
方法)来填充任何几何原语的内部。 - 渲染任何文本字符串(
drawString
方法)。字体属性用于将字符串转换为字形,然后用颜色或图案指定的填充。 - 渲染指定的图像(
drawImage
方法)。
此外,Graphics2D
类支持特定形状的drawOval
和fillRect
等Graphics
渲染方法。上面列出的所有方法可以分为两组:
- 绘制形状的方法
- 影响渲染的方法
第二组方法使用形成Graphics2D
上下文的状态属性,用于以下目的:
- 变化笔画宽度
- 更改如何连接笔画
- 设置裁剪路径以限制渲染区域
- 在渲染对象时平移、旋转、缩放或倾斜对象
- 定义颜色和图案以填充形状
- 指定如何组合多个图形对象
在应用程序中使用 Java 2D API 功能,将传递给组件渲染方法的Graphics
对象转换为Graphics2D
对象。例如:
public void paint (Graphics g) { Graphics2D g2 = (Graphics2D) g; ... }
如下图所示,Graphics2D
类的渲染上下文包含几个属性。
要了解更多关于变换和合成的内容,请参阅 Java2D 中的高级主题。
当设置属性时,会传递适当的属性对象。如下例所示,要将绘画属性更改为蓝绿色渐变填充,您需要构造一个 GradientPaint
对象,然后调用 setPaint
方法。
gp = new GradientPaint(0f,0f,blue,0f,30f,green); g2.setPaint(gp);
几何基元
原文:
docs.oracle.com/javase/tutorial/2d/overview/primitives.html
Java 2D API 提供了一组有用的标准形状,如点、线、矩形、弧、椭圆和曲线。定义常见几何基元的最重要的包是java.awt.geom
包。任意形状可以由直线几何基元的组合表示。
Shape
接口表示具有轮廓和内部的几何形状。此接口提供了一组用于描述和检查二维几何对象的常见方法,并支持曲线线段和多个子形状。Graphics
类仅支持直线段。Shape
接口可以支持曲线段。
关于如何绘制和填充形状的更多详细信息,请参阅几何处理课程。
点
Point2D
类定义了表示(x, y)坐标空间中位置的点。Java 2D API 中的术语“点”与像素不同。点没有面积,不包含颜色,也不能呈现。
点用于创建其他形状。Point2D
类还包括一种计算两点之间距离的方法。
线
Line2D
类是表示一条线的抽象类。线的坐标可以作为双精度数检索。Line2D
类包括几种设置线端点的方法。
您还可以使用下面描述的GeneralPath
类创建直线段。
矩形形状
Rectangle2D
、RoundRectangle2D
、Arc2D
和Ellipse2D
基元都是从RectangularShape
类派生的。此类定义了可以由矩形边界框描述的Shape
对象的方法。RectangularShape
对象的几何形状可以从完全包围Shape
轮廓的矩形中推断出来。
二次和三次曲线
QuadCurve2D
使您能够创建二次参数曲线段。二次曲线由两个端点和一个控制点定义。
CubicCurve2D
类使您能够创建三次参数曲线段。三次曲线由两个端点和两个控制点定义。以下是二次和三次曲线的示例。请参阅描边和填充图形基元以获取三次和二次曲线的实现。
此图表示一个二次曲线。
此图表示一个三次曲线。
任意形状
GeneralPath
类使您能够通过指定沿着形状边界的一系列位置来构造任意形状。这些位置可以通过线段、二次曲线或三次(贝塞尔)曲线连接。以下形状可以通过三条线段和一条三次曲线创建。有关此形状实现的更多信息,请参见描边和填充图形基元。
区域
使用Area
类,您可以对任意两个Shape
对象执行布尔运算,如并集、交集和差集。这种技术通常被称为构造性区域几何,使您能够快速创建复杂的Shape
对象,而无需描述每条线段或曲线。
文本
Java 2D API 具有各种文本渲染功能,包括用于呈现字符串的方法以及用于设置字体属性和执行文本布局的整个类。
如果您只想绘制静态文本字符串,最直接的方法是通过Graphics
类使用drawString
方法直接呈现它。要指定字体,您可以使用Graphics
类的setFont
方法。
如果您想要实现自己的文本编辑例程或需要比文本组件提供的更多对文本布局的控制,您可以使用java.awt.font
包中的 Java 2D 文本布局类。
字体
字体用于表示字符串中字符的形状称为字形。特定字符或字符组合可能表示为一个或多个字形。例如,á可能由两个字形表示,而连字fi可能由一个字形表示。
字体可以被视为一组字形。单个字体可能有许多面孔,如斜体和常规。字体中的所有面孔具有类似的印刷特征,并且可以被识别为同一字体系列的成员。换句话说,具有特定样式的一组字形形成一个字体面孔。一组字体面孔形成一个字体系列。字体系列的集合形成了系统中可用的字体集。
当您使用 Java 2D API 时,您可以通过使用Font
的实例来指定字体。您可以通过调用静态方法GraphicsEnvironment.getLocalGraphicsEnvironment
并查询返回的GraphicsEnvironment
来确定可用的字体。getAllFonts
方法返回一个包含系统上所有可用字体的Font
实例数组。getAvailableFontFamilyNames
方法返回可用字体系列的列表。
文本布局
在文本可以显示之前,必须对其进行布局,以便字符以适当的位置表示为适当的字形。以下是两种用于管理文本布局的 Java 2D 机制:
TextLayout
类管理文本布局、高亮显示和命中检测。TextLayout
提供的功能处理最常见的情况,包括具有混合字体、混合语言和双向文本的字符串。- 您可以通过使用
Font
类创建自己的GlyphVector
对象,然后通过Graphics2D
类渲染每个GlyphVector
对象。因此,您可以完全控制文本的形状和位置。
文本的渲染提示
Java 2D API 使您能够通过使用渲染提示来控制形状和文本渲染的质量。渲染提示由java.awt.RenderingHints
类封装。
当应用于文本时,这种能力用于抗锯齿(也称为平滑边缘)。例如,KEY_TEXT_ANTIALIASING
提示可以让您单独控制文本的抗锯齿效果,而不影响其他形状的抗锯齿效果。要了解更多关于渲染提示的信息,请参阅控制渲染质量课程。
图像
在 Java 2D API 中,图像通常是一个矩形的二维像素数组,其中每个像素表示图像该位置的颜色,而维度表示图像显示时的水平范围(宽度)和垂直范围(高度)。
表示此类图像最重要的图像类是java.awt.image.BufferedImage
类。Java 2D API 将这些图像的内容存储在内存中,以便可以直接访问。
应用程序可以直接创建一个BufferedImage
对象,或从外部图像格式(如 PNG 或 GIF)获取图像。
在任一情况下,应用程序可以通过使用 Java 2D API 图形调用在图像上绘制。因此,图像不仅限于显示照片类型的图像。不同的对象,如线条艺术、文本和其他图形,甚至其他图像都可以绘制到图像上(如下图所示)。
Java 2D API 允许您对BufferedImage
应用图像过滤操作,并包括几个内置过滤器。例如,ConvolveOp
过滤器可用于模糊或锐化图像。
然后生成的图像可以绘制到屏幕上,发送到打印机上,或保存为 PNG、GIF 等图形格式。要了解更多关于图像的信息,请参阅使用图像课程。
打印
原文:
docs.oracle.com/javase/tutorial/2d/overview/printing.html
所有的 Swing 和 Java 2D 图形,包括合成图形和图像,都可以通过使用 Java 2D Printing API 渲染到打印机上。该 API 还提供文档组合功能,使您能够执行诸如更改打印页面顺序之类的操作。
渲染到打印机就像渲染到屏幕一样。打印系统控制何时渲染页面,就像绘图系统控制组件何时在屏幕上绘制一样。
Java 2D Printing API 基于回调模型,其中打印系统而不是应用程序控制打印页面的时间。应用程序向打印系统提供要打印的文档信息,打印系统确定何时需要成像每一页。
以下两个功能对支持打印很重要:
- 作业控制 – 启动和管理打印作业,包括显示标准打印和设置对话框
- 分页 – 在打印系统请求时呈现每一页
当需要成像页面时,打印系统使用适当的Graphics
上下文调用应用程序的print
方法。要在打印时使用 Java 2D API 功能,您将Graphics
对象转换为Graphics2D
类,就像在渲染到屏幕时一样。
教程:开始使用图形
Java 2D API 强大而复杂。然而,Java 2D API 的绝大多数用途利用了java.awt.Graphics
类中封装的其功能的一个小子集。本课程涵盖了应用程序开发人员最常见的需求。较少常见的需求稍后在 Java 2D API 的高级主题中描述。
Graphics
类的大多数方法可以分为两个基本组:
- 绘制和填充方法,使您能够渲染基本形状、文本和图像
- 设置属性的方法,影响绘制和填充的外观
诸如setFont
和setColor
之类的方法定义了如何渲染绘制和填充方法。
本图说明了这些方法与图形对象的关系:
)
绘制方法包括:
drawString
– 用于绘制文本
g.drawString("Hello", 10, 10);
drawImage
– 用于绘制图像
g.drawImage(img, 0, 0, width, height, 0, 0, imageWidth, imageHeight, null);
drawLine
,drawArc
,drawRect
,drawOval
,drawPolygon
– 用于绘制几何形状
g2.draw(new Line2D.Double(0, 0, 30, 40));
根据您当前的需求,您可以根据以下标准在Graphics
类中选择几种方法之一:
- 无论您想要在指定位置以原始大小渲染图像还是将其缩放以适应给定矩形
- 无论您喜欢用颜色填充图像的透明区域还是保持其透明
填充方法适用于几何形状,包括fillArc
,fillRect
,fillOval
,fillPolygon
。
无论您绘制文本还是图像,记住在 2D 图形中,每个点由其 x 和 y 坐标确定。所有绘制和填充方法都需要这些信息,这些信息确定了文本或图像应该渲染在哪里。
例如,要绘制一条线,应用程序调用以下代码:
java.awt.Graphics.drawLine(int x1, int y1, int x2, int y2)
在此代码中*(x1, y1)是线的起点,(x2, y2)*是线的终点。
因此,绘制水平线的代码如下:
Graphics.drawLine(20, 100, 120, 100);
下面的演示累积了所有提到的技术。移动滑块以显示各种天气类型。
注意: 如果您看不到小程序运行,您需要安装至少Java SE Development Kit (JDK) 7版本。
WeatherWizard
演示使用 JSlider
组件以及各种图形功能来生成和显示指定的天气类型。有关 JSlider
类的更多信息,请参阅 Swing 教程的 How to Use Sliders 部分。
WeatherPainter
类的 paint
方法实现了图形特性。以下代码使用 setupWeatherReport()
方法绘制了一个图像。
... origComposite = g2.getComposite(); if (alpha0 != null) g2.setComposite(alpha0); g2.drawImage(img0, 0, 0, size.width, size.height, 0, 0, img0.getWidth(null), img0.getHeight(null), null); if (img1 != null) { if (alpha1 != null) g2.setComposite(alpha1); g2.drawImage(img1, 0, 0, size.width, size.height, 0, 0, img1.getWidth(null), img1.getHeight(null), null); } ...
setFont
和 drawString
方法渲染温度和天气状况。
... // Freezing, Cold, Cool, Warm, Hot, // Blue, Green, Yellow, Orange, Red Font font = new Font("Serif", Font.PLAIN, 36); g.setFont(font); String tempString = feels + " " + temperature+"F"; FontRenderContext frc = ((Graphics2D)g).getFontRenderContext(); ... g.setColor(textColor); int xTextTemp = rX-(int)boundsTemp.getX(); int yTextTemp = rY-(int)boundsTemp.getY(); g.drawString(tempString, xTextTemp, yTextTemp); int xTextCond = rX-(int)boundsCond.getX(); int yTextCond = rY-(int)boundsCond.getY() + (int)boundsTemp.getHeight(); g.drawString(condStr, xTextCond, yTextCond);
fillRect
方法允许您绘制一个填充了指定颜色的矩形。
... Rectangle2D boundsTemp = font.getStringBounds(tempString, frc); Rectangle2D boundsCond = font.getStringBounds(condStr, frc); int wText = Math.max((int)boundsTemp.getWidth(), (int)boundsCond.getWidth()); int hText = (int)boundsTemp.getHeight() + (int)boundsCond.getHeight(); int rX = (size.width-wText)/2; int rY = (size.height-hText)/2; g.setColor(Color.LIGHT_GRAY); g2.fillRect(rX, rY, wText, hText); ...
尝试修改 WeatherWizard
演示以更改图形内容。例如,使用 fillRoundRect
方法代替 fillRect
或在 setFont
方法中应用另一个字体大小。在 WeatherWizard.java
文件中找到此小程序的完整代码。演示还需要以下图像:weather-cloud.png
, weather-rain.png
, weather-snow.png
和 weather-sun.png
,这些图像位于 images
目录中。
教程:与几何形状一起工作
在之前的课程中,您已经学习了关于图形概念的知识,包括关于坐标系和图形对象创建的基本信息。现在,您将进一步学习有关 2D 图形类的详细课程。本课程将向您展示如何使用Graphics2D
类绘制图形基元以及任意形状,以及如何使用花哨的轮廓和填充样式显示图形。这些主题将在以下部分讨论。
绘制几何基元
这一部分解释了如何创建标准形状,如点、线、曲线、弧线、矩形和椭圆。
绘制任意形状
这一部分解释了如何使用GeneralPath
类绘制由直线几何基元组合表示的形状。
填充和描边
这一部分解释了如何设置描边和填充属性,以控制应用于Shape
对象和文本的轮廓和填充样式。
绘制几何图元
原文:
docs.oracle.com/javase/tutorial/2d/geometry/primitives.html
Java 2D API 提供了几个定义常见几何对象(如点、线、曲线和矩形)的类。这些几何类是java.awt.geom
包的一部分。
PathIterator
接口定义了从路径中检索元素的方法。
Shape
接口提供了一组描述和检查几何路径对象的方法。该接口由GeneralPath
类和其他几何类实现。
本节中的所有示例都是通过使用java.awt.geom
包创建几何图形,然后通过使用Graphics2D
类来呈现它们。首先,您需要获取一个Graphics2D
对象,例如通过将paint()
方法的Graphics
参数进行强制转换。
public void paint (Graphics g) { Graphics2D g2 = (Graphics2D) g; ... }
点
Point
类创建一个表示(x,y)坐标空间中位置的点。子类Point2D.Float
和Point2D.Double
分别提供存储点坐标的浮点和双精度。
//Create Point2D.Double Point2D.Double point = new Point2D.Double(x, y);
要创建坐标为 0,0 的点,您可以使用默认构造函数Point2D.Double()
。
您可以使用setLocation
方法设置点的位置如下:
setLocation(double x, double y)
– 以双精度值设置点的位置-定义坐标。setLocation(Point2D p)
– 使用另一个点的坐标设置点的位置。
此外,Point2D
类有方法来计算当前点与给定坐标点之间的距离,或者两点之间的距离。
线
Line2D
类表示(x, y)坐标空间中的线段。Line2D.Float
和Line2D.Double
子类指定了浮点和双精度的线。例如:
// draw Line2D.Double g2.draw(new Line2D.Double(x1, y1, x2, y2));
该类包括几个setLine()
方法来定义线的端点。
或者,可以使用Line2D.Float
类的构造函数指定线的端点如下:
Line2D.Float(float X1, float Y1, float X2, float Y2)
Line2D.Float(Point2D p1, Point2D p2)
在Graphics2D
类中使用 Stroke 对象定义线路径的笔画。
曲线
java.awt.geom
包使您能够创建二次或三次曲线段。
二次曲线段
QuadCurve2D
类实现了Shape
接口。该类表示(x, y)坐标空间中的二次参数曲线段。QuadCurve2D.Float
和QuadCurve2D.Double
子类指定了浮点和双精度的二次曲线。
几个setCurve
方法用于指定曲线的两个端点和控制点,其坐标可以直接定义,通过其他点的坐标定义,或使用给定数组。
一个非常有用的方法,setCurve(QuadCurve2D)
,设置具有与提供的曲线相同端点和控制点的二次曲线。例如:
// 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);
三次曲线段
CubicCurve2D
类还实现了Shape
接口。该类表示(x, y)坐标空间中的三次参数曲线段。CubicCurve2D.Float
和CubicCurve2D.Double
子类指定了浮点和双精度的三次曲线。
CubicCurve2D
类具有设置曲线的类似方法,与QuadraticCurve2D
类相同,只是有第二个控制点。例如:
// 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);
矩形
在下面的示例中表示的原语的类扩展了RectangularShape
类,该类实现了Shape
接口并添加了一些自己的方法。
这些方法使您能够获取有关形状位置和大小的信息,检查矩形的中心点,并设置形状的边界。
Rectangle2D
类表示由位置(x, y)和尺寸(w x h)定义的矩形。Rectangle2D.Float
和Rectangle2D.Double
子类指定了浮点和双精度的矩形。例如:
// draw Rectangle2D.Double g2.draw(new Rectangle2D.Double(x, y, rectwidth, rectheight));
RoundRectangle2D
类表示具有圆角的矩形,由位置(x, y)、尺寸(w x h)和圆角的宽度和高度定义。RoundRectangle2D.Float
和RoundRectangle2D.Double
子类指定了浮点和双精度的圆角矩形。
圆角矩形由以下参数指定:
- 位置
- 宽度
- 高度
- 圆角弧的宽度
- 圆角弧的高度
要设置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));
Java 中文官方教程 2022 版(三十一)(2)https://developer.aliyun.com/article/1487980