重い処理の時に再描画するには?

解決


通りすがり  2005-04-14 09:44:40  No: 14300

こんばんは、早速ですが質問させていただきます。
重いというよりかはCPUを占領しているのかもしれませんが、
for文内で、TLabelを再描画しようとしたのですが、うまくいきませんでした。

Formに ボタン、ラベルを貼り付けます。
ボタンの処理を

procedure TForm1.Button1Click(Sender: TObject);
var
i : Integer;
begin

 for i := 0 to 100000 do
 begin
   Label1.Invalidate;
   Label1.Caption := IntToStr(i);
 end;

end;

このようにし、期待していた動作は、Labelのテキストが、増えていく経過が見れるようにしたかったのです。
しかし、結果はしばらく動かなくなり、いきなりLabelに100000と表示されてしまいます。
このような場合に再描画するのにはどうすればいいのでしょうか。
教えていただければ幸いです。


通りすがりV2  2005-04-14 09:53:31  No: 14301

>   Label1.Invalidate;
    Application.ProcessMessages;
>   Label1.Caption := IntToStr(i);


!  2005-04-14 20:13:31  No: 14302

>   Label1.Invalidate;
>   Label1.Caption := IntToStr(i);
    Label1.Update;


BETTER  2005-04-14 20:27:00  No: 14303

Label1.Update;よりも、ループ中にメッセージ処理が可能なApplication.ProcessMessages;の方がベター。


!  2005-04-14 20:54:13  No: 14304

ProcessMessagesとUpdateの違いわかりますか?


傍観者  2005-04-14 21:23:59  No: 14305

Label1.Update;だけだとループが回っている間はフォームの移動もできないですよね?


傍観者2  2005-04-14 22:10:52  No: 14306

Application.ProcessMessages; だとループが回ってるときでも Button1 をまた押せますけど..


きりり  2005-04-14 22:37:20  No: 14307

> ループが回ってるときでも Button1 をまた押せますけど

procedure TForm1.Button1Click(Sender: TObject);
var
i : Integer;
begin

 Button1.Enabled := False;

 for i := 0 to 100000 do
 begin
   Label1.Invalidate;
   Application.ProcessMessages;
   Label1.Caption := IntToStr(i);
 end;

 Button1.Enabled := True;

end;

・・で良いのでは?
検証してないけど、これで二度押しは防げるかと。


メラトニン  2005-04-14 22:41:19  No: 14308

目的次第でしょう ^^;
どちらでも「増えていく経過」は見れますが仕組みが違います。


傍観者  2005-04-14 23:01:42  No: 14309

ボタンの2度押しは防止するとして、
今回のような長いループは別のスレッドにしてもよさそうですね。


通りすがり  2005-04-15 00:40:33  No: 14310

なるほど、このような場合には
Application.ProcessMessages;や、
UpDataを使うのですね。
とても参考になりました。
また、両者とも、用途に分けて使い分けていこうと思います。
(UpDataのほうが処理が速いなどのメリットがあればなのですが)
皆様多数の意見、参考になる発言をしていただきありがとうございました。


通りすがり  2005-04-15 00:40:51  No: 14311

解決です


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加