В C # WinForms - я рисую линейную диаграмму в реальном времени, основанную на данных, получаемых через последовательный порт каждые 500 мс.
Логика e.Graphics.DrawLine находится в обработчике OnPaint формы.
Как только я получаю данные из последовательного порта, мне нужно вызвать что-то, что заставляет форму перерисовываться, чтобы вызвать обработчик OnPaint. Я пробовал this.Refresh и this.Invalidate, и в результате я теряю все, что было нарисовано ранее в форме.
Есть ли другой способ добиться этого без потери того, что было нарисовано в вашей форме?
Суть в том, что вы должны подумать о том, чтобы где-то хранить данные для рисования. Как уже было сказано, буферный битмап - это решение. Однако, если вам не нужно рисовать слишком много, иногда проще и лучше хранить данные рисунка в переменной или массиве и перерисовывать все в событии 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 точек и использует гораздо меньше памяти, чем буферное растровое решение. Но вы должны решить, какой способ использовать в зависимости от сложности рисования.
Как было сказано в повторном запуске, вам необходимо буферизовать вашу форму (поскольку кажется, что вы отбрасываете данные после того, как нарисовали ее).
Я бы сделал это в основном следующим образом:
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);
}
}
Тем не менее, вы, вероятно, захотите кэшировать свои данные, чтобы вы могли изменить размер буфера при изменении размера формы, а затем перерисовать в нем старые данные.
по умолчанию способ справиться с этим - создать растровое изображение памяти и нарисовать его, а затем установить для свойства изображения графического блока значение растровое изображение памяти.
Вам нужно будет где-то хранить исторические данные и просто перерисовывать их.
Это будет намного проще, чем, скажем, кэшировать и обрезать растровые изображения.