動的に作成したTimageの削除方法


リュウ  2004-08-31 00:29:15  No: 10707

動的に作成したTimageをボタンを押下ごとに削除する処理を作成しましたが
最後の一つになるとFreeをしているのに画像表示が消えません。
実際、コントロールの配列が開放されているか、わざと最終インデックスで
もう一度、Freeすると要素がないようなエラーが発生し落ちました。

マシンのメモリの関係とかで中身は消え画像だけ残ってしまう現象とかあるのでしょうか?

しかし、一つだけ自動作成し、ボタン押下で削除するときちんと画像も消えます。


リュウ  2004-08-31 00:30:58  No: 10708

すみません、以下で動的に作成するTimageは3つです。

>動的に作成したTimageをボタンを押下ごとに削除する処理を作成しましたが
>最後の一つになるとFreeをしているのに画像表示が消えません。


ふぐちゃん  2004-08-31 00:53:39  No: 10709

ソースコードを提示された方がよいと思います。
他の環境でもテストしてもらえますので。


リュウ  2004-08-31 03:49:52  No: 10710

うーん、ちょっと、ソースが多いのでとても載せることができません。
単純な話で、Freeしても画像が残る現象とかありましたか?
残ってしまったという事が起こりで、そのとき、どういう対処を取られたか
教えてほしいです。


jok  2004-08-31 04:54:03  No: 10711

> うーん、ちょっと、ソースが多いのでとても載せることができません。

問題を解決するには、物事を単純化して個別に検証することが大切です。
開発中のソースそのものではなく、問題が再現する最低限のコードを提示できる
ようにすることができれば、自力で解決できることに近づきます。コードを提示
しなければ、

>マシンのメモリの関係とかで中身は消え画像だけ残ってしまう現象とかあるのでしょうか?

こういうことはありません、としか答えられません。

推測すると、TImageのオブジェクトの動的なリストを作成し、破棄するとき、
インデクスの0の方からすると、こういうことが起こります。動的リストの
中身を破棄するときは、インデックスの大きいほうから削除してください。

for i := 2 downto 0 do TImage(List[i]).Free;

のようにします。


sadoyama  URL  2004-08-31 04:54:58  No: 10712

> ソースが多いのでとても載せることができません。

  多くても少なくても、こういう場合には該当部分のみを抽出して示すようにします。
  その作業をするだけで原因が発見できてしてしまうことも少なくありません。

  例えば、次のよう取り出します。
  「動的に作成するTimageは3つです」ということですので、それに合わせました。
  この事例では、きれいに開放できてしまいます。  

var
  Form1: TForm1;
  Images: Array[0..2] of TImage;
  ImagesCount: Integer;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to 2 do
  begin
    Images[i] := TImage.Create(Self);
    Images[i].Parent := Form1;
    Images[i].Width := 20;
    Images[i].Height := 20;
    Images[i].Top := 50;
    Images[i].Left := i * 50 + (i + 1) * 10;
    // 作成されたことがモニタで確認できるようにする
    Images[i].Canvas.Brush.Color := clWhite;
    // 画像の読み込みなど他の記述はカットして示す
  end;
  ImagesCount := 2;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if ImagesCount >= 0 then
  begin
    Images[ImagesCount].Free;
    Dec(ImagesCount);
  end;
end;


jok  2004-08-31 04:56:38  No: 10713

> 単純な話で、Freeしても画像が残る現象とかありましたか?

ありません、あったらVCLの重大なバグになります。


リュウ  2004-08-31 07:51:11  No: 10714

具体的なソースを載せようとせず質問してしまい大変、申し訳ありませんでした。
それでも、いろいろと返答していただきありがとうございます。

デクリメントで試したのですが、画像がどうしても残ってしまいます。
再度、ソースを整理し見直してみます。


にしの  2004-08-31 19:03:11  No: 10715

TListでなく、TObjectListを使えば解放の手間が省けますよ。


リュウ  2004-09-01 08:26:00  No: 10716

すみません、現段階ではイメージ作成数は3つですが、将来的に51個くらい
イメージを想定しており、配列宣言のところを以下のようにしています。

 Images: Array[0..50] of TImage;

上記でイメージを3つしか作成せず、Freeメソッドで削除すると何か不都合とか
あるでしょうか?ちなみにnil以外のものをFreeメソッドで解放しています。


jok  2004-09-01 08:36:05  No: 10717

不都合は無いと思います。Free したらそのインデックスのところに nil を
代入してますよね?


jok  2004-09-01 09:10:13  No: 10718

public
    Images: Array[0..50] of TImage;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Images[0] := TImage.Create(self);
  Images[0].Parent := self;
  Images[0].Top := 10;
  Images[0].Left := 10;
  Images[0].AutoSize := true;
  Images[0].Picture.LoadFromFile('C:\Borland Shared\Images\Splash\256Color\shipping.bmp');

  Images[1] := TImage.Create(self);
  Images[1].Parent := self;
  Images[1].Top := 10;
  Images[1].Left := 210;
  Images[1].AutoSize := true;
  Images[1].Picture.LoadFromFile('C:\Borland Shared\Images\Splash\256Color\shipping.bmp');

  Images[2] := TImage.Create(self);
  Images[2].Parent := self;
  Images[2].Top := 10;
  Images[2].Left := 410;
  Images[2].AutoSize := true;
  Images[2].Picture.LoadFromFile('C:\Borland Shared\Images\Splash\256Color\shipping.bmp');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i:integer;
begin
  for i := 0 to High(Images) do
    if Assigned(Images[i]) then begin
       Images[i].Free;
       Images[i] := nil;
       Break;
    end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i:integer;
begin
  for i := 0 to High(Images) do
    if Assigned(Images[i]) then begin
       Images[i].Free;
       Images[i] := nil;
    end;
end;

このようにして、Button1 を押すたびに一つずつ Free しても問題ありません。
また、Button2 を押すと一括して Free します。

問題を単純化して個別に検証することは重要です。


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

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






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