Reputation: 411
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
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
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