12

一種の自習演習として、2x3 の長方形に 6 つのパネルを含むフォームを作成し、表示と非表示を次々に切り替えたいと考えています。ある種の for ループを使用してそうしようとしています。もちろん、次のように書くこともできます。

Panel1.Visible := true;
Panel1.Visible := false;
Panel2.Visible := true;
Panel2.Visible := false;
Panel3.Visible := true;
etc. etc.

しかし、これには非常に多くのタイピングが必要であり、各ステップ間で 100 ミリ秒待機することを決定した場合、かなり非効率的です。たとえば、待機するには 6 つのステップすべてを編集する必要があります。これは6ステップで実行可能ですが、別の機会に100回やりたいと思います! したがって、変数が1から6まで変化し、オブジェクト識別子で使用される、これにはforループを使用する方法もあるに違いないと考えています。したがって、次のようになります。

for variable := 1 to 6 do begin
Panel + variable.Visible := true;
Panel + variable.Visible := false;
end;

さて、これは明らかに機能しませんが、これが実際に可能かどうか、可能であればその方法を誰かが教えてくれることを願っています. 文字列を識別子として使用できますか?すべての技術用語を知っているわけではないので、私の説明はおそらくかなり悪いですが、コードが何かを説明してくれることを願っています.

4

5 に答える 5

23

Componentsパネルの所有者の配列をループできます。

var
  i: Integer;
  TmpPanel: TPanel;
begin
  { This example loops through all of the components on the form, and toggles the
    Visible property of each panel to the value that is opposite of what it has (IOW,
    if it's True it's switched to False, if it's False it's switched to True). }
  for i := 0 to ComponentCount - 1 do                  
    if Components[i] is TPanel then                    
    begin
      TmpPanel := TPanel(Components[i]);
      TmpPanel.Visible := not TmpPanel.Visible;     // Toggles between true and false
    end;
end;

FindComponent名前で非常に具体的なタイプのコンポーネントが必要な場合は、メソッドを使用することもできます。たとえば、6 つのパネルがあり、その名前がPanel1Panel2などである場合:

var
  i: Integer;
  TmpPanel: TPanel;
begin
  for i := 1 to 6 do
  begin
    TmpPanel := FindComponent('Panel' + IntToStr(i)) as TPanel;
    if TmpPanel <> nil then      // We found it
      TmpPanel.Visible := not TmpPanel.Visible;
  end;
end;
于 2012-11-30T16:39:48.590 に答える
6

これは、設計時ではなく実行時に動的にコントロールを作成したい状況です。6つの異なる変数に取り組もうとすると、苦痛の世界になります。また、グリッドを2x3ではなく3x4にする必要がある場合は、その決定をさらに後悔することになります。

したがって、完全に空白のフォームから始めます。そして、コードに、パネルの2次元配列を追加します。

private
  FPanels: array of array of TPanel;

次に、フォームのコンストラクターまたはOnCreateイベントハンドラーで、次のような関数を呼び出して配列を初期化できます。

procedure TMyForm.InitialisePanels(RowCount, ColCount: Integer);
var
  Row, Col: Integer;
  aLeft, aTop, aWidth, aHeight: Integer;
  Panel: TPanel;
begin
  SetLength(FPanels, RowCount, ColCount);
  aTop := 0;
  for Row := 0 to RowCount-1 do begin
    aLeft := 0;
    aHeight := (ClientHeight-aTop) div (RowCount-Row);
    for Col := 0 to ColCount-1 do begin
      Panel := TPanel.Create(Self);
      FPanels[Row, Col] := Panel;
      Panel.Parent := Self;
      aWidth := (ClientWidth-aLeft) div (ColCount-Col);
      Panel.SetBounds(aLeft, aTop, aWidth, aHeight);
      inc(aLeft, aWidth);
    end;
    inc(aTop, aHeight);
  end;
end;

これで、フラットな1次元配列ではなく、デカルト座標を使用してパネルを参照できるようになりました。もちろん、必要に応じて、フラットな1次元配列を簡単に宣言することもできます。

重要なアイデアは、構造化されたレイアウトで多数のコントロールを作成する場合は、デザイナーを放棄してコード(ループと配列)を使用するのが最善であるということです。

于 2012-11-30T16:54:56.443 に答える
5

の使用FindComponent方法TComponent:

  for variable := 1 to 6 do begin
    pnl := FindComponent('Panel' + IntToStr(variable));
    if pnl is TPanel then
    begin
      TPanel(pnl).Visible := true;
      TPanel(pnl).Visible := false;
    end;
  end;
于 2012-11-30T16:43:50.163 に答える
0

他の人が答えたように、FindComponent が道です。

ただし、コンポーネントの一般的なプロパティ (visible、position など) を変更するだけの場合は、型と比較する必要はありません。

これはうまくいきます:

  for i := 1 to 16 do
  begin
    (FindComponent( 'P' + inttostr(i) ) as TControl).Visible := false;
  end;

(注: これは Delphi 6/7 用です。最近のバージョンではおそらく他の方法でこれを行います)

于 2020-01-17T22:08:21.807 に答える