動的に作成したTimageをボタンを押下ごとに削除する処理を作成しましたが
最後の一つになるとFreeをしているのに画像表示が消えません。
実際、コントロールの配列が開放されているか、わざと最終インデックスで
もう一度、Freeすると要素がないようなエラーが発生し落ちました。
マシンのメモリの関係とかで中身は消え画像だけ残ってしまう現象とかあるのでしょうか?
しかし、一つだけ自動作成し、ボタン押下で削除するときちんと画像も消えます。
すみません、以下で動的に作成するTimageは3つです。
>動的に作成したTimageをボタンを押下ごとに削除する処理を作成しましたが
>最後の一つになるとFreeをしているのに画像表示が消えません。
ソースコードを提示された方がよいと思います。
他の環境でもテストしてもらえますので。
うーん、ちょっと、ソースが多いのでとても載せることができません。
単純な話で、Freeしても画像が残る現象とかありましたか?
残ってしまったという事が起こりで、そのとき、どういう対処を取られたか
教えてほしいです。
> うーん、ちょっと、ソースが多いのでとても載せることができません。
問題を解決するには、物事を単純化して個別に検証することが大切です。
開発中のソースそのものではなく、問題が再現する最低限のコードを提示できる
ようにすることができれば、自力で解決できることに近づきます。コードを提示
しなければ、
>マシンのメモリの関係とかで中身は消え画像だけ残ってしまう現象とかあるのでしょうか?
こういうことはありません、としか答えられません。
推測すると、TImageのオブジェクトの動的なリストを作成し、破棄するとき、
インデクスの0の方からすると、こういうことが起こります。動的リストの
中身を破棄するときは、インデックスの大きいほうから削除してください。
for i := 2 downto 0 do TImage(List[i]).Free;
のようにします。
> ソースが多いのでとても載せることができません。
多くても少なくても、こういう場合には該当部分のみを抽出して示すようにします。
その作業をするだけで原因が発見できてしてしまうことも少なくありません。
例えば、次のよう取り出します。
「動的に作成する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;
> 単純な話で、Freeしても画像が残る現象とかありましたか?
ありません、あったらVCLの重大なバグになります。
具体的なソースを載せようとせず質問してしまい大変、申し訳ありませんでした。
それでも、いろいろと返答していただきありがとうございます。
デクリメントで試したのですが、画像がどうしても残ってしまいます。
再度、ソースを整理し見直してみます。
TListでなく、TObjectListを使えば解放の手間が省けますよ。
すみません、現段階ではイメージ作成数は3つですが、将来的に51個くらい
イメージを想定しており、配列宣言のところを以下のようにしています。
Images: Array[0..50] of TImage;
上記でイメージを3つしか作成せず、Freeメソッドで削除すると何か不都合とか
あるでしょうか?ちなみにnil以外のものをFreeメソッドで解放しています。
不都合は無いと思います。Free したらそのインデックスのところに nil を
代入してますよね?
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 します。
問題を単純化して個別に検証することは重要です。
ツイート | ![]() |