首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Swing 雙緩衝技術解決繪圖閃爍問題

     編輯:Java 相關知識

在開發遠程桌面協助功能時,接收對方螢幕畫面並顯示於 JLabel 上,若直接在 paint() 繪製圖片,畫面會嚴重閃爍。根因在於 Swing 預設繪圖流程:repaint() → update() → paint(),其中 update() 會先清除背景再呼叫 paint(),導致畫面瞬間變白再重繪,產生閃爍。

雙緩衝原理

雙緩衝(Double Buffering)在記憶體中建立一個與元件同尺寸的離屏圖像 off_screen_buf,所有繪圖操作先在離屏 Graphics 上完成,最後一次性將離屏圖像繪製到螢幕 Graphics 上,避免中間態被使用者看見。

關鍵程式碼實作

public class MyLabel extends JLabel {
    // 雙緩衝離屏緩衝區
    private Image offScreenImage;
    private Graphics offScreenGraphics;

    @Override
    public void paint(Graphics g) {
        // 實際業務繪圖邏輯:繪製遠程螢幕截圖
        if (Myjxta.image != null) {
            this.setPreferredSize(new Dimension(
                    Myjxta.image.getWidth(), Myjxta.image.getHeight()));
            g.drawImage(Myjxta.image, 0, 0, this);
        }
        // 模擬網路延遲
        try { Thread.sleep(200); } catch (Exception ignored) {}
    }

    @Override
    public void update(Graphics g) {
        if (Myjxta.image != null) {
            // 1. 建立離屏圖像與 Graphics
            offScreenImage = this.createImage(this.getWidth(), this.getHeight());
            offScreenGraphics = offScreenImage.getGraphics();

            // 2. 在離屏上完成所有繪圖
            paint(offScreenGraphics);

            // 3. 釋放離屏 Graphics 資源
            offScreenGraphics.dispose();

            // 4. 一次性將離屏圖像畫到螢幕
            g.drawImage(offScreenImage, 0, 0, null);

            // 5. 觸發下一幀重繪(形成動畫迴路)
            this.repaint();
        }
    }
}

關鍵點解析

步驟說明
建立離屏圖像createImage(w, h) 產生與元件等大的 Image
取得離屏 GraphicsoffScreenImage.getGraphics() 所有繪圖導向記憶體
呼叫 paint()將原本給螢幕的 Graphics 換成離屏 Graphics
釋放資源dispose() 避免記憶體洩漏
一次性上螢幕g.drawImage(offScreenImage, 0, 0, null) 無閃爍
持續重繪repaint() 形成動畫迴路

現代替代方案

Swing 元件預設已啟用雙緩衝(JComponent.setDoubleBuffered(true)),若仍閃爍,請檢查:

  • 是否在 paint() 中執行耗時運算或 I/O(應移至背景執行緒)
  • 是否重寫 update() 卻未正確處理背景清除
  • 嘗試使用 BufferStrategy(適用於全螢幕/Canvas)或 JavaFX 內建雙緩衝

本例展示手動控制雙緩衝的經典寫法,理解其機制有助於排查疑難雜症。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved