我该如何在面板上绘图而不出现闪烁?

3
这是我的代码。当我将光标移动到表单上时,它可以工作,圆圈在移动,但是会闪烁。我该如何解决这个问题?
public partial class Preprocesor : Form
{
    int x, y;
    Graphics g;

    public Preprocesor()
    {
        InitializeComponent();
    }

    private void Preprocesor_Load(object sender, EventArgs e)
    {
        g = pnlMesh.CreateGraphics();
    }

    private void pnlMesh_Paint(object sender, PaintEventArgs e)
    {
        g.Clear(Color.White);
        g.FillEllipse(Brushes.Black, x, y, 10, 10);
    }

    private void pnlMesh_MouseMove(object sender, MouseEventArgs e)
    {
        x = e.X;
        y = e.Y;
        pnlMesh.Invalidate();
    }
}

为什么你需要在这里创建 Graphics?PaintEventArgs 已经提供了一个 graphics 方法。 - Rye
2个回答

5
您需要在双缓冲控件上进行绘制。
创建一个继承自Control的类,并在构造函数中设置DoubleBuffered = true;(这是一个受保护的属性)。使用该控件代替您的面板,这样就不会出现闪烁。
此外,您不应该为以后存储Graphics对象。相反,您应该在Paint处理程序中绘制e.Graphics

谢谢。那个有效 :). 除了我制作了继承“Panel”的控件。 - Ichibann
@Ichibann:除非您还在其中放置控件,否则不应使用面板;它只会增加开销。 - SLaks
+1 只有一个小评论 - 在使用双缓冲之前,我每次都会处理e.Graphics对象,这没有引起任何问题,但是设置了双缓冲为真后,它导致什么都没有绘制。移除处理操作后一切正常运行。 - Shadow The Spring Wizard
@ShadowWizard:除非文档告诉你这样做,否则你不应该处理属于其他人的对象。 - SLaks
@SLaks,写原始代码时我不知道这一点,直到你说了才确定,一直担心在幕后返回需要处理的新图形对象。也许是因为我的SharePoint背景 - 无论如何,感谢你的澄清。 - Shadow The Spring Wizard
这是一个新的图形对象,但它由Windows拥有和处理。 - SLaks

4

您可以尝试重写面板用户控件并将 Doublebuffered 属性设置为 true。

public partial class BufferPanel : Panel
{
    public BufferPanel()
    {
        SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        UpdateStyles();
    }
}

它是BufferPanel类,但具有TransparentPanel构造函数:P - Ichibann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接