문제

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;
도움이 되었습니까?

해결책

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.

다른 팁

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;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top