首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# PictureBox 繪圖消失之謎:CreateGraphics 非持久化特性與 Paint 事件正解

     編輯:程式設計綜合問答

現象原因

使用 `pictureBox.CreateGraphics()` 獲取的 `Graphics` 物件進行繪圖 (如 `DrawEllipse` 棋子),**繪製內容僅存在於視訊記憶體 (顯示緩衝區) 中,不持久化到 `Image` 屬性**。當視窗最小化、遮擋、拖動、失去焦點重繪時,Windows 發送 `WM_PAINT`,`PictureBox` 重繪其 `Image` 屬性 (棋盤背景),**你的臨時繪圖內容隨即消失**。

正解:兩種持久化繪圖模式

模式一:離屏位圖 + Image 屬性 (推薦、效能最佳)

// 1. 建立離屏位圖 (尺寸 = PictureBox.ClientSize)
Bitmap offscreenBmp = new Bitmap(picBox.Width, picBox.Height);
using (Graphics g = Graphics.FromImage(offscreenBmp)) {
    // 2. 先畫背景 (棋盤)
    g.DrawImage(Properties.Resources.Board, 0, 0);
    // 3. 畫所有棋子 (從資料模型遍歷)
    foreach (var piece in pieces) {
        g.DrawImage(piece.Image, piece.Rect);
    }
}
// 4. 一次性賦值給 PictureBox (自動觸發重繪)
picBox.Image?.Dispose(); // 釋放舊圖
picBox.Image = offscreenBmp;

優點:雙緩衝無閃爍、繪圖邏輯集中、縮放/列印支援原生、資料驅動視圖 (MVC)。

模式二:重寫 OnPaint / 訂閱 Paint 事件

// 繼承 PictureBox 或在 Form 載入時訂閱
picBox.Paint += (sender, e) => {
    Graphics g = e.Graphics;
    // 1. 畫背景
    g.DrawImage(Properties.Resources.Board, 0, 0);
    // 2. 畫棋子 (讀取資料模型)
    foreach (var piece in pieces) {
        g.DrawImage(piece.Image, piece.Rect);
    }
};
// 資料變更時呼叫
picBox.Invalidate(); // 觸發重繪

優點:標準 WinForms 繪圖模式、自動處理重繪。缺點:高頻 `Invalidate` 可能閃爍 (需設 `DoubleBuffered = true`)、繪圖邏輯分散在事件中。

五子棋專項建議

  • 建立 `Piece` 類 `{ Point Position; Color Color; }` 列表作為**唯一資料源**。
  • 落子邏輯:`pieces.Add(new Piece(...))` -> `picBox.Invalidate()`。
  • 悔棋/重開:`pieces.Clear()` / `pieces.RemoveAt()` -> `picBox.Invalidate()`。
  • 判斷輸贏:遍歷 `pieces` 陣列檢查五連線,**完全脫離繪圖邏輯**。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved