没有在OnPaint()中绘图时双缓冲:为什么它不起作用?

时间:2010-06-24 19:18:03

标签: c# .net winforms gdi+

我正在使用C#/ .Net中的简单矢量绘图应用程序。绘图是在一个面板中完成的,但是我并没有对所有这些事件使用OnPaint()事件 - 实际上OnPaint()甚至只调用另一个实际绘制文档中所有内容的方法。

我尝试添加双缓冲,但是当我将DoubleBuffered设置为true时,闪烁问题更加严重。为什么是这样?如果我想双重缓冲控件,我是否必须使用提供的Graphics对象在OnPaint()事件中完成所有绘图,而不是使用Panel.CreateGraphics()然后绘制到那个?

编辑:这是我正在使用的基本代码。

private void doc_Paint(object sender, PaintEventArgs e)
{
    g = doc.CreateGraphics();
    Render(ScaleFactor, Offset);
}    

private void Render(float ScaleFactor, PointF offset)
{
    foreach (Line X in Document.Lines) { DrawLine(X.PointA, X.PointB, X.Color, X.LineWidth); }
}
private void DrawLine(PointF A, PointF B, Color Color, float Width)
{
    Pen p = new Pen(Color, Width);
    PointF PA = new PointF(((A.X + Offset.X) * ScaleFactor), ((A.Y + Offset.Y) * ScaleFactor));
    PointF PB = new PointF(((B.X + Offset.X) * ScaleFactor), ((B.Y + Offset.Y) * ScaleFactor));
    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    g.DrawLine(p, PA, PB);
}

一般的想法是两个变量ScaleFactor和Offset指的是UI中的缩放级别和平移级别。 g是一个Graphics对象。

2 个答案:

答案 0 :(得分:28)

g = doc.CreateGraphics();

这是错误的。双缓冲只有在您进入缓冲区时才能工作。 e.Graphics引用的那个。修正:

g = e.Graphics;

请注意Panel默认情况下没有启用双缓冲。你需要派生出自己的。将其粘贴到一个新类中:

using System;
using System.Windows.Forms;

class BufferedPanel : Panel {
    public BufferedPanel() {
        this.DoubleBuffered = true;
        this.ResizeRedraw = true;
    }
}

编译。将其从工具箱顶部删除。

答案 1 :(得分:1)

就个人而言,我不打扰DoubleBuffered设置。我只是将所有内容绘制成一个位图,然后在paint事件中在屏幕上绘制该位图。

Bitmap BackBuffer;

private void MainFormSplitContainerPanel1Paint(object sender, PaintEventArgs e)
{
    e.Graphics.Clear(MainFormSplitContainer.Panel1.BackColor);
    if (BackBuffer != null)
        e.Graphics.DrawImage(BackBuffer, positionX, positionY, SizeX, SizeY);
}