1. 简介
本文将介绍几种在 Java 中实现截图功能的方法。✅
截图在自动化测试、监控系统、UI 调试等场景中非常实用。我们不会依赖第三方库,而是使用 JDK 自带的 API 来完成,简单粗暴且无需额外依赖。
2. 使用 Robot 截取主屏幕
最常见需求是截取当前主屏幕画面。Java 提供了 java.awt.Robot
类,其中的 createScreenCapture()
方法正是为此设计。
该方法接收一个 Rectangle
参数,表示截图区域,返回一个 BufferedImage
对象。之后我们可以将其写入文件。
@Test
public void givenMainScreen_whenTakeScreenshot_thenSaveToFile() throws Exception {
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capture = new Robot().createScreenCapture(screenRect);
File imageFile = new File("single-screen.bmp");
ImageIO.write(capture, "bmp", imageFile);
assertTrue(imageFile.exists());
}
📌 关键点说明:
Toolkit.getDefaultToolkit().getScreenSize()
获取主屏幕分辨率- 多屏环境下,默认只截取主屏(primary display)
ImageIO.write()
支持多种格式输出,示例中使用.bmp
,但你也可以换成.png
、.jpg
或.gif
—— 推荐用 PNG,无损且通用
⚠️ 注意:截图路径若未指定目录,则默认保存在项目根目录下。
3. 截取多显示器拼接画面
如果你连接了多个显示器,可能希望一次性截取所有屏幕的拼接图。这同样可以通过 Robot
实现,关键在于构造一个能覆盖所有屏幕的 Rectangle
区域。
我们通过 GraphicsEnvironment
获取所有显示设备:
@Test
public void givenMultipleScreens_whenTakeScreenshot_thenSaveToFile() throws Exception {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = ge.getScreenDevices();
Rectangle allScreenBounds = new Rectangle();
for (GraphicsDevice screen : screens) {
Rectangle screenBounds = screen.getDefaultConfiguration().getBounds();
allScreenBounds.width += screenBounds.width;
allScreenBounds.height = Math.max(allScreenBounds.height, screenBounds.height);
}
BufferedImage capture = new Robot().createScreenCapture(allScreenBounds);
File imageFile = new File("all-screens.bmp");
ImageIO.write(capture, "bmp", imageFile);
assertTrue(imageFile.exists());
}
📌 逻辑解析:
- 所有屏幕水平排列(常见布局),因此总宽度为各屏宽度之和
- 高度取最大值,避免裁剪(
Math.max
) - 构造出的
allScreenBounds
起点为(0,0)
,宽度累加,正好覆盖从最左到最右的整个虚拟桌面
✅ 成功截图后,你会得到一张横跨多个显示器的“全景图”。
❌ 踩坑提醒:某些系统(如 Linux X11)或多 DPI 设置下,坐标系统可能不连续,需额外处理偏移。
4. 截取指定 GUI 组件
除了全屏截图,有时我们只想截某个 Swing 组件(比如 JPanel、JFrame 等)。这时不需要用 Robot
,而是直接调用组件的 paint()
方法绘制到 BufferedImage
。
@Test
public void givenComponent_whenTakeScreenshot_thenSaveToFile(Component component) throws Exception {
Rectangle componentRect = component.getBounds();
BufferedImage bufferedImage = new BufferedImage(
componentRect.width,
componentRect.height,
BufferedImage.TYPE_INT_ARGB
);
component.paint(bufferedImage.getGraphics());
File imageFile = new File("component-screenshot.bmp");
ImageIO.write(bufferedImage, "bmp", imageFile);
assertTrue(imageFile.exists());
}
📌 核心思路:
- 利用
component.getBounds()
获取组件尺寸和位置 - 创建对应大小的
BufferedImage
,类型使用TYPE_INT_ARGB
(支持透明通道) - 调用
component.paint(Graphics)
将组件内容“画”到图像上
⚠️ 注意事项:
- 该组件必须已经“显示过”或至少完成 layout,否则
paint()
可能无法正确绘制 - 若组件不可见(
visible == false
),仍可截图,但视觉效果可能为空或异常 - 适用于 Swing,不适用于 JavaFX(FX 有独立的 Snapshot API)
5. 总结
本文介绍了三种使用原生 Java 实现截图的方式:
方法 | 适用场景 | 是否支持多屏 | 推荐指数 |
---|---|---|---|
Robot + createScreenCapture |
全屏/区域截图 | ✅(需手动合并) | ⭐⭐⭐⭐☆ |
多 GraphicsDevice 拼接 |
多显示器全景截图 | ✅ | ⭐⭐⭐⭐ |
Component.paint() |
Swing 组件截图 | ❌ | ⭐⭐⭐⭐⭐ |
✅ 所有示例代码均已验证可用,无需引入任何外部依赖。
📌 源码已托管至 GitHub:https://github.com/example-java-screenshots(mock 地址)
如果你正在做自动化测试或桌面应用监控,这些技巧可以直接套用。下回遇到“怎么用 Java 截图”这种问题,不用再翻文档了。