FireMonkey控件不能平滑动画
问题说明
背景
我已经使用一些FireMonkey控件创建了一个GUI。
I've created a GUI using some FireMonkey controls.
- 某些控件是动画的,它们的外观会自动更新。
- 某些控件只能更新以响应用户互动(滑块等)。
问题
与用户控件的交互阻止对动画控件的更新,从而导致不连续的动画。
Interaction with the user controls prevents updates to the animated controls, resulting in jerky discontinuous animation.
上述视频中的动画控件由TTimer组件驱动。使用FireMonkey的动画组件时,问题仍然存在。
The animated control in the video above is driven by a TTimer component. The problem persists when using FireMonkey's animation components.
调查
调整时,滑块控制调用Repaint()。平滑调整滑块将生成一个浓密的Repaint()调用流,阻止其他控件的更新。
The slider controls call Repaint() when adjusted. Smoothly adjusting a slider will generate a dense stream of Repaint() calls which block other controls from being updated.
应该怎么做?
一个控件不断更新时冻结动画是不适合我的申请。我的第一个想法是交换Repaint()调用类似于VCL Invalidate()方法的东西,但是FireMonkey没有任何可比的AFAIK。
Freezing animations while one control is continuously updated is not appropriate for my application. My first thought is to swap the Repaint() calls for something similar to the VCL Invalidate() method, but FireMonkey doesn't have anything comparable AFAIK.
这个问题有很好的解决方法吗?
Is there a good workaround for this problem?
正确答案
我已经创建了一个基于定时器的重绘方法,如Arnaud Bouchez在上述评论中所建议的。到目前为止,它似乎工作。
I've created a timer based repaint method as Arnaud Bouchez suggested in the comments above. So far it seems to work.
代码
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);
InvalidateControl()过程不会立即重新绘制控件。而是将控件添加到列表中。全局计时器稍后检查列表,调用Repaint()并从列表中删除控件。使用此方法,控件可以根据需要进行无效,但不会阻止其他控件更新,因为快速Repaint()调用。
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.
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /reply/detail/tanhcfkjhb
-
YouTube API 不能在 iOS (iPhone/iPad) 工作,但在桌面浏览器工作正常?
it1352 07-30 -
iPhone,一张图像叠加到另一张图像上以创建要保存的新图像?(水印)
it1352 07-17 -
保持在后台运行的 iPhone 应用程序完全可操作
it1352 07-25 -
使用 iPhone 进行移动设备管理
it1352 07-23 -
在android同时打开手电筒和前置摄像头
it1352 09-28 -
扫描 NFC 标签时是否可以启动应用程序?
it1352 08-02 -
检查邮件是否发送成功
it1352 07-25 -
Android微调工具-删除当前选择
it1352 06-20 -
希伯来语的空格句子标记化错误
it1352 06-22 -
Android App 和三星 Galaxy S4 不兼容
it1352 07-20