在C#WinForms中 - 我正在绘制一个实时的折线图,它基于每500毫秒通过串口接收的数据。
e.Graphics.DrawLine逻辑位于表单的OnPaint处理程序中。
一旦我从串口收到数据,我需要调用一些导致表单重绘的东西,以便调用OnPaint处理程序。我试过这个.Refresh和this.Invalidate,会发生的事情是我丢失了以前在表单上绘制的内容。
有没有其他方法可以实现这一目标而不会丢失表格中的内容?
答案 0 :(得分:22)
重点是你应该考虑将绘图数据存储在某个地方。如前所述,缓冲位图是一种解决方案。但是,如果您没有太多绘图,有时将绘图数据存储在变量或数组中并重绘OnPaint事件中的所有内容会更容易也更好。
假设您收到了一些应添加到图表中的点数据。你们所有人都创造了一个点列表:
List<Point> points = new List<Point>();
然后,每次获得新点时,都会将其添加到列表中并刷新表单:
points.Add(newPoint);
this.Refresh();
在OnPaint事件中输入以下代码:
private void Form_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLines(Pens.Red, points);
}
这种工作速度非常快,达到了100 000点,并且使用的内存比缓冲区位图解决方案少得多。但是你应该根据绘图的复杂性决定使用哪种方式。
答案 1 :(得分:7)
正如重新运行所说,您需要缓冲表单(因为您在绘制数据后似乎丢弃了数据)。
这基本上就是我这样做的方式:
private Bitmap buffer;
// When drawing the data:
if (this.buffer == null)
{
this.buffer = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
}
// then draw on buffer
// then refresh the form
this.Refresh();
protected override void OnPaint(PaintEventArgs e)
{
if (this.buffer != null)
{
e.Graphics.DrawImage(this.buffer);
}
}
也就是说,您可能希望缓存数据,以便在表单大小更改时更改缓冲区的大小,然后重新绘制其中的旧数据。
答案 2 :(得分:1)
解决方案可能是this.Invalidate()
答案 3 :(得分:0)
处理此问题的默认方法是创建一个内存位图并在其上绘制,然后将图片框的图像属性设置为内存位图。
答案 4 :(得分:0)
您需要在某处存储历史数据并重新绘制它。
这比缓存和剪辑位图要容易得多。