VÄLFÄRD VÄLFÄRD - 1 month ago 5
C# Question

Skipping a FillEllipse (C#)

protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
SolidBrush brush = new SolidBrush(Color.Black);
g.FillRectangle(brush, 35, 30, 140, 420);
if (figure.Equals("red"))
{
brush.Color = Color.Red;
g.FillEllipse(brush, 35, 30, 140, 140);
figure = "red";
}
else if (figure.Equals("yellow"))
{
brush.Color = Color.Yellow;
g.FillEllipse(brush, 35, 170, 140, 140);
figure = "yellow";
}
else if (figure.Equals("green"))
{
brush.Color = Color.ForestGreen;
g.FillEllipse(brush, 35, 310, 140, 140);
figure = "green";
}
}


private void Form1_Load(object sender, EventArgs e)
{

}

private void button1_Click(object sender, EventArgs e)
{
if (figure.Equals("red"))
{
System.Threading.Thread.Sleep(750);
figure = "yellow";
Invalidate();
System.Threading.Thread.Sleep(750);
figure = "green";
Invalidate();
}

else if (figure.Equals("green"))
{
System.Threading.Thread.Sleep(750);
figure = "yellow";
Invalidate();
System.Threading.Thread.Sleep(750);
figure = "red";
Invalidate();
}


}


I'm programming a simple traffic signal and thought it would look nicer if you could press the "Switch" button one time and go from red to yellow to green instead of having to press it every time. However, now when I run the program, instead of waiting 0,75 seconds to draw the yellow and then another 0,75 seconds to draw the green, it waits 1,5 seconds and goes from red to green directly, not showing the yellow at all.

Answer

Your problem is explained in the MSDN page on the Invalidate method

Calling the Invalidate method does not force a synchronous paint; to force a synchronous paint, call the Update method after calling the Invalidate method. When this method is called with no parameters, the entire client area is added to the update region.

So you need to add a call to Update after the first Invalidate

if (figure.Equals("red"))
{
    System.Threading.Thread.Sleep(750);
    figure = "yellow";
    Invalidate();
    Update();
    System.Threading.Thread.Sleep(750);
    figure = "green";
    Invalidate();   
}           

else if (figure.Equals("green"))
{
    System.Threading.Thread.Sleep(750);
    figure = "yellow";
    Invalidate();
    Update();
    System.Threading.Thread.Sleep(750);
    figure = "red";
    Invalidate();               
}

There is no need to call Update after the second Invalidate because your event handler exits and thus the system can honor the call to last Invalidate