Delphi TAction.OnUpdate事件是否会降低性能?
在Delphi XE7中,我使用此技巧根据是否选择ListView中的项目自动启用或禁用工具栏按钮(“编辑ListView项目”),以防止用户在没有选择ListView项目的情况下单击按钮:Delphi TAction.OnUpdate事件是否会降低性能?,delphi,delphi-xe7,tlistview,taction,Delphi,Delphi Xe7,Tlistview,Taction,在Delphi XE7中,我使用此技巧根据是否选择ListView中的项目自动启用或禁用工具栏按钮(“编辑ListView项目”),以防止用户在没有选择ListView项目的情况下单击按钮: 在VCL表格上放一个战术专家 在操作列表中创建操作actTest 在表格上按一个T按钮 将动作actTest分配给按钮 在表单上放置一个TListView 在ListView中创建两个项目 在actTest操作写入的OnUpdate事件中: procedure TForm1.actTestUpdate(
- 在VCL表格上放一个战术专家
- 在操作列表中创建操作
李>actTest
- 在表格上按一个T按钮李>
- 将动作
分配给按钮李>actTest
- 在表单上放置一个TListView李>
- 在ListView中创建两个项目李>
- 在
操作写入的actTest
事件中:OnUpdate
procedure TForm1.actTestUpdate(Sender: TObject); begin actTest.Enabled := ListView1.SelCount > 0; CodeSite.Send('actTestUpdate'); // gets fired very often! end;
actTestUpdate
事件是连续且经常触发的,因此语句actTest.Enabled:=ListView1.SelCount>0代码>经常被执行
所以我的问题是:这会降低性能吗?如果是,是否还有其他技巧可以达到上述目的?操作更新事件(主要)在Application.Idle内执行。只要不在事件处理程序中执行时间关键的操作,就不会出现明显的性能下降。通常
是的,事件处理程序需要时间,就像任何其他例程一样。多个处理程序占用该时间的倍数。所有这些代码的总量将评估导致无所事事的条件。从这个意义上讲,您可以得出这样的结论:这种更新机制会降低性能。特别是考虑到这些更新事件经常发生:
在应用程序空闲或操作列表更新时发生
这可能是不使用它的一个理由。但是您应该意识到,对单个表达式的求值通常不会花费那么多时间。另外,要认识到,无论动作更新如何,应用程序都会在每次鼠标移动时执行(更繁重的)计算和操作
当您将操作更新事件中的代码持续时间保持在最小值(例如,不通过数据库连接检查密码)时,性能将正常。如果您有与更新操作相关联的冗长操作,那么在这些特定情况下,您可以求助于手动更新
请注意,不使用操作的单个OnUpdate
事件,而是使用操作列表的事件,可以稍微提高性能,该事件具有Handled
参数以取消进一步的处理,并具有集中和分类的额外好处
明确地
您的ListView1.SelCount
向控件发送一条WinAPI消息以检索选择计数。这是一个很小的手术,我不会打扰它所需要的时间
另一种方法是更新ListView事件中的操作。该事件将捕获由于鼠标和键盘交互而导致的所有选择更改,以及设置单个项目的属性
财产:
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
actTest.Enabled := ListView1.SelCount > 0;
end;
但是,ListView和VCL都不提供仅在SelCount=0
和SelCount>0
之间发送信号的任何内容,因此您将更严格地评估该行代码
假设MultiSelect
为真,您也可以自己计算选择更改,以消除调用SelCount
的需要:
private
FListViewSelected: Longbool;
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
if Selected then
Inc(FListViewSelected)
else
Dec(FListViewSelected);
actTest.Enabled := FListViewSelected;
end;
或所选项目的测试为零:
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
actTest.Enabled := ListView1.Selected <> nil;
end;
如果您有(或计划有)多个操作,您可能希望将Application.ActionUpdateDisplay设置为例如50毫秒。这可以提高性能
同样,如果您有许多操作,我建议您尝试使用TForm.UpdateActions,而不是为每个操作定义TAction.OnUpdate。这将使代码更具可读性。更新的traction.OnUpdate
目的是做你正在做的事情,看看你是按照预期做的。但是,这是不必要的资源浪费。更糟糕的是,可能有一些情况需要在方法执行过程中禁用某个动作,并且使用<代码> OnUpvest方法可能导致不安全地延迟。我试图完全避免个人更新。@TLama您建议哪种选择?我会在发生事情时立即更新操作状态。在这种情况下,当列表视图的基础模型选择发生更改时。@TLama您会怎么做?我都试过了。记住,目标是独立于使用鼠标或键盘选择/取消选择项目来更新按钮。这与时间关键性无关(事情本身取决于时间花费),而是与时间花费/持续时间有关(事情本身对未来的事情有影响)。NGLN,如果您提供了一个没有缺陷的OnSelectItem
工作示例,我将推荐您参加下一届诺贝尔奖。我已经试过了…@user你了解OnIdle吗,当它启动时,为什么会影响OnUpdate?是的,这就是问题所在,不过我会选择更高的值。
procedure TForm1.ActionList1Update(Action: TBasicAction; var Handled: Boolean);
begin
actTest.Enabled := ListView1.Selected <> nil;
Handled := True;
end;