Graphics 对象是 Java AWT (Abstract Window Toolkit) 包中的一个核心类,它代表了绘图上下文,你可以把它想象成一个“画笔”或者“画家”,它知道如何在特定的组件(如窗口、按钮、面板等)上绘制图形、文本和图像。

核心概念:Graphics 对象是什么?
Graphics 对象本身并不存储要绘制的内容,它封装了执行绘图操作所需的所有信息和方法,
- 绘图目标: 你要在哪个组件上画?(一个
JPanel) - 当前颜色: 画笔的当前颜色是什么?
- 当前字体: 绘制文本时使用的字体是什么?
- 坐标系: 组件的左上角是坐标原点 (0, 0),X 轴向右,Y 轴向下。
当你调用一个组件的 paint() 或 paintComponent() 方法时,Java 会自动为你创建一个 Graphics 对象作为参数传入,你不需要手动创建它,只需要使用它。
如何获取和使用 Graphics 对象?
Graphics 对象通常在重写绘画方法时获得,主要有两个关键方法:
a) paint(Graphics g) (AWT Component 类)
这是最基础的绘画方法,几乎所有可显示的 AWT 组件都有,当组件首次显示、被遮挡后重新显示、或者被调整大小时,系统会自动调用此方法。

import java.awt.*;
import java.applet.Applet; // 为了简单,用 Applet 演示,在现代 Swing 中类似
public class MyFirstApplet extends Applet {
@Override
public void paint(Graphics g) {
// g 就是系统传给我们的 "画笔"
g.drawString("Hello, AWT Graphics!", 50, 50);
}
}
b) paintComponent(Graphics g) (Swing JComponent 类)
这是在 Swing 中推荐使用的方法,它是 javax.swing.JComponent 类的一部分。
关键区别:paintComponent() 只负责绘制组件的“内容”,而 paint() 方法会先绘制组件的边框和背景,然后再调用 paintComponent(),在 paintComponent() 中,你通常应该先调用 super.paintComponent(g) 来清除背景,然后再绘制你自己的内容。
import javax.swing.*;
import java.awt.*;
public class MyDrawingPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
// 1. 调用父类方法,清除组件背景(非常重要!)
super.paintComponent(g);
// 2. 现在可以使用 g 对象进行绘制
g.setColor(Color.BLUE);
g.fillRect(20, 20, 100, 50); // 画一个蓝色矩形
g.setColor(Color.RED);
g.drawString("Hello, Swing Graphics!", 30, 100);
}
}
Graphics 对象的核心方法
Graphics 类提供了丰富的绘图方法,可以大致分为以下几类:
1 绘制基本图形
| 方法 | 描述 |
|---|---|
drawLine(int x1, int y1, int x2, int y2) |
画一条从 (x1, y1) 到 (x2, y2) 的直线。 |
drawRect(int x, int y, int width, int height) |
画一个矩形(空心)。 |
fillRect(int x, int y, int width, int height) |
画一个填充的矩形(实心)。 |
drawOval(int x, int y, int width, int height) |
画一个椭圆(空心),椭圆内切于指定的矩形。 |
fillOval(int x, int y, int width, int height) |
画一个填充的椭圆(实心)。 |
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) |
画一个圆弧(空心)。 |
fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) |
画一个填充的扇形(实心)。 |
drawPolygon(int[] xPoints, int[] yPoints, int nPoints) |
画一个由多个点构成的多边形(空心)。 |
fillPolygon(int[] xPoints, int[] yPoints, int nPoints) |
画一个填充的多边形(实心)。 |
示例:

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 画一条线
g.drawLine(10, 10, 200, 10);
// 画一个红色实心矩形
g.setColor(Color.RED);
g.fillRect(10, 20, 100, 80);
// 画一个蓝色空心椭圆
g.setColor(Color.BLUE);
g.drawOval(120, 20, 100, 80);
}
2 绘制文本
| 方法 | 描述 |
|---|---|
drawString(String str, int x, int y) |
在指定的位置绘制字符串,坐标 (x, y) 是文本基线的起点。 |
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(new Font("宋体", Font.BOLD, 24)); // 设置字体
g.drawString("你好,世界!", 50, 150);
}
3 设置绘图属性
在绘制之前,你需要设置画笔的属性。
| 方法 | 描述 |
|---|---|
setColor(Color c) |
设置绘图颜色。Color 类提供了预定义颜色,如 Color.RED, Color.BLACK,也可以用 new Color(r, g, b) 自定义。 |
setFont(Font f) |
设置字体。Font 类通过字体名称、样式(Font.PLAIN, Font.BOLD, Font.ITALIC)和大小来创建。 |
setXORMode(Color c) |
设置异或模式,在这种模式下,绘制的内容会与已有颜色进行异或运算,常用于实现“橡皮擦”或拖动时的临时效果。 |
setPaintMode() |
恢复到正常的绘制模式(默认模式)。 |
Graphics2D:更强大的绘图
Graphics 是一个基础类,功能有限,现代 Java 图形编程主要使用它的子类 Graphics2D,它提供了更强大的功能,如抗锯齿、旋转变换、透明度、复杂形状等。
如何获取 Graphics2D 对象?只需将传入的 Graphics 参数强制转换即可。
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 将 Graphics 对象转换为 Graphics2D 对象
Graphics2D g2d = (Graphics2D) g;
// 开启抗锯齿,让图形边缘更平滑
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 设置一个渐变色
GradientPaint gradient = new GradientPaint(0, 0, Color.CYAN, 200, 200, Color.MAGENTA);
g2d.setPaint(gradient); // setPaint 比 setColor 更通用
// 画一个圆角矩形
g2d.fillRoundRect(50, 50, 150, 100, 30, 30);
// 保存当前状态
AffineTransform oldTransform = g2d.getTransform();
// 平移坐标系
g2d.translate(250, 0);
// 旋转坐标系(角度是弧度制)
g2d.rotate(Math.toRadians(45));
// 画一个旋转的矩形
g2d.setColor(Color.ORANGE);
g2d.fillRect(0, 0, 100, 50);
// 恢复之前的状态
g2d.setTransform(oldTransform);
}
Graphics2D 的核心思想是将画笔(Graphics2D)和画布(组件)分离,它通过一个变换(AffineTransform)对象来改变坐标系,从而实现平移、旋转、缩放等效果。
完整的 Swing 示例
下面是一个完整的、可运行的 Swing 示例,它创建一个窗口并在一个自定义的面板上绘制各种图形。
import javax.swing.*;
import java.awt.*;
public class GraphicsDemo {
public static void main(String[] args) {
// 创建一个窗口
JFrame frame = new JFrame("Java Graphics Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
// 创建一个自定义的面板,并添加到窗口中
DrawingPanel panel = new DrawingPanel();
frame.add(panel);
// 让窗口可见
frame.setVisible(true);
}
}
// 自定义的绘图面板
class DrawingPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
// 1. 调用父类方法,确保背景被正确绘制
super.paintComponent(g);
// 2. 将 g 转换为 Graphics2D 以获得更强大的功能
Graphics2D g2d = (Graphics2D) g;
// 3. 设置抗锯齿,使图形更平滑
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// --- 绘制基本图形 ---
// 画一条线
g2d.setColor(Color.BLACK);
g2d.drawLine(20, 20, 200, 20);
// 画一个红色实心矩形
g2d.setColor(Color.RED);
g2d.fillRect(20, 40, 100, 80);
// 画一个蓝色空心椭圆
g2d.setColor(Color.BLUE);
g2d.drawOval(140, 40, 100, 80);
// --- 绘制文本 ---
g2d.setColor(Color.DARK_GRAY);
g2d.setFont(new Font("Arial", Font.BOLD, 20));
g2d.drawString("This is a String", 20, 160);
// --- 使用 Graphics2D 的高级功能 ---
// 画一个带渐变色和旋转的矩形
g2d.translate(300, 100); // 将原点(0,0)移动到(300,100)
// 创建一个线性渐变
GradientPaint gp = new GradientPaint(0, 0, Color.GREEN, 100, 100, Color.YELLOW);
g2d.setPaint(gp);
// 画一个填充的矩形
g2d.fillRect(0, 0, 150, 100);
// 旋转画布
g2d.rotate(Math.toRadians(30)); // 旋转30度
// 画一个带透明度的红色矩形
g2d.setColor(new Color(255, 0, 0, 128)); // 最后一个参数是透明度 (0-255)
g2d.fillRect(50, -50, 100, 100);
// 注意:变换是累积的,后续绘制会继续基于当前变换后的坐标系
// 如果需要重置,可以使用 g2d.setTransform(new AffineTransform());
}
}
| 特性 | Graphics |
Graphics2D |
|---|---|---|
| 功能 | 基础绘图功能 | 强大的 2D 绘图功能 |
| 图形 | 基本形状(线、矩形、椭圆) | 任意 Shape 对象(如 RoundRectangle2D, Path2D) |
| 颜色 | 单一颜色 (setColor) |
任何 Paint 对象(Color, GradientPaint, TexturePaint) |
| 变换 | 无 | 强大的 AffineTransform(平移、旋转、缩放) |
| 渲染 | 无 | 可配置的渲染提示(如抗锯齿) |
| 使用场景 | 简单的、对性能要求不高的绘图 | 现代、复杂、高质量的图形界面开发 |
核心要点:
- 获取:
Graphics对象由系统在paint()或paintComponent()方法中传入,无需手动创建。 - 使用: 在
paintComponent()中,先调用super.paintComponent(g),然后使用g(或g2d) 的方法进行绘制。 - 升级: 几乎所有情况下,都应该将
g强制转换为Graphics2D(Graphics2D g2d = (Graphics2D) g;) 来使用更现代、更强大的功能。 - 状态:
Graphics对象的状态(颜色、字体等)是累积的,绘制完一部分后,记得用setColor(Color.BLACK)等方法恢复或设置为你想要的状态。
