Reputation: 137
I want to make a program wait a few seconds twice in one if
statement. But my problem is that it skips the second Sleep
command? I have searched for an answer but no one else seems to have this?
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if Form1.shapeGreen.Brush.Color=clLime then
begin
Sleep(4000);
Form1.shapeRed.Brush.Color:=clMaroon ;
Form1.shapeYellow.Brush.Color:=clYellow;
Form1.shapeGreen.Brush.Color:=clGreen;
Sleep(3000); (it skips this (waits 0...))
Form1.shapeRed.Brush.Color:=clRed ;
Form1.shapeYellow.Brush.Color:=clOlive;
Form1.shapeGreen.Brush.Color:=clGreen;
end;
end;
Upvotes: 3
Views: 288
Reputation: 34899
The program flow is event driven. Breaking the flow with Sleep()
calls will turn your application non-responsive. In your case it will prevent updating colors in the first step. Hence it will look like it is skipping the last Sleep()
call.
Use a Timer
and a state variable to change your colors at given intervals instead.
Type
TMyState = (msActivate,msFirstStep,msSecondStep);
Tform1 = class(TForm)
...
private
fMyCounter: Integer;
fMyState : TMyState;
end;
// Timer1 is a TTimer with interval 1000 ms,
// initially disabled
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Inc(fMyCounter);
case fMyState of
msActivate:
begin
fMyCounter := 0;
fMyState := msFirstState;
end;
msFirstState:
if (fMyCounter = 4) then
begin
ShapeRed.Brush.Color := clMaroon;
ShapeYellow.Brush.Color := clYellow;
ShapeGreen.Brush.Color := clGreen;
fMyState := msSecondState;
fMyCounter := 0;
end;
msSecondState:
if (fMyCounter = 3) then
begin
ShapeRed.Brush.Color := clRed;
ShapeYellow.Brush.Color := clOlive;
ShapeGreen.Brush.Color := clGreen;
Timer1.Enabled := False;
end;
end;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if shapeGreen.Brush.Color=clLime then
begin
fMyState := msActivate;
Timer1.Enabled := True; // Trigger color change states
end;
end;
Upvotes: 2
Reputation: 43649
The second Sleep
is not skipped; you wil see that you are unable to move your Form for 7 seconds.
With Sleep
you make the application unresponsive in such way that it does not get time to update itself. Setting the color of a shape requests the parenting window to paint the shape again (with the new color settings), but these paint-requests are not handled, because you pause the application. Both color changes áre handled, but both paint-requests are packed into one, leaving only the latter to last.
An easy way is to update the Form yourself in between:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if ShapeGreen.Brush.Color = clLime then
begin
Sleep(4000);
ShapeRed.Brush.Color := clMaroon;
ShapeYellow.Brush.Color := clYellow;
ShapeGreen.Brush.Color := clGreen;
Update;
Sleep(3000);
ShapeRed.Brush.Color := clRed;
ShapeYellow.Brush.Color := clOlive;
ShapeGreen.Brush.Color := clGreen;
end;
end;
But this still makes your application freeze twice. (Note that you cannot do anything in the application during the pauses). A better solution is to make use of a Timer
to eliminate the use of Sleep
all together:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if ShapeGreen.Brush.Color = clLime then
begin
Timer1.Interval := 4000;
Timer1.Enabled := True;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if ShapeGreen.Brush.Color = clLime then
begin
ShapeRed.Brush.Color := clMaroon;
ShapeYellow.Brush.Color := clYellow;
ShapeGreen.Brush.Color := clGreen;
Timer1.Interval := 3000;
end
else
begin
ShapeRed.Brush.Color := clRed;
ShapeYellow.Brush.Color := clOlive;
Timer1.Enabled := False;
end;
end;
Next step is to make the logic in this code more rubust, for example with (a) variable(s) to decide which colors and intervals should be set.
Upvotes: 7