2
        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,图像仍然闪烁。任何想法我做错了什么?谢谢!

4

3 回答 3

6

正如 Neil 所指出的,您不需要(也不应该)在循环的每次迭代中创建一个新的 Graphics 对象。这些是相对昂贵的资源,不应随意创建。

此外,您不应该通过调用 CreateGraphics 在按钮 Click 处理程序中进行这样的绘制。它可能会导致问题,最明显的是在调用绘制处理程序时您的绘图被“撤消”(即,每次窗口接收到 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 ) );
    }
}
于 2011-02-23T18:25:51.517 回答
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);
     }
}

那,将您正在加载的资源文件移动到局部变量中也可能是一个好主意。

于 2011-02-23T18:22:55.487 回答
2

仅对 Paint 事件启用双缓冲。您正在使用 CreateGraphics() 直接在屏幕上绘图,g.Clear() 调用非常明显,因为它会立即擦除绘制的图像。没有在 Paint 事件或 OnPaint 方法中绘图几乎总是一个错误。

于 2011-02-23T18:36:10.093 回答