【问题标题】:Why TButton.enable does not produce the expected result in this case?为什么在这种情况下 TButton.enable 不会产生预期的结果?
【发布时间】:2013-07-04 04:26:54
【问题描述】:

在 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;

我希望 Button4 在进入“for”循环所代表的繁忙操作之前会变灰。尽管如此,事实并非如此。

在 OnClick 处理程序执行结束时,按钮“似乎没有反应”到 Button4.Enabled:= false。为什么?

我该如何解决它?

这在 VCL 中工作得很好。

谢谢。

【问题讨论】:

  • MainThread 仅用于 UI 任务,不适用于长时间运行的计算任务。这必须在后台任务中完成。在后台任务完成后禁用后台任务启动按钮并启用它

标签: delphi firemonkey delphi-xe3


【解决方案1】:

它没有反应,因为反应仅在按钮重新绘制自身时可见。这只发生在处理下一条 wm_Paint 消息时,但您的代码不处理消息,因此按钮,实际上是整个表单,在该循环期间保持不变。

立即解决方法是调用Button4.Repaint,这将允许按钮更新其外观。不过,这并不能处理所有消息。

一个糟糕的解决方法是偶尔在你的循环中调用Application.ProcessMessages,但需要调用这通常表明你做错了。

最后,最好的解决办法是将长时间运行的任务移到另一个线程中。启动任务时禁用该按钮,并在任务完成时启用它。

【讨论】:

  • Rob,FMX 控件没有更新方法吗?
  • 你是在问我还是告诉我,@Jason?火猴好像没有这种方法。不过,还有 Repaint,它也可以在 VCL 中使用。它是更新的同义词。
  • 好吧,我找不到一个 - 更新方法 - 所以只是把它放在那里而不做一揽子声明,以防我错了。 FWIW,我刚刚使用 Repaint 进行了测试,但它对我不起作用 - 而 Application.ProcessMessages 可以,因此对于 FMX 相关控件可能会稍微复杂一些。
  • 调用“Button4.Repaint”没有任何区别。这是我尝试的第一件事,但我在发布问题时忘记提及它。对此感到抱歉。 Application.ProcessMessages 解决了这个问题,但我也不喜欢它。我将尝试使用多线程。谢谢大家。
猜你喜欢
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多