C# 强制表单重绘?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2376998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Force Form To Redraw?
提问by Chris
In C# WinForms - I am drawing a line chart in real-time that is based on data received via serial port every 500 ms.
在 C# WinForms 中 - 我正在实时绘制一个折线图,该折线图基于每 500 毫秒通过串行端口接收到的数据。
The e.Graphics.DrawLine logic is within the form's OnPaint handler.
e.Graphics.DrawLine 逻辑位于表单的 OnPaint 处理程序中。
Once I receive the data from the serial port, I need to call something that causes the form to redraw so that the OnPaint handler is invoked. I have tried this.Refresh and this.Invalidate, and what happens is that I lose whatever had been drawn previously on the form.
一旦我从串行端口接收到数据,我需要调用一些导致表单重绘的东西,以便调用 OnPaint 处理程序。我已经尝试过 this.Refresh 和 this.Invalidate,结果是我丢失了之前在表单上绘制的任何内容。
Is there another way to achieve this without losing what has been drawn on your form?
有没有另一种方法可以在不丢失表单上绘制的内容的情况下实现这一目标?
采纳答案by Zenya
The point is that you should think about storing your drawing data somewhere. As already said, a buffer bitmap is a solution. However, if you have not too much to draw, sometimes it is easier and better to store your drawing data in a variable or an array and redraw everything in the OnPaint event.
关键是您应该考虑将绘图数据存储在某处。如前所述,缓冲区位图是一种解决方案。但是,如果您没有太多要绘制的内容,有时将绘制数据存储在变量或数组中并在 OnPaint 事件中重绘所有内容会更容易也更好。
Suppose you receive some point data that should be added to the chart. Firs of all you create a point List:
假设您收到一些应添加到图表中的点数据。首先创建一个点列表:
List<Point> points = new List<Point>();
Then each time you get a new point you add it to the list and refresh the form:
然后每次获得新点时,将其添加到列表中并刷新表单:
points.Add(newPoint);
this.Refresh();
In the OnPaint event put the following code:
在 OnPaint 事件中放入以下代码:
private void Form_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLines(Pens.Red, points);
}
This works quite fast up to somehow 100 000 points and uses much less memory than the buffer bitmap solution. But you should decide which way to use according to the drawing complexity.
与缓冲区位图解决方案相比,这在某种程度上可以快速运行到 100 000 点,并且使用的内存要少得多。但是你应该根据绘图的复杂程度来决定使用哪种方式。
回答by rerun
the default way to handle this is to create a memory bitmap and draw on that then set the image property of the picture box to the memory bitmap.
处理此问题的默认方法是创建一个内存位图并在其上绘制,然后将图片框的图像属性设置为内存位图。
回答by Zach Johnson
As rerun said, you need to buffer your form (since it appears that you are discarding the data after you draw it).
正如重新运行所说,您需要缓冲您的表单(因为看起来您在绘制后丢弃了数据)。
This is basically how I would do it:
这基本上是我将如何做到的:
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);
}
}
That said, you probably want to cache your data so you can change the size of the buffer when the form size changes and then redraw the old data on it.
也就是说,您可能希望缓存数据,以便在表单大小更改时更改缓冲区的大小,然后在其上重绘旧数据。
回答by leppie
You will need to store historical data somewhere and just repaint it.
您需要将历史数据存储在某处并重新绘制它。
That will be much easier than say caching and clipping bitmaps.
这比缓存和剪切位图要容易得多。
回答by edu feliu
The solution may be this.Invalidate()
解决办法可能是 this.Invalidate()