强制表格重绘?

Chr*_*ris 24 c# winforms

在C#WinForms中 - 我正在绘制一个实时的折线图,它基于每500毫秒通过串口接收的数据.

e.Graphics.DrawLine逻辑位于表单的OnPaint处理程序中.

一旦我从串口接收数据,我需要调用导致表单重绘的东西,以便调用OnPaint处理程序.我试过这个.Refresh和this.Invalidate,会发生什么,我失去了之前在表单上绘制的内容.

还有另一种方法可以实现这一目标,而不会丢失表格中的内容吗?

Zen*_*nya 23

关键是你应该考虑将绘图数据存储在某个地方.如前所述,缓冲位图是一种解决方案.但是,如果您没有太多绘制,有时将绘图数据存储在变量或数组中并重绘OnPaint事件中的所有内容会更容易和更好.

假设您收到一些应添加到图表中的点数据.你们所有人都创造了一个点列表:

List<Point> points = new List<Point>();
Run Code Online (Sandbox Code Playgroud)

然后,每次获得新点时,将其添加到列表中并刷新表单:

points.Add(newPoint);
this.Refresh();
Run Code Online (Sandbox Code Playgroud)

在OnPaint事件中输入以下代码:

private void Form_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawLines(Pens.Red, points);
}
Run Code Online (Sandbox Code Playgroud)

这种工作速度相当快,达到100 000点并且使用的内存比缓冲位图解决方案少得多.但是你应该根据绘图的复杂性决定使用哪种方式.

  • 有很多方法可以做到这一点.例如,您可以使用e.Graphics.TranslateTransform(-x,0); 这会使您绘制的所有图形向左移动x像素. (2认同)

Zac*_*son 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

也就是说,您可能希望缓存数据,以便在表单大小更改时更改缓冲区的大小,然后重新绘制其上的旧数据.