C#,WinForms 中的双缓冲区?

发布于 2024-10-19 01:29:08 字数 502 浏览 2 评论 0原文

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

        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);
                }
            }
    }

Yet thought I have the DoubleBuffered set to true, the image still flickers. Any ideas what am I doing wrong?
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

回心转意 2024-10-26 01:29:08

正如 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 ) );
    }
}

As Neil noted, you don't need to (and shouldn't) create a new Graphics object in each iteration of the loop. These are relatively expensive resources and should not be created willy nilly.

Also, you shouldn't be painting like that inside of a button Click handler by calling CreateGraphics. It can lead to problems, most notably your drawing being "undone" when the paint handler is invoked (i.e., every time the window is receives a WM_PAINT message and is refreshed). You should do all of your painting by overriding OnPaint and simply call Invalidate() when you need to update your form.

As for the flickering, setting DoubleBuffered to true will usually take care of it, but rolling your own double buffering is trivial. Give it a try. Also realize that drawing in a loop like that probably isn't what you want to do. Use a timer if you want to update once per some interval. Your code is being executed as fast as the loop can execute, which is not usually desirable.

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 ) );
    }
}
醉生梦死 2024-10-26 01:29:08

问题是您在循环的每次迭代中创建一个新的图形对象

将 for 语句移动到 using 语句中,您应该会看到性能的显着提高:

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);
     }
}

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

The problem is you are creating a new graphics object on each iteration of the loop

Move the for statement within the using statement, and you should see a dramatic performance increase:

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);
     }
}

That, and it may also be a good idea to move the Resource file you are loading into a local variable.

动次打次papapa 2024-10-26 01:29:08

双缓冲仅对 Paint 事件启用。您可以使用 CreateGraphics() 直接在屏幕上绘图,g.Clear() 调用非常引人注目,因为它会立即删除绘制的图像。不在 Paint 事件或 OnPaint 方法中绘图几乎总是一个错误。

Double-buffering is only enabled for the Paint event. You are directly drawing to the screen with CreateGraphics(), the g.Clear() call is very noticeable since it instantly erases the drawn image. Not drawing in the Paint event or OnPaint method is almost always a mistake.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文