AWT 提供豐富的 Graphics 繪圖方法,但直接在螢幕繪圖易導致閃爍、效能差。將繪圖操作導向記憶體內的 Image 物件(離屏繪圖/雙緩衝),再一次性繪製到螢幕,是流暢動畫、報表生成、元件快照的關鍵技術。
首選方案:使用 java.awt.image.BufferedImage 而非傳統 Image,因其提供 createGraphics() 回傳功能更強大的 Graphics2D 物件,支援反鋸齒、幾何變換、複合繪圖等進階特性。
// 1. 建立離屏緩衝影像(指定寬高、影像類型)
BufferedImage offscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// 2. 取得 Graphics2D 繪圖上下文
Graphics2D g2d = offscreenImage.createGraphics();
// 3. 可選:啟用高品質繪圖提示
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// 4. 執行繪圖操作
g2d.drawRect(10, 10, 50, 20);
g2d.fillOval(30, 30, 40, 40);
g2d.drawString("Hello", 20, 50);
// 5. 釋放繪圖資源
g2d.dispose();
// 6. 後續使用:寫入檔案、網路傳輸、螢幕繪製
// ImageIO.write(offscreenImage, "PNG", new File("output.png"));
// screenGraphics.drawImage(offscreenImage, 0, 0, null);
public static BufferedImage captureComponent(Component comp) {
// 確保元件已佈局且可繪製
BufferedImage image = new BufferedImage(
comp.getWidth(), comp.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
comp.paint(g2d); // 或 comp.printAll(g2d) 含子元件
g2d.dispose();
return image;
}
注意:元件必須可繪製(已加入容器、可見)。不可見元件需先加入不可見容器佈局後再擷取。開源庫 nanoTITAN ComponentUtility 提供封裝好的快照方法。
public class SmoothAnimation extends JPanel implements Runnable {
private BufferedImage buffer;
private volatile boolean running = true;
public void run() {
while (running) {
// 1. 確保緩衝區尺寸匹配
if (buffer == null || buffer.getWidth() != getWidth() || buffer.getHeight() != getHeight()) {
buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
}
// 2. 離屏繪製完整幀
Graphics2D g2d = buffer.createGraphics();
drawFrame(g2d); // 自訂繪圖邏輯
g2d.dispose();
// 3. 觸發重繪(EDT 執行緒)
SwingUtilities.invokeLater(this::repaint);
// 4. 幀率控制
try { Thread.sleep(16); } catch (InterruptedException ignored) {}
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (buffer != null) g.drawImage(buffer, 0, 0, null); // 一次性繪製無閃爍
}
}
javax.imageio.ImageIO 內建支援 PNG、JPEG、GIF、BMP、WBMP 讀寫// 現代寫法
ImageIO.write(bufferedImage, "PNG", outputStream); // 或 File、ImageOutputStream
| 因素 | 建議 |
|---|---|
| 影像尺寸 | 按實際顯示尺寸建立,避免過大浪費記憶體 |
| 影像類型 | TYPE_INT_ARGB (32位含透明) 最通用;不需透明用 TYPE_INT_RGB 節省 25% 記憶體 |
| Graphics2D 釋放 | 必須呼叫 dispose(),否則洩漏原生資源 |
| 重用緩衝區 | 動畫循環中重用同一 BufferedImage,避免頻繁 GC |
BufferedImage.createGraphics() 是 AWT/Swing 離屏繪圖、影像生成、元件快照的統一入口。掌握「建立→繪製→釋放→使用」四步範式,配合 Graphics2D 進階渲染提示,能解決閃爍、實現高品質向量繪圖、生成報表圖片、支援列印預覽等多元需求。這是 Java 客戶端圖形程式設計的必修內功。