在 Delphi 多设备应用程序中为我的例程添加延迟或睡眠

Adding a delay or sleep to my routine in a Delphi Multi-device application

使用 Dephi XE-7 和 FMX(多设备应用程序)- 当前在 Win32 中编译

我正在使用 Raize Radiant Shapes 并尝试创建一个演示,我可以在其中遍历所有 RadiantCircles 并更改它们的描边和填充颜色。我的屏幕上垂直排列了四个 RadiantCircles。下面的代码有效,但速度很快。如何在每次迭代后添加 "delay"、"sleep"、"etc" 以减慢速度。似乎 AnimateColor 影响了我的延迟。

var
 I: integer;
 fillColor: Cardinal;


for I := 0 to ScaledLayout2.ControlsCount-1 do
 if ScaledLayout2.Controls[I] is TRadiantCircle then
 begin
   TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Stroke.Color', 4294967040, 1); //yellow
   case  TRadiantCircle(ScaledLayout2.Controls[I]).Tag of
    1: fillColor:= 4278190335; //Blue
    2: fillColor:= 4281519410; //Lime Green
    3: fillColor:= 4294901760; //Red
    4: fillColor:= 4293821166; //Dark Violet
   end;
   TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Fill.Color', fillColor, 1);
   TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Stroke.Color', 4278190080, 1); //black
   case TRadiantCircle(ScaledLayout2.Controls[I]).Tag of
    1: fillColor:= 4278190219; //Dark Blue
    2: fillColor:= 4278215680; //Dark Green
    3: fillColor:= 4287299584; //Dark Red
    4: fillColor:= 4286578816; //Purple
   end;
   TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Fill.Color', fillColor, 1);
  sleep(1000);
 end;

我尝试在每次迭代结束后放置一个 sleep(1000),但它不起作用。我看不到任何动画。睡眠是多设备应用程序的当前功能吗?

您在评论中提到您一直在考虑为此使用计时器,但不知道如何去做。

简而言之,将更新代码(循环内的代码)移动到接受索引作为参数的单独过程中。 然后在计时器 OnTimer 事件中,您需要注意增加该索引并执行您的方法,如下所示:

procedure TMyForm.MyAnimation(I: Integer);
begin
  if ScaledLayout2.Controls[I] is TRadiantCircle then
  begin
    TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Stroke.Color', 4294967040, 1); //yellow
    case  TRadiantCircle(ScaledLayout2.Controls[I]).Tag of
      1: fillColor:= 4278190335; //Blue
      2: fillColor:= 4281519410; //Lime Green
      3: fillColor:= 4294901760; //Red
      4: fillColor:= 4293821166; //Dark Violet
    end;
    TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Fill.Color', fillColor, 1);
    TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Stroke.Color', 4278190080, 1); //black
    case TRadiantCircle(ScaledLayout2.Controls[I]).Tag of
      1: fillColor:= 4278190219; //Dark Blue
      2: fillColor:= 4278215680; //Dark Green
      3: fillColor:= 4287299584; //Dark Red
      4: fillColor:= 4286578816; //Purple
    end;
    TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Fill.Color', fillColor, 1);
  end;
end;

procedure TMyForm.Timer1Timer(Sender: TObject);
begin
  //Check to see if we already reached end of animation
  if ComponentIndex > AnimationLength do
  begin
    //Reset component index back to 0 so we can repeat hte animation if required
    ComponentIndex  := 0;
    //Disable the timer
    Timer1.Enabled := False;
  end
  //if not continue with animation
  else
  begin
    //Execute MyAnimation for specific component defined by its index
    MyAnimation(ComponentIndex );
    //Increase the ComponentIndex by one which means that next time the Timer fires we advance with our animation
    ComponentIndex := ComponentIndex +;
end;

所以你基本上是通过启用定时器来启动这个动画,一旦动画结束它就会禁用定时器并将 I 设置为 0 所以它基本上会重置到初始位置。

如果您需要多个并发动画,您将需要多个计时器,因此在需要时在运行时创建它们然后在动画结束时最终销毁它们可能不是一个坏主意。

您还可以查看下一个 link,了解如何在 Delphi 中控制各种动画的其他想法: http://docwiki.embarcadero.com/CodeExamples/XE7/en/FMXTimerAnimation_(Delphi)

编辑:至于为什么使用睡眠不起作用的解释: 当您在代码中使用 Sleep 命令时,它所做的是暂停执行您指定的特定毫秒数的调用它的线程。

因此,当您从用于 UI 更新的主线程中调用 Sleep 时,您实际上会在特定时间停止 UI 更新,因此阻止您的程序更新 UI 到当前状态。

这就是为什么您的动画似乎没有发生但您立即得到最终结果的原因。

现在,为了使其按您希望的方式工作,您必须强制程序 UI 在调用 Sleep 之前自行更新。

您可以通过调用 Application.ProcessMessages 来实现这一点,但我不建议这样做,因为它会带来很多其他问题。