delphi - FireMonkey 控件的动画效果不流畅

标签 delphi firemonkey

背景

我使用一些 FireMonkey 控件创建了一个 GUI。

  • 某些控件具有动画效果,其外观会自动更新。
  • 某些控件仅根据用户交互( slider 等)进行更新。

问题

与用户控件的交互会阻止动画控件的更新,从而导致动画不连续。

Video of glitchy animation

上面视频中的动画控件由 TTimer 组件驱动。使用 FireMonkey 的动画组件时问题仍然存在。

调查

slider 控件在调整时调用 Repaint()。平滑地调整 slider 将生成密集的 Repaint() 调用流,从而阻止其他控件的更新。

该做什么?

在一个控件不断更新的同时卡住动画不适合我的应用程序。我的第一个想法是将 Repaint() 调用替换为类似于 VCL Invalidate() 方法的方法,但 FireMonkey 没有任何类似的 AFAIK。

这个问题有好的解决办法吗?

最佳答案

我已经按照 Arnaud Bouchez 在上面的评论中建议的那样创建了一个基于计时器的重绘方法。到目前为止它似乎有效。

代码

unit FmxInvalidateHack;

interface

uses
  Fmx.Types;

procedure InvalidateControl(aControl : TControl);


implementation

uses
  Contnrs;

type
  TInvalidator = class
  private
  protected
    Timer : TTimer;
    List  : TObjectList;
    procedure Step(Sender : TObject);
  public
    constructor Create;
    destructor Destroy; override;

    procedure AddToQueue(aControl : TControl);
  end;

var
  GlobalInvalidator : TInvalidator;

procedure InvalidateControl(aControl : TControl);
begin
  if not assigned(GlobalInvalidator) then
  begin
    GlobalInvalidator := TInvalidator.Create;
  end;
  GlobalInvalidator.AddToQueue(aControl);
end;


{ TInvalidator }

constructor TInvalidator.Create;
const
  FrameRate = 30;
begin
  List  := TObjectList.Create;
  List.OwnsObjects := false;

  Timer := TTimer.Create(nil);
  Timer.OnTimer  := Step;
  Timer.Interval := round(1000 / FrameRate);
  Timer.Enabled  := true;
end;

destructor TInvalidator.Destroy;
begin
  Timer.Free;
  List.Free;
  inherited;
end;

procedure TInvalidator.AddToQueue(aControl: TControl);
begin
  if List.IndexOf(aControl) = -1 then
  begin
    List.Add(aControl);
  end;
end;

procedure TInvalidator.Step(Sender: TObject);
var
  c1: Integer;
begin
  for c1 := 0 to List.Count-1 do
  begin
    (List[c1] as TControl).Repaint;
  end;
  List.Clear;
end;


initialization

finalization
  if assigned(GlobalInvalidator) then GlobalInvalidator.Free;

end.

==

使用

可以通过调用重新绘制控件:

InvalidateControl(MyControl);

InvalidateControl() 过程不会立即重新绘制控件。相反,它将控件添加到列表中。全局计时器稍后检查列表,调用 Repaint() 并从列表中删除控件。使用此方法,可以根据需要使控件失效,但不会像快速 Repaint() 调用那样阻止其他控件更新。

关于delphi - FireMonkey 控件的动画效果不流畅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8411143/

相关文章:

android - 单击弹出控件时生成的滑动 Firemonkey Delphi

delphi - Delphi XE6可以为Windows Phone编译吗?

delphi - 通过设置透明颜色来剪切火猴形状的一部分不起作用?

delphi - 如何在 Mac 上的 Lazarus 中执行与 shellexecute() 等效的操作?

sql-server - 为什么 context_info 会失败?

delphi - FireDAC - 在宏扩展后显示 SQL

arrays - 如何在 Delphi 中公开私有(private)静态数组字段的内置枚举器?

delphi - 让 WinInet 与 Internet Explorer 共享 session /cookie

ios - Firemonkey在iOS中不显示希伯来文字

delphi - Firemonkey TListBox.OnClick - 单击了哪个项目?