1.問題一,當我們直接在form上連續繪製會出現閃爍的情況!
解決方案:啓用窗體的雙緩衝設置 this.DoubleBuffered = true;或者在構造函數中添加代碼以下代碼即可:
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint, true);
2.假設form中有一個panel,此時我需要在窗口加載動態的在panel中添加數量不等的控件,如果不做處理,在加載時也會出現閃爍
解決方案:將panel設置爲雙緩衝控件,添加一個自定義控件,繼承panel,在自定義控件的構造函數中添加代碼
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint, true);
可以解決閃爍問題,如果編譯報錯,刪除報錯行即可!
3.當我開啓雙緩衝後,繪製正常,一切看起來都是那麼完美,但是如果我們查看CPU佔用率會發現很高,並隨我們繪製的快慢和累計時間而也越來越大!我的電腦基本上上會達到30%左右,這在有的場景下是不能容忍的
經測試發現,關閉雙緩衝,cpu佔用率下降一半,但是還是很高!並且會閃爍!
臨時方案1:究其原因,鼠標移動太快,調用Invalidate次數過多,並且太快! 在mouse_move中使用Thread.sleep(10),來控制刷新頻率。當然,界面刷新可能不太流暢!
臨時方案2:如何每次刷新的位置固定和區域固定,使用Invalidate的重載,傳遞區域進去,這樣也可以有效減少CPU佔用!
解決方案:針對連續繪製的問題,首先我們需要禁用掉Form的雙緩衝,然後重載函數OnPaintBackground和Onpaint,
並且註釋掉base,調用,實現手動繪製背景,這樣,我們再繪製時,背景就不會被擦除!同時繪製的時候,我們只繪製相鄰的點,這樣避免重繪所有點,帶來覆蓋和性能損失!在mouse_up時再在OnPaintBackground中繪製背景和所有節點!
當然如果畫布上繪製的對象很多,在刷新背景時,會明顯看到繪製的先後順序。我們可以新建一個bitmap,大小和畫布一致,然然後將所有對象繪製在bitmap上,繪製完成後使用form的gdi將bitmap繪製在form上即可!
關鍵代碼:
Bitmap memoryPanel = new Bitmap (this.Width, this.Height);
Graphics tempg = Graphics.FromImage(memoryPanel);
tempg.Clear(this.BackColor);
tempg.SmoothingMode = SmoothingMode.AntiAlias;
ReDrawAllElement(tempg);
e.Graphics.DrawImage(memoryPanel, this.ClientRectangle);