![](/img/trans.png)
[英]C# flickering when using Graphics.DrawImage with Transparancy
[英]C# graphics flickering
我正在開發某種繪圖程序,但在繪制橡皮筋線時移動鼠標光標時出現閃爍問題。 我希望你能幫我去除那條閃爍的線,這是代碼:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace GraphicsTest
{
public partial class Form1 : Form
{
int xFirst, yFirst;
Bitmap bm = new Bitmap(1000, 1000);
Graphics bmG;
Graphics xG;
Pen pen = new Pen(Color.Black, 1);
bool draw = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bmG = Graphics.FromImage(bm);
xG = this.CreateGraphics();
bmG.Clear(Color.White);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
xFirst = e.X;
yFirst = e.Y;
draw = true;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
bmG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
draw = false;
xG.DrawImage(bm, 0, 0);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (draw)
{
xG.DrawImage(bm, 0, 0);
xG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
xG.DrawImage(bm, 0, 0);
}
}
}
首先不要使用CreateGraphics()
除非你絕對必須。 將事件處理程序綁定到OnPaint
並在您想要刷新表面時調用Invalidate()
。
如果您不希望它閃爍,則需要對繪圖表面進行雙重緩沖。 最簡單的方法是將表單的DoubleBuffered
屬性設置為 True。
如果您打算將其擴展為將繪圖繪制到 PictureBox 控件,我強烈建議您。 默認情況下,PictureBox 是雙緩沖的,允許您更簡單地控制繪圖區域。
在代碼中:
public partial class Form1 : Form
{
int xFirst, yFirst;
Bitmap bm = new Bitmap(1000, 1000);
Graphics bmG;
Pen pen = new Pen(Color.Black, 1);
bool draw = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bmG = Graphics.FromImage(bm);
bmG.Clear(Color.White);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
xFirst = e.X;
yFirst = e.Y;
draw = true;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
bmG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
draw = false;
Invalidate();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (draw)
{
Invalidate();
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (draw) {
e.Graphics.DrawImage(bm, 0, 0);
e.Graphics.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
} else {
e.Graphics.DrawImage(bm, 0, 0);
}
}
}
編輯:
另一個問題,您正在創建一個私人Pen
成員。 筆(和畫筆,以及許多 GDI+ 對象)表示需要處理的非托管對象的句柄,否則您的程序將泄漏。 要么將它們包裝在using
語句中(首選且異常安全的方式),要么在表單的Dispose
方法中顯式處理它們。
或者,在 System.Drawing 中,您可以訪問一些不需要(也不應該)處理的預先構建的鋼筆和畫筆。 像這樣使用它們:
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (draw) {
e.Graphics.DrawImage(bm, 0, 0);
e.Graphics.DrawLine(Pens.Black, xFirst, yFirst, e.X, e.Y);
} else {
e.Graphics.DrawImage(bm, 0, 0);
}
}
它閃爍的原因是您正在繪制背景(立即顯示在屏幕上,擦除線條)然后疊加線條。 因此,該線不斷消失和出現,顯示閃爍。
對此的最佳解決方案稱為雙緩沖。 您所做的是將整個圖像繪制到“屏幕外”位圖,並僅在完成后顯示在屏幕上。 因為您只顯示完成的圖像,所以沒有閃爍效果。 您應該能夠設置 this.DoubleBuffered = true 讓 WinForms 為您完成所有艱苦的工作。
注意:您真的不應該在您的油漆處理程序之外進行繪制 - 理想情況下,您應該 Invalidate() 需要重繪的區域,然后您的油漆處理程序將只重繪該區域(根據需要使用任何重疊線等)。
固定和工作代碼。
public partial class Form1 : Form
{
int x1, y1, x2, y2;
bool drag = false;
Bitmap bm = new Bitmap(1000, 1000);
Graphics bmg;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bmg = Graphics.FromImage(bm);
}
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
drag = true;
x1 = e.X;
y1 = e.Y;
}
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
drag = false;
bmg.DrawLine(Pens.Black, x1, y1, e.X, e.Y);
pictureBox.Invalidate();
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (drag)
{
x2 = e.X;
y2 = e.Y;
pictureBox.Invalidate();
}
}
private void pictureBox_Paint(object sender, PaintEventArgs e)
{
if (drag) {
e.Graphics.DrawImage(bm, 0, 0);
e.Graphics.DrawLine(Pens.Black, x1, y1, x2, y2);
}
else {
e.Graphics.DrawImage(bm, 0, 0);
}
}
}
我用它來管理雙緩沖到面板中:
myPanel.GetType().GetMethod("SetStyle",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic).Invoke(myPanel,
new object[]
{
System.Windows.Forms.ControlStyles.UserPaint |
System.Windows.Forms.ControlStyles.AllPaintingInWmPaint |
System.Windows.Forms.ControlStyles.DoubleBuffer, true
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.