private void button3_Click(object sender, EventArgs e)
{
this.DoubleBuffered = true;
for (int i = 0; i < 350; i++)
{
using (Graphics g = this.CreateGraphics() )
{
g.Clear(Color.CadetBlue);
g.DrawImage(Properties.Resources._256, 100, 100, i-150, i-150);
}
}
}
然而,我认为我将DoubleBuffered设置为true,图像仍然闪烁。有什么想法我做错了什么? 谢谢!
答案 0 :(得分:6)
正如Neil所说,你不需要(也不应该)在循环的每次迭代中创建一个新的Graphics对象。这些是相对昂贵的资源,不应该毫无疑问地创建。
此外,您不应该在按钮内部进行绘制通过调用CreateGraphics来单击处理程序。它可能会导致问题,最明显的是当调用绘制处理程序时(即,每次窗口收到WM_PAINT消息并刷新时)您的绘图都“撤消”。您应该通过覆盖OnPaint来完成所有绘画,并在需要更新表单时简单地调用Invalidate()。
至于闪烁,将DoubleBuffered设置为true通常会处理它,但滚动自己的双缓冲是微不足道的。试试看。还要意识到在这样的循环中绘制可能不是你想要做的。如果要每隔一段时间更新一次,请使用计时器。您的代码正在以循环执行的速度执行,这通常是不可取的。
private void someTimer_Tick( ... )
{
Invalidate();
}
protected override void OnPaint( PaintEventArgs e )
{
using( var tempBmp = new Bitmap( ... ) )
using( var g = Graphics.FromImage( tempBmp ) )
{
// draw to tempBmp
e.Graphics.DrawImage( tempBmp, new Point( 0, 0 ) );
}
}
答案 1 :(得分:2)
问题是你是在循环的每次迭代中创建一个新的图形对象
在using语句中移动for语句,您应该会看到显着的性能提升:
using (Graphics g = this.CreateGraphics() )
{
for (int i = 0; i < 350; i++)
{
g.Clear(Color.CadetBlue);
g.DrawImage(Properties.Resources._256, 100, 100, i-150, i-150);
}
}
那,将您正在加载的资源文件移动到局部变量中也是一个好主意。
答案 2 :(得分:2)
Double-buffering仅对Paint事件启用。您正在使用CreateGraphics()直接绘制到屏幕,g.Clear()调用非常明显,因为它会立即擦除绘制的图像。不在Paint事件或OnPaint方法中绘图几乎总是一个错误。