Принудительно перерисовывать форму?

В C # WinForms - я рисую линейную диаграмму в реальном времени, основанную на данных, получаемых через последовательный порт каждые 500 мс.

Логика e.Graphics.DrawLine находится в обработчике OnPaint формы.

Как только я получаю данные из последовательного порта, мне нужно вызвать что-то, что заставляет форму перерисовываться, чтобы вызвать обработчик OnPaint. Я пробовал this.Refresh и this.Invalidate, и в результате я теряю все, что было нарисовано ранее в форме.

Есть ли другой способ добиться этого без потери того, что было нарисовано в вашей форме?

24
задан Erik Godard 5 August 2017 в 19:50
поделиться

4 ответа

Суть в том, что вы должны подумать о том, чтобы где-то хранить данные для рисования. Как уже было сказано, буферный битмап - это решение. Однако, если вам не нужно рисовать слишком много, иногда проще и лучше хранить данные рисунка в переменной или массиве и перерисовывать все в событии 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 точек и использует гораздо меньше памяти, чем буферное растровое решение. Но вы должны решить, какой способ использовать в зависимости от сложности рисования.

23
ответ дан 29 November 2019 в 00:01
поделиться

Как было сказано в повторном запуске, вам необходимо буферизовать вашу форму (поскольку кажется, что вы отбрасываете данные после того, как нарисовали ее).

Я бы сделал это в основном следующим образом:

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

Тем не менее, вы, вероятно, захотите кэшировать свои данные, чтобы вы могли изменить размер буфера при изменении размера формы, а затем перерисовать в нем старые данные.

7
ответ дан 29 November 2019 в 00:01
поделиться

по умолчанию способ справиться с этим - создать растровое изображение памяти и нарисовать его, а затем установить для свойства изображения графического блока значение растровое изображение памяти.

0
ответ дан 29 November 2019 в 00:01
поделиться

Вам нужно будет где-то хранить исторические данные и просто перерисовывать их.

Это будет намного проще, чем, скажем, кэшировать и обрезать растровые изображения.

0
ответ дан 29 November 2019 в 00:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: