添え字を使用して動的にラベルを作成するには?

解決


めるめる  2007-08-27 21:30:24  No: 27538

いつもお世話になります。

現在は、下記のようなソースで、ラベルを配列で定義し、
for ループで動的にラベルを作成し、
for ループで処理し(省略)、
for ループで解放しています。

・問題点
  予め、配列の最大値を array で定義している。
  →  配列の最大値がもっと必要な場合が発生した場合どうするのか
      実際にそんなに配列が必要なくても、余裕を持った配列の定義が必要

・質問内容
 (1)配列そのものを動的に作成できないのか?
 (2)ラベルの配列を[0..10000]とか指定したらメモリ等を圧迫しないのか?
 (3)別の方法で実現できないのか?
    ※ComponentList を使用すれば出来そうらしいのですが、
      検索方法が悪いらしく、それらしいHELPが見つかりません。
      HELPの場所または使用方法を教えていただけないでしょうか?

以上、よろしくお願いいたします。

※以下、現在のソース(概要)です。
var
  Form1: TForm1;
  arLabel : array [0..100] of TLabel;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 1 to 10 do
  begin
    arLabel[i] := TLabel.Create(self);
    arLabel[i].Parent := self;
    arLabel[i].Left := i * 20;
    arLabel[i].Top  := i * 20;
    arLabel[i].Caption := 'Label' + IntToStr(i);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 1 to 10 do
    arLabel[i].Free;
end;


ヘルプの見方を覚えましょう  2007-08-27 22:26:33  No: 27539

・質問内容
 (1)動的配列で調べてみましょう。
 (2)オブジェクトの配列はポインタ(4バイト)の配列と同じなので配列を宣言しただけでメモリを圧迫することは無いでしょう。(10000*4≒40KB)
 (3)リストで管理するのが定石でしょう。TListについて知らない様なのでヘルプで調べてみましょう。TListの使い方が分かればTComponentListの使い方も自ずと分かるはずです。
それと、ヘルプでクラスを調べるときはComponentListとするのではなく、TComponentListというように頭にTをつけて検索すれば見つかります。


Mr.XRAY  URL  2007-08-29 05:38:16  No: 27540

めるめるさん、こんにちは。
コードはお世辞にもいいとは言えませんが、以下のページが参考にならないてしょうか。

http://homepage2.nifty.com/Mr_XRAY/Delphi/plSamples/T_SaveComponentList1.htm
http://homepage2.nifty.com/Mr_XRAY/Delphi/plSamples/T_SaveComponentList2.htm
http://homepage2.nifty.com/Mr_XRAY/Delphi/plSamples/T_CreateComponent.htm


さどやま  URL  2007-08-30 01:38:46  No: 27541

> (1)配列そのものを動的に作成できないのか?
  Delphi4 以降であれば,SetLength()が使えます。 (Delphi3 以前ならGetMem()を使用) 

var
  arLabel: array of TLabel;
  MaxCount: Integer;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MaxCount := 必要な配列数を得る。
  SetLength(arLabel, MaxCount);

  for i := 0 to MaxCount - 1 do  // 0 から始めたほうが無難。
  begin
    arLabel[i] := TLabel.Create(self);
    arLabel[i].Parent := self;
    arLabel[i].Left := i * 20;
    arLabel[i].Top  := i * 20;
    arLabel[i].Caption := 'Label' + IntToStr(i);

    // (2)の質問で追加

  end;
end;

> (2)ラベルの配列を[0..10000]とか指定したらメモリ等を圧迫しないのか?
> オブジェクトの配列はポインタ(4バイト)の配列と同じなので配列を宣言しただけでメモリを圧迫することは無いでしょう。
  Button1ClickでTLabel.Createした段階では考慮が必要です。
  TLabelならまず心配はないでしょうが,TBitmapの配列だとBitmapのサイズによっては簡単にメモリを使い切ってしまいます。

var
  AvailPhys: Integer;
  MemoryStatus: TMemoryStatus;
begin
  for i := 0 to MaxCount - 1 do   
  begin

    // 「(2)の質問で追加」の部分
    GlobalMemoryStatus(MemoryStatus);  // メモリ情報を得る
    // 空きメモリを得る
    // MemoryStatus.dwAvailPhysで直接得られるはずだが,経験上信用できない。
    AvailPhys := MemoryStatus.dwTotalPhys div 100 * MemoryStatus.dwMemoryLoad;
    // 100%使い切るのは危険, 100MBにしたのは例えばの例
    if AvailPhys < 100000000 then 
    begin
      MaxCount := i;
      Break; 
    end;
  end;
end;    

>  for i := 1 to 10 do
>    arLabel[i].Free;
  // Createは昇順, Freeは降順が無難。
  for i := 9 downto 0 do
  // Nilも必ず設定する癖をつけたほうが良い。
    if Assigned(arLabel[i]) then  // arLabel[i]にnilが設定されていなければ 
      FreeAndNil(arLabel[i]);

> (3)別の方法で実現できないのか?
  Mr.XRAYさんの回答で解決しますよね。


さどやま  2007-08-30 01:52:31  No: 27542

追伸

  上記例は,作成されるTLabel等のサイズが事前に決定できない場合の例です。
  このコードだと,処理速度がかなりかかります。
  TLabel等のサイズあるいは限度サイズが事前に決定できる場合には,先に使用可能メモリサイズを得て作成数を決めるようにすると良いでしょう。


めるめる  2007-08-31 07:37:16  No: 27543

Mr.XRAY 様、さどやま 様、ありがとうございます。

何とか、希望通りのものが出来そうです。
ソース・コードを提示して頂き、とても助かりました。

今後ともよろしくお願いいたします。


ヘルプの見方を覚えましょう  2007-08-31 10:01:41  No: 27544

親切心で答えたのに無視されるとは切ないですね・・・
ヘルプに載っていますよというのは、答えにならないのでしょうか?
ヘルプやドキュメントの見方が分かるって言うのも一つのスキルだと思うんですけどね、最近は何でもかんでも掲示板で聞けばすむと言う風潮のようですが・・・
掲示板で聞くよりもヘルプを見たほうがよっぽど早いし正確な情報が乗っています(Delphiのヘルプは若干日本語おかしいですが)
あとは、google等を使って調べ物をする技術も最近では一つのスキルと見なされるようですね。


めるめる  2007-08-31 19:33:21  No: 27545

ヘルプの見方を覚えましょう 様

ご指摘ありがとうございます。
その通りだと思います。

確かに、ある程度、予備知識があって、ちょっとわからない事は、
ヘルプは助かります。
ただ、まったく予備知識がないと、ヘルプを見ても具体的な使用例がない
と、どのようにとりかかってよいのかが、よくわからなかったのです。

従って、とりかかりの具体的なサンプル・ソースがあると、あとは
もっと実用的に使うためのヘルプはとても役に立ちました。

無視したつもりではなかったのですが、ご気分を害されたのであれば、
私の不徳のいたすところです。
申し訳ありませんでした。
いたらない点、多々あるとは思いますが、今後ともよろしくお願い
いたします。


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

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






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