Graphics2D 是 Java 2D API 的核心类,它扩展了 Graphics 类,提供了更强大、更灵活的 2D 图形绘制功能,与早期 Graphics 类主要用于绘制基本图形(线、矩形、圆)不同,Graphics2D 引入了现代图形学的概念,如坐标变换、抗锯齿、任意形状的路径、渐变和纹理填充等。

你可以把 Graphics2D 想象成一个功能极其丰富的“虚拟画笔”和“虚拟画布”,你可以用它来绘制从简单的 UI 组件到复杂的图表、游戏画面等各种 2D 图形。
核心概念:Graphics2D 的工作模式
Graphics2D 的工作遵循一个核心思想:修改状态,然后绘制,这个状态由一个叫做 Graphics2D 对象自身的属性集合来定义,在调用任何绘制方法(如 draw() 或 fill())之前,你需要先设置好这些属性。
这些属性主要包括:
Stroke(描边): 定义线条的样式,如宽度、虚线模式等。Paint(填充): 定义填充图形内部的方式,可以是纯色、渐变色或图案。Font(字体): 定义绘制文本时使用的字体。Transform(变换): 定义坐标系的变换,如平移、旋转、缩放等。Composite(合成): 定义新绘制的图形与已有图形如何混合(如透明度)。Rendering Hint(渲染提示): 提供关于如何进行高质量渲染的提示,如是否启用抗锯齿。
如何获取 Graphics2D 对象?
你通常不会直接 new 一个 Graphics2D 实例,相反,它会由 Java AWT 或 Swing 框架在特定事件(如组件需要重绘时)传递给你。

最常见的场景是在 Swing 组件的 paintComponent 方法中:
import javax.swing.*;
import java.awt.*;
public class MyCanvas extends JPanel {
@Override
protected void paintComponent(Graphics g) {
// 1. 首先调用父类的 paintComponent,确保组件的正常绘制
super.paintComponent(g);
// 2. 将传入的 Graphics 对象强制转换为 Graphics2D
Graphics2D g2d = (Graphics2D) g;
// 3. 你就可以使用 g2d 的所有强大功能了
// ... 在这里绘制你的图形 ...
}
}
为什么需要强制转换?
paintComponent 方法的参数是 Graphics,这是一个更基础、更通用的类,为了使用 Java 2D 的高级功能,你必须将其“升级”为 Graphics2D。
Graphics2D 的核心功能与使用示例
下面我们通过代码示例来展示 Graphics2D 的主要功能。
示例1:基本图形绘制
这是 Graphics2D 的基础,但它比 Graphics 更灵活。

// 在 paintComponent 方法中 Graphics2D g2d = (Graphics2D) g; // 设置抗锯齿,让图形边缘更平滑 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 1. 绘制一个填充矩形 g2d.setColor(Color.BLUE); g2d.fillRect(50, 50, 100, 80); // 2. 绘制一个描边矩形 g2d.setColor(Color.RED); g2d.setStroke(new BasicStroke(3.0f)); // 设置线条宽度为3像素 g2d.drawRect(170, 50, 100, 80); // 3. 绘制一个填充圆形 g2d.setColor(Color.GREEN); g2d.fillOval(50, 160, 100, 100); // 4. 绘制一个描边圆形 g2d.setColor(Color.ORANGE); g2d.setStroke(new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); g2d.drawOval(170, 160, 100, 100);
示例2:使用 Paint(渐变填充)
Paint 接口允许你用更复杂的方式填充图形,比如线性渐变。
// 创建一个从左到右的线性渐变 // 参数:起点坐标, 终点坐标, 颜色数组, 颜色位置数组 (null 表示均匀分布) GradientPaint gradient = new GradientPaint(50, 50, Color.YELLOW, 250, 250, Color.RED); // 设置当前的填充模式为这个渐变 g2d.setPaint(gradient); // 用这个渐变填充一个矩形 g2d.fillRect(50, 50, 200, 200);
示例3:使用 Stroke(虚线描边)
BasicStroke 可以让你创建虚线、点线等。
// 创建一个虚线模式
// 参数:线宽, 端点样式, 连接样式, 虚线模式数组, 虚线偏移量
float[] dashPattern = {10.0f, 5.0f}; // 10像素实线,5像素空白
BasicStroke dashedStroke = new BasicStroke(2.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0.0f, dashPattern, 0.0f);
g2d.setStroke(dashedStroke);
g2d.setColor(Color.PURPLE);
g2d.drawRect(50, 50, 200, 200);
示例4:使用 Transform(坐标变换)
这是 Graphics2D 最强大的功能之一,它允许你移动、旋转、缩放整个坐标系。
重要提示:变换操作是累积的,并且会影响后续的所有绘制,通常的做法是保存当前状态 -> 应用变换 -> 绘制 -> 恢复状态。
// 保存当前原始的 Graphics2D 状态 g2d.save(); // 1. 平移坐标系 g2d.translate(100, 100); // 原点 (0,0) 现在在 (100,100) 位置 // 2. 旋转坐标系 (弧度) // Math.PI / 2 表示 90 度 g2d.rotate(Math.PI / 4); // 围绕当前原点 (0,0) 旋转,也就是新的 (100,100) 点 // 3. 缩放坐标系 g2d.scale(1.5, 1.5); // x 和 y 方向都放大 1.5 倍 // 在这个变换后的坐标系中绘制一个矩形 // 这个矩形在原始坐标系中的位置会非常复杂,但现在画起来很简单 g2d.setColor(Color.MAGENTA); g2d.fillRect(-50, -50, 100, 100); // 围绕新原点绘制 // 恢复到之前保存的状态,避免影响后续绘制 g2d.restore(); // 在原始坐标系中绘制一个矩形,用于对比 g2d.setColor(Color.BLACK); g2d.drawRect(50, 50, 100, 100);
示例5:绘制任意形状(Path2D)
Graphics2D 可以绘制由直线和曲线组成的任意复杂路径。
// 创建一个路径对象 Path2D path = new Path2D.Double(); // 移动到起点 path.moveTo(50, 50); // 画一条线到 (150, 50) path.lineTo(150, 50); // 画一条二次贝塞尔曲线 // 参数:控制点x, 控制点y, 终点x, 终点y path.quadTo(200, 100, 150, 150); // 画一条线回到起点,形成封闭图形 path.lineTo(50, 50); // 填充这个路径 g2d.setColor(Color.CYAN); g2d.fill(path); // 描边这个路径 g2d.setColor(Color.BLUE); g2d.setStroke(new BasicStroke(2)); g2d.draw(path);
Graphics2D 的应用场景
- Swing/AWT 自定义绘制:当你需要超越标准组件(如
JButton,JLabel)的功能时,例如绘制一个自定义的进度条、图表、仪表盘等。 - 游戏开发:2D 游戏(如平台跳跃游戏、策略游戏)的渲染核心,每一帧都会通过
paintComponent清空画布,然后重新绘制所有游戏元素(玩家、敌人、背景等)。 - 数据可视化:绘制柱状图、折线图、饼图等,你需要根据数据动态计算坐标和形状,然后用
Graphics2D将其绘制出来。 - 图像处理:虽然 Java 有专门的
BufferedImage和图像处理类,但Graphics2D提供了在图像上绘制图形、文本、叠加其他图像等基础功能。 - 图表生成:生成报告、网页中使用的静态图表图片。
完整可运行的示例代码
下面是一个完整的、可运行的 Swing 应用,它在一个窗口中展示了上面提到的各种 Graphics2D 功能。
import javax.swing.*;
import java.awt.*;
public class Graphics2DDemo extends JFrame {
public Graphics2DDemo() {
setTitle("Java Graphics2D Demo");
setSize(600, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// 将自定义的 JPanel 添加到窗口中
add(new DrawingPanel());
}
public static void main(String[] args) {
// 在事件调度线程中创建和显示 GUI
SwingUtilities.invokeLater(() -> {
new Graphics2DDemo().setVisible(true);
});
}
}
// 自定义的 JPanel,负责所有绘制工作
class DrawingPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// 启用抗锯齿,使图形更平滑
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// --- 1. 基本图形 ---
drawBasicShapes(g2d);
// --- 2. 渐变填充 ---
drawGradient(g2d);
// --- 3. 虚线描边 ---
drawDashedShape(g2d);
// --- 4. 坐标变换 ---
drawTransformedShape(g2d);
// --- 5. 任意路径 ---
drawCustomPath(g2d);
}
private void drawBasicShapes(Graphics2D g2d) {
g2d.setColor(Color.BLUE);
g2d.fillRect(20, 20, 80, 60);
g2d.setColor(Color.RED);
g2d.drawRect(110, 20, 80, 60);
g2d.setColor(new Color(0, 128, 0)); // 绿色
g2d.fillOval(20, 100, 60, 60);
g2d.setColor(Color.ORANGE);
g2d.drawOval(100, 100, 60, 60);
}
private void drawGradient(Graphics2D g2d) {
GradientPaint gradient = new GradientPaint(200, 20, Color.YELLOW, 300, 100, Color.RED);
g2d.setPaint(gradient);
g2d.fillRect(200, 20, 100, 80);
}
private void drawDashedShape(Graphics2D g2d) {
float[] dashPattern = {10.0f, 5.0f};
BasicStroke dashedStroke = new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0.0f, dashPattern, 0.0f);
g2d.setStroke(dashedStroke);
g2d.setColor(Color.PURPLE);
g2d.drawRect(320, 20, 100, 80);
}
private void drawTransformedShape(Graphics2D g2d) {
g2d.save(); // 保存原始状态
g2d.translate(350, 250); // 平移
g2d.rotate(Math.PI / 6); // 旋转30度
g2d.setColor(Color.MAGENTA);
g2d.fillRect(-40, -40, 80, 80); // 围绕新原点绘制
g2d.restore(); // 恢复状态
}
private void drawCustomPath(Graphics2D g2d) {
Path2D star = new Path2D.Double();
double centerX = 100;
double centerY = 350;
double outerRadius = 50;
double innerRadius = 20;
int points = 5;
for (int i = 0; i < points * 2; i++) {
double radius = (i % 2 == 0) ? outerRadius : innerRadius;
double angle = Math.toRadians(i * 180.0 / points) - Math.PI / 2;
double x = centerX + Math.cos(angle) * radius;
double y = centerY + Math.sin(angle) * radius;
if (i == 0) {
star.moveTo(x, y);
} else {
star.lineTo(x, y);
}
}
star.closePath();
g2d.setColor(Color.CYAN);
g2d.fill(star);
g2d.setColor(Color.BLUE);
g2d.setStroke(new BasicStroke(2));
g2d.draw(star);
}
}
Graphics2D 是 Java 进行 2D 图形绘制的基石,掌握它的关键在于理解其状态驱动的绘制模式,即通过设置 Stroke, Paint, Transform 等属性,然后调用 draw() 和 fill() 方法,虽然它已经被一些更现代的库(如 JavaFX)部分取代,但在 Swing 应用、数据可视化和 2D 游戏开发中,Graphics2D 依然是一个非常强大和重要的工具。
