C#.NET ..在Paint事件处理程序之外绘制是不好的做法?

时间:2015-05-28 09:58:16

标签: c# graphics invalidation paintevent

要澄清我的问题我的意思..我在使用.NET框架在C#中制作游戏时使用,实现我自己的DrawScene()方法并在我想重新绘制游戏时调用它图形(基本上在游戏中的任何实例移动或改变其形状/状态之后),如下所示:

private void DrawScene()
{
    Graphics g = this.CreateGraphics();
    g.Clear(Color.Black);

    g.DrawImage(myBitmap, 0, 0);

    g.Dispose();
}

通过这样做,在我的Paint事件处理程序中,我所做的就是以下内容:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    DrawScene();
}

例如,当我想在玩家进行一些移动后重绘时,我只是以同样的方式调用DrawScene():

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Keycode == Keys.Up)
    {
        hero.y -= 5;
    }

    DrawScene();
}

这样做或者这样做是否有任何严重的区别(我注意到大多数人都这样做):

private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.Clear(Color.Black);

    e.Graphics.DrawImage(myBitmap, 0, 0);
}

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Keycode == Keys.Up)
    {
        hero.y -= 5;
    }

    this.Invalidate();
}

很抱歉,如果这话题很多,但我只想澄清一下我的问题..

所以,如果上面两个案例的绘图方式完全相同(从图形角度来看),并且在第一种情况下保持我常规实现没有任何损害..那么什么时候最好使用invalidate()方法?

1 个答案:

答案 0 :(得分:1)

这两种方法严重不同(第二种方法是首选)。

首先 - 在您的方法中,每次需要绘制内容时都会创建新的Graphics对象,而在Paint事件处理程序中,每次都使用相同的图形对象。

这增加了内存使用量(因为重绘可能非常频繁地发生),而且因为你没有处理你正在创建的图形(基本上你应该使用任何实现IDisposable的对象来执行它,你不再需要使用它) - 图形使用的系统资源未被释放。

此外,您的表单可以不通过您的调用手动重绘,但在其他一些情况下(由其他窗口重叠,显示/隐藏等)。如果您的绘画将在Paint处理程序中完成 - 那么它们将自动完成,但在您的“第一”方法中,乳清将不会直到您手动调用绘图方法。

所以基本上总是更好地在Paint事件处理程序中绘制所有内容(并调用Invalidate甚至Refresh以强制重绘),而不是在单独的方法中手动绘制。

有时候(如果您的绘图需要很多代码并且可以逻辑地拆分成部分),最好像处理它一样:

private void DrawScene(Graphics g)
{
    g.Clear(Color.Black);
    g.DrawImage(myBitmap, 0, 0);
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
    DrawScene(e.Graphics);
    DrawSomething(e.Graphics);
}

所以你仍然使用Paint事件处理程序中的grahics对象,但只是将它传递给绘图方法。