0

My Application is recieving data from external hardware and plots it onto a panel (can be actually any other child of "Control"). The painting currently happens in a "OnPaint" callback. A List is used to store the recently recieved data to allow to redraw the whole graph in OnPaint to get the proportions right if e.g. the window gets resized.

The graph itself is drawn with the e->Graphics element using lines between two data points.

This is working fine, but when I have new data coming in every 50 ms (= repaint the whole graph), the graph soon begins to flicker. The flickering gets stronger the more data needs to be plotted (when the right side of the control is reached, the data cache gets cleared, so there is a finite max number of data points in the graph).

The main part of my code:

void Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e)
{
    Size^ s = m_Control->Size;
    Bitmap^ bmp = gcnew Bitmap(s->Width, s->Height);
    Graphics^ g = Graphics::FromImage(bmp);

    for each(double y in m_Data)
    {
        /* ...calculations etc... */
        g->DrawLine(Pens::Blue, recentX, recentY, currentX, currentY);
    }           

    e->Graphics->DrawImageUnscaled(bmp, 0, 0);
}

Any suggestion how I can optimize the painting to get rid of the flickering? Thanks in advance!

Niko
  • 26,516
  • 9
  • 93
  • 110
  • 2
    In the form constructor, set the this->DoubleBuffered property to true. Easy peasy way. – Hans Passant Apr 08 '12 at 23:53
  • @Hans: Yes, but shouldn't that be set on the Panel instead of the Form? And the existing code is double-buffered already... – Ben Voigt Apr 09 '12 at 00:12
  • Trying to access "DoubleBuffered" on the panel raises an error, not really sure why. @HansPassant Thank you, that made it better but did not resolve the problem. – Niko Apr 09 '12 at 00:37
  • Type "BufferedPanel" in the search box. – Hans Passant Apr 09 '12 at 07:15
  • @HansPassant Wow thanks, you're answer on this question http://stackoverflow.com/questions/7569471/double-buffering-with-panel worked a treat for me! – Niko Apr 09 '12 at 10:00

2 Answers2

1

Speaking independengly from your platform or language, this is kind of problems solved mostly using a method called governing the frame rate.

You will call your paint method, then estimate how much time spent on painting. Now you know how much time spent during a step and how long your refreshment intervals are - in your case it's 40 ms -. You can sleep the thread for (intervals - timespent) milliseconds.

By the way, it is my first answer and I know I am terrible at explaining stuff.

M M Enanc
  • 11
  • 3
1

The flickering comes from WinForms erasing the background before calling your Paint handler.

You need to write your own custom control inheriting from Panel, and override OnPaintBackground to do nothing (especially, do not call the base class version).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Thanks, this is working pretty good. But when the form gets resized, strange things happen because the background gets no longer repainted. Any idea how I can resolve that issue? – Niko Apr 09 '12 at 00:42
  • @Niko: From the code you provided, you're creating a Bitmap the size of the control, and copying it to the control as the last step. So any garbage you're seeing is coming from that bitmap. Or are you saying the form background itself isn't painting? I just suggested short-circuiting `OnEraseBackground` on the Panel, not the whole Form. – Ben Voigt Apr 09 '12 at 00:53
  • Great, thank you! Filling the bitmap's background with white color resolved that garbage problem. – Niko Apr 09 '12 at 01:01