0

为了澄清我的问题的意思。我在使用 .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() 方法?

4

1 回答 1

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 对象,但只是将其传递给绘图方法。

于 2015-05-28T10:08:28.323 回答