Nil
Nil

Reputation: 411

PictureBox Refresh causes layers above to flicker

I am trying to read data from ports and show that on a dial. the background is a PictureBox containing the image of a circular scale giving readings, and a Lineshape has been used to represent the dial. The PictureBox has been 'sent to back' to allow visibility of the Lineshape. I'm enclosing representative codes: if i do this:

    private void timer1_Tick(object sender, EventArgs e)
    {
        ang += 2.0 * Math.PI / 180.0;
        lineShape1.X1 = Convert.ToInt32(lineShape1.X2 - r * Math.Sin(ang));
        lineShape1.Y1 = Convert.ToInt32(lineShape1.Y2 - r * Math.Cos(ang));

    }

then it leaves a trace on the PictureBox.

But if i use the Refresh function of the PictureBox, then the dial appears to flicker. i have tried with timer intervals of 10, 15, 20, 50 and 100, but the problem persists.

    private void timer1_Tick(object sender, EventArgs e)
    {
        ang += 2.0 * Math.PI / 180.0;
        lineShape1.X1 = Convert.ToInt32(lineShape1.X2 - r * Math.Sin(ang));
        lineShape1.Y1 = Convert.ToInt32(lineShape1.Y2 - r * Math.Cos(ang));
        pictureBox1.Refresh();
    }

For the sake of the actual problem, it is not possible to increase the interval. What can i do to Show a smooth variation of the dial?

Upvotes: 1

Views: 857

Answers (2)

Larry
Larry

Reputation: 18031

As @Hans Passant suggested, you should not be using a LineShape object. This is a example of code that implement his suggestion (quick, untested):

private void timer1_Tick(object sender, EventArgs e)
{
    pictureBox1.Invalidate();
}

void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    ang += 2.0 * Math.PI / 180.0;
    var X1 = Convert.ToInt32(X2 - r * Math.Sin(ang));
    var Y1 = Convert.ToInt32(Y2 - r * Math.Cos(ang));

    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

    e.Graphics.DrawLine(
        new Pen(Color.Yellow, 1f),
        new Point(X1, Y1), 
        new Point(X2, Y2 ));
}

Also, try to set this.DoubleBuffered = true; to avoid the flickering problem.

Upvotes: 4

fourpastmidnight
fourpastmidnight

Reputation: 4234

GDI+ is known to have this effect, in general. This is why WinForms has generally been replaced with WPF and XAML. I think, IIRC, PictureBox is especially prone to this problem. What you need to do is perform all of your "drawing" on the image in the PictureBox outsde of the PictureBox. Once all of your drawing is complete, update the PictureBox with the new image.

However, if you're drawing new images really quickly and subsequently updating the PictureBox, you're still likely to get flicker. PictureBox was just not designed for this use case. It's designed, more or less, to display a static image (or one that may change occassionally, but not at a high frequency).

Upvotes: 0

Related Questions