为什么在这种情况下TButton.enable没有产生预期的结果?

3
以下内容出现在一个FireMonkey(Delphi XE3)应用程序中。请看下面的代码(这只是一个虚拟示例,以说明问题):
procedure TForm1.Button4Click(Sender: TObject);
var
    i: Integer;
begin
    Button4.Enabled:= false; //This should gray-out the button

    // get busy for some time
    for I := 0 to 100000000000 do
    begin

    end;

    Button4.Enabled:= true;
end;

我希望在进入由“for”循环表示的繁忙操作之前,按钮4会变灰。然而,它没有变灰。
在OnClick处理程序执行结束时,该按钮不“似乎有反应”Button4.Enabled:= false。为什么?
我该怎么解决这个问题?
在VCL中,这个方法完全可行。
谢谢。

MainThread 仅用于 UI 任务,而不是长时间运行的计算任务。这必须在后台任务中完成。在后台任务开始时禁用按钮,并在后台任务完成时启用它。 - Sir Rufo
1个回答

6
它没有反应是因为当按钮重新绘制时才会显示反应。只有在处理下一个wm_Paint消息时才会发生这种情况,但您的代码没有处理消息,因此整个窗体,包括按钮,保持不变,直到该循环结束。
立即解决方法是调用Button4.Repaint,它将允许按钮更新其外观。但这并不能处理所有消息。
一个较差的解决方法是在您的循环中偶尔调用Application.ProcessMessages,但需要调用它通常意味着您正在做一些错误的事情。
最好的解决方法是将耗时的任务移动到另一个线程中。在开始任务时禁用按钮,并在任务完成后启用按钮。

Rob,FMX控件没有Update方法吗? - Jason
你是在问我还是告诉我,@Jason?在Fire Monkey中似乎没有这样的方法。不过有一个名为Repaint的方法,在VCL中也可以使用。它是Update的同义词。 - Rob Kennedy
好的,我找不到一个“Update”方法,所以我只是把它放出来,而不是发表一般性声明,以防我错了。顺便说一句,我刚刚测试了使用Repaint,但它对我没有起作用 - 而Application.ProcessMessages确实起作用,因此对于FMX相关控件可能会稍微复杂一些。 - Jason
调用"Button4.Repaint"没有任何影响。这是我尝试的第一件事情之一,当我发布问题时忘了提到它。对此感到抱歉。Application.ProcessMessages可以解决问题,但我也不喜欢它。我会尝试使用多线程。谢谢大家。 - YAA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接