在Winforms中创建自定义图形

时间:2012-12-15 11:08:28

标签: c# winforms doublebuffered

我正在尝试为我的应用程序创建一个简单的图表,显示每100毫秒的实时数据。所以我想我可以使用DrawCurve方法绘制图形线,并从以下代码开始:

class BufferedPanel : Panel
{
     public BufferedPanel()
     {
        this.DoubleBuffered = true;         //to avoid flickering of the panel
     }                    
}



class Form2: Form
{
    BufferedPanel panel1 = new BufferedPanel();
    List<Point> graphPoints = new List<System.Drawing.Point>();

    private void Form2_Load(object sender, EventArgs e)
    {
       this.panel1.Paint += new System.Windows.Forms.PaintEventHandler(this.panel1_Paint);
    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        using (Graphics g = e.Graphics)
        {
            Point[] points = graphPoints.ToArray();
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            if (points.Length > 1)
               g.DrawCurve(graphPen, points);
         }
     }

     private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
     {
         graphPoints.Add(new System.Drawing.Point(counter * steps, (int)(float)e.UserState));      //x - regular interval decided by a constant; y - simulated by background worker
         panel1.Refresh();
         counter++;
     }

}

截至目前,我正在从后台工作线程模拟graphPoints的值。我的问题是,当我对我的面板进行双重缓冲时,我无法看到图形线。当我将doublebuffering设置为false时,它运行良好。我是使用Graphics进行绘图的新手。所以我不太清楚它是如何工作的。请帮助我。

此外,当图表线到达面板末尾时,我希望实现AutoScrolling。你能就这个方法提出一个想法吗?

这是我工作图的图像:

enter image description here

1 个答案:

答案 0 :(得分:2)

    using (Graphics g = e.Graphics)

那很糟糕。这会破坏传递给Paint事件处理程序的Graphics对象。当你的事件处理程序返回时,没有什么可以用这个对象完成,它是一个死鹦鹉。所以不要指望之后有什么工作,包括打开双缓冲时需要发生的事情,需要将缓冲区绘制到屏幕上才能看到。

使用使用语句或Dispose()方法有一个简单的规则。如果你创建了一个对象,那么你就拥有了它,你可以将其销毁。放手,你没有创造它。

有些证据表明你的“graphPen”变量也出错了。笔绝对是您在Paint事件处理程序中创建和销毁的对象。不要存储一个只是不必要地占用GDI堆中的空间,不值得创建一个所需的几微秒。你肯定会使用笔的使用语句。

所以快速解决方法是:

    var g = e.Graphics;