强制表格重新绘制?

27
在C# WinForms中,我正在实时绘制一条基于每500毫秒通过串口接收到的数据的线图。 e.Graphics.DrawLine逻辑在表单的OnPaint处理程序中。
一旦我从串口接收到数据,我需要调用某些东西来导致表单重新绘制,以便调用OnPaint处理程序。我尝试了this.Refresh和this.Invalidate,但会导致在表单上先前绘制的任何内容丢失。
是否有其他方法可以实现这一点,而不会失去已在表单上绘制的内容?
5个回答

29

重点是要考虑将绘图数据存储在某个地方。如先前所述,缓冲位图是一种解决方案。但是,如果您没有太多要绘制的内容,有时将绘图数据存储在变量或数组中,并在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);
}

这种方法对于大约10万个点的图形处理速度非常快,并且使用的内存比缓冲位图解决方案要少得多。但是,根据绘图的复杂性,您应该决定使用哪种方式。


谢谢 - 运行良好。快速问题 - 我正在实时绘制这条线图 - 最终我将超过屏幕上可用的最大宽度,因此我希望已在表单上绘制的线条向左移动一点,为正在绘制的新坐标腾出空间。有什么建议吗?基本上我正在开发一个简单的心电图类型应用程序。 - Chris
2
有很多方法可以做到这一点。例如,你可以使用e.Graphics.TranslateTransform(-x, 0);这将使所有的图形被向左平移x个像素绘制出来。 - Zenya

7

正如rerun所说,您需要缓冲您的表单(因为似乎您在绘制后丢弃了数据)。

基本上我会这样做:

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);
    }
}

话虽如此,您可能想要缓存数据以便在表单大小更改时更改缓冲区的大小,然后在其上重绘旧数据。


4
解决方案可能是 this.Invalidate()

0

处理这个问题的默认方式是创建一个内存位图并在其上绘制,然后将图片框的图像属性设置为内存位图。


0

你需要将历史数据存储在某个地方,然后重新绘制它。

这比缓存和剪切位图要容易得多。


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