Question

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;
Was it helpful?

Solution

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.

OTHER TIPS

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;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top