5

私はDelphi5を使用しており、実行時に多数のパネルを作成してから、明らかに実行時にパネルにボタンを作成しています。将来、パネルとボタンの組み合わせを動的に作成する必要があるかもしれないので、この方法で行う必要があります。

これらはすべて実行できますが、パネルのコンポーネント名にアクセスする方法が見つからないため、作成したパネルを参照する方法がわかりません。インターネットを探し回ると、FindComponentを使用してパネルコンポーネントを名前で検索できることがわかりましたが、文字列変数を使用して参照できないため、その名前の使用方法がわかりません。たとえば、StringVar :=Panel.Name。タイプの不一致、TComponentNameとStringが発生します。

パネルを作成するときに、各パネルのボタンを作成しました。簡略化すると、次のようになります。

   With TypeQuery do begin // Create Panels
   First;
   While (not eof) do begin        // create the actual panel
      panelno := FieldByName('Product_type_id').AsInteger;
      pnl := Tpanel.Create(Self);
      pnl.name := FieldByName('PanelName').AsString;
      pnl.color := clInactiveCaption;
      pnl.parent := MainForm;
      pnl.width := 365;
      pnl.Height := 551;
      pnl.left := 434
      pnl.top := 122;
      pnl.caption := '';
      With ButtonQuery do begin
         Close;
         Parameters.parambyname('PanelID').Value := PanelNo;
         Open;
         First;
         While (not eof) and (FieldByName('Product_type_id').AsInteger = PanelNo) do begin    //put the buttons on it.
            btnName := FieldByName('ButtonName').AsString;
            BtnText := FieldByName('ButtonText').AsString;
            BtnGroup := FieldByName('Product_Group_ID').AsString;
            GrpColour := FieldByName('ButtonColour').AsString;
            btn := TColorButton.Create(Self);
            btn.Parent := pnl;
            btn.Name := BtnName;
            Btn.backcolor := HexToTColor(GrpColour);
            btn.Font.Name := 'Arial Narrow';
            btn.Font.Style := [fsBold];
            btn.Font.Size := 10;
            . . .
        end;
        . . .
     end; 
  end;

私はいくつかのフォーラム(これを含む)で、パネルを名前で直接参照する方法がないことを読みました。コンポーネント配列を使用してみましたが、同じ問題が発生します。割り当てられたコンポーネント名でコンポーネントを参照する必要があります。

さて、私は銃のプログラマーではありません-私は何年もの間Delphiを使用して単純なプログラムを作成してきましたが、これははるかに複雑です。これまで、ランタイムコンポーネントの作成に取り組んだことはありません。

FindComponentを使用して、パネルを表示または非表示にすることはできますか?もしそうなら、私が上であなたに示したことを考えると、私が赤ちゃんのステップで取るべきアプローチを私に与えることができますか?

前もって感謝します ...

4

4 に答える 4

12

「文字列変数を使用して参照することはできません。たとえば、StringVar:=Panel.Name」とはどういう意味かわかりません。

これを試して:

procedure TForm1.FormCreate(Sender: TObject);
var
  p: TPanel;
begin
  p := TPanel.Create(Self); // create a TPanel at run-time
  p.Name := 'MyPanel'; // set a unique name
  p.Parent := Self;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  p: TPanel;
  StringVar: string;
begin
  p := FindComponent('MyPanel') as TPanel;
  if Assigned(p) then // p has reference to MyPanel
  begin
    // use that reference
    p.Caption := 'Foo';
    StringVar := p.Name;
    ShowMessage(StringVar);
  end;
end;

それとも私は何かを逃しましたか?

于 2012-12-05T16:38:48.963 に答える
6

コンポーネント名変数名と混同しています。Delphi IDEは、IDEで作成されたコンポーネントについて、これら2つを同じに保つように努めていますが、必ずしも同じであるとは限りません。コンポーネントを動的に作成しているため、変数名はありません。また、必要な変数の数がわかりません。ただし、コンポーネント名は引き続き制御できます。コンポーネントのNameプロパティを割り当てるだけで、を呼び出すことで、他のコンポーネント名と同じように使用できますFindComponent。パネルインスタンスごとに名前が一意であることを確認してください。

コンパイル時に必要な数がわからない場合に変数を処理する方法は、配列またはリストを使用することであることも忘れないでください。プレーンな古い配列を使用することも、またはのようなより高度なデータ構造を使用することもできTComponentListますTDictionary

最後に、作成しているパネルのコントロールを参照しやすくするために、パネルを省略して、代わりにフレームを使用できます。IDEでを視覚的にデザインTFrameし、ボタンに名前を付けることができます。実行時に、フレームクラスをインスタンス化でき、フォームやデータモジュールをインスタンス化するときと同じように、すべてのボタンが自動的に作成されます。新しいフレームオブジェクトに名前を付ける必要があるだけですが、そのオブジェクトには、ボタンを参照する名前付きフィールドがすでにあります。

于 2012-12-05T15:20:02.577 に答える
2

tFormインスタンスに表示するために作成したアイテムのセカンダリリストを作成する必要はありません。

AFAIK、自分の代わりにフォームまたは他のコンテナを使用する新しいパネルを作成するときはいつでも

  pnl := Tpanel.Create(Self);

含まれている「自己」コンポーネントによって処理されるため、新しいpnlを破棄する必要はありません。

これは、親コンポーネントの子コンポーネントを保持するコンストラクトが存在する必要があることを意味します。

親オブジェクトにComponentCount、Componentsリスト、またはFindComponentメソッドのいずれかが見つかることを期待しています。「Self」参照オブジェクトがTformであると仮定します。

 for i := 0 to tForm(self).ComponentCount -1 do 
   if tForm(self).Components[i] is tPanel then 
      tPanel(tForm(self).Components[i]).Caption := intToStr(i) ;

アプリケーション内のtPanelのすべてのキャプションを変更します。コードとデザイナーによって作成されたパネルを区別するために、作成された各tPanelのTAGプロパティを使用して、上記の例で使用できます。

于 2012-12-05T15:49:40.453 に答える
0

参照が必要なコンポーネントをTList|Container ...に追加してから、list|containerを使用してそれらにアクセスできます。

var
  slPanels: TStringList;
...


 With TypeQuery do begin // Create Panels
   First;
   While (not eof) do begin        // create the actual panel
      panelno := FieldByName('Product_type_id').AsInteger;
      pnl := Tpanel.Create(Self);
      pnl.name := FieldByName('PanelName').AsString;
      slPanels.AddObject(FieldByName('PanelName').AsString, pnl);

必要なとき:

TPanel(slPanels.Objects[slPanels.IndexOf(FieldByName('PanelName').AsString)]) ...

私は上記のコードが嫌いです(より良いコンテナがあります...しかしこれは仕事をするはずです:o))

于 2012-12-05T15:22:03.127 に答える