FireMonkey controls do not animate smoothly

后端 未结 1 816
别跟我提以往
别跟我提以往 2021-01-02 09:38

Background

I\'ve created a GUI using some FireMonkey controls.

  • Some controls are animated and their appearance updates automatically.
相关标签:
1条回答
  • 2021-01-02 09:55

    I've created a timer based repaint method as Arnaud Bouchez suggested in the comments above. So far it seems to work.

    Code

    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.
    

    ==

    Usage

    A control can be repainted by calling:

    InvalidateControl(MyControl);
    

    The InvalidateControl() procedure doesn't repaint the control immediately. Instead it adds the control to a list. A global timer later checks the list, calls Repaint() and removes the control from the list. Using this method, a control can be invalidated as needed but will not block other controls from being updated, as rapid Repaint() calls do.

    0 讨论(0)
提交回复
热议问题