実行時にコンポーネントを作成し、それを操作するにはどうすればよいですか(プロパティの変更など)?
ビジュアルコンポーネントか非ビジュアルコンポーネントかによって異なります。原理は同じですが、コンポーネントの種類ごとにいくつかの追加の考慮事項があります。
非ビジュアルコンポーネント用
var
C: TMyComponent;
begin
C := TMyComponent.Create(nil);
try
C.MyProperty := MyValue;
//...
finally
C.Free;
end;
end;
ビジュアルコンポーネントの場合:
基本的に、ビジュアルコンポーネントは、非ビジュアルコンポーネントと同じ方法で作成されます。ただし、それらを表示するには、いくつかの追加プロパティを設定する必要があります。
var
C: TMyVisualComponent;
begin
C := TMyVisualComponent.Create(Self);
C.Left := 100;
C.Top := 100;
C.Width := 400;
C.Height := 300;
C.Visible := True;
C.Parent := Self; //Any container: form, panel, ...
C.MyProperty := MyValue,
//...
end;
上記のコードのいくつかの説明:
Parent
プロパティを設定すると、コンポーネントが表示されます。忘れた場合、コンポーネントは表示されません。 (それを見逃すのは簡単です:))多くのコンポーネントが必要な場合は、上記と同じことをループで実行できます:
var
B: TButton;
i: Integer;
begin
for i := 0 to 9 do
begin
B := TButton.Create(Self);
B.Caption := Format('Button %d', [i]);
B.Parent := Self;
B.Height := 23;
B.Width := 100;
B.Left := 10;
B.Top := 10 + i * 25;
end;
end;
これにより、フォームの左端に10個のボタンが追加されます。後でボタンを変更する場合は、ボタンをリストに保存できます。 ( TComponentList は最適ではありませんが、コメントからこの回答への提案もご覧ください)
イベントハンドラーの割り当て方法:
イベントハンドラーメソッドを作成し、それをイベントプロパティに割り当てる必要があります。
procedure TForm1.MyButtonClick(Sender: TObject);
var
Button: TButton;
begin
Button := Sender as TButton;
ShowMessage(Button.Caption + ' clicked');
end;
B := TButton.Create;
//...
B.OnClick := MyButtonClick;
ランタイムコンポーネントの作成プロセスを簡略化するには、 GExperts を使用できます。
例(この方法で生成されたTButton作成コード):
var
btnTest: TButton;
btnTest := TButton.Create(Self);
with btnTest do
begin
Name := 'btnTest';
Parent := Self;
Left := 272;
Top := 120;
Width := 161;
Height := 41;
Caption := 'Component creation test';
Default := True;
ParentFont := False;
TabOrder := 0;
end;
コントロールを動的に追加するときに追加したいと思います... @Despatcherの<1>で提案されているように、オブジェクトリスト(TObjectList)に追加することをお勧めします。
procedure Tform1.AnyButtonClick(Sender: TObject);
begin
If Sender is TButton then
begin
Case Tbutton(Sender).Tag of
.
.
.
// Or You can use the index in the list or some other property
// you have to decide what to do
// Or similar :)
end;
end;
procedure TForm1.BtnAddComponent(Sender: TObJect)
var
AButton: TButton;
begin
AButton := TButton.Create(self);
Abutton. Parent := [Self], [Panel1] [AnOther Visual Control];
AButton.OnClick := AnyButtonClick;
// Set Height and width and caption ect.
.
.
.
AButton.Tag := MyList.Add(AButton);
end;
ユニット 'Contnrs'をUsesリストに追加する必要があります。つまり、System.Contnrs.pasベースのContainersユニットそして、多くのオブジェクトリストを持つことができます。使用するコントロールのタイプごとにTObjectListを使用することをお勧めします。
Interface
Uses Contnrs;
Type
TMyForm = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
Var
MyForm: TMyForm;
checkBoxCntrlsList: TObjectList; //a list for the checkBoxes I will createin a TPanel
comboboxCntrlsList: TObjectList; //a list of comboBoxes that I will create in some Form Container
これにより、どのタイプのコントロールであるかがわかるので、各コントロールを簡単に操作/管理できます。
Var comboBox: TComboBox;
I: Integer;
begin
For I = 0 to comboboxCntrlsList.Count -1 do // or however you like to identify the control you are accessing such as using the tag property as @Despatcher said
Begin
comboBox := comboboxCntrlsList.Items[I] as TComboBox;
...... your code here
End;
end;
これにより、そのコントロールのメソッドとプロパティを使用できるようになります。TObjectListを作成することを忘れないでください。
checkBoxCntrlsList := TObjectList.Create;
comboboxCntrlsList := TObjectList.Create;
ただし、作成するコンポーネントの数が確実にわからない場合は、たとえばユーザーの決定に依存する場合。では、コンポーネントを動的に宣言するにはどうすればよいですか?
答えは提案されています-最も簡単な方法はオブジェクト(コンポーネント)のリストです。 TObjectListは(ユニットcontnrsで)最も簡単に使用できます。リストは素晴らしいです!
In Form1 Public
MyList: TObjectList;
procedure AnyButtonClick(Sender: TObject);
//より洗練された// TNotifyeventsを宣言して割り当てることができますが、単純に保つことができます:)。 。 。
procedure Tform1.AnyButtonClick(Sender: TObject);
begin
If Sender is TButton then
begin
Case Tbutton(Sender).Tag of
.
.
.
// Or You can use the index in the list or some other property
// you have to decide what to do
// Or similar :)
end;
end;
procedure TForm1.BtnAddComponent(Sender: TObJect)
var
AButton: TButton;
begin
AButton := TButton.Create(self);
Abutton. Parent := [Self], [Panel1] [AnOther Visual Control];
AButton.OnClick := AnyButtonClick;
// Set Height and width and caption ect.
.
.
.
AButton.Tag := MyList.Add(AButton);
end;
オブジェクトリストには、オブジェクトのビジュアルを含めるかどうかを指定できますが、どのアイテムがどのアイテムであるかを分類するオーバーヘッドが追加されます。たとえば、同様のパネルに複数の動的コントロールが必要な場合は、関連リストを用意することをお勧めします。
注:他のコメンターと同様に、簡潔にするために単純化しすぎたかもしれませんが、アイデアを理解していただければ幸いです。作成されたオブジェクトを管理するためのメカニズムが必要であり、リストはこれに最適です。
「XMLベースのテンプレートを使用してデルファイフォームを作成する」に関する調査中に、RTTIを指摘し、オープンツールAPI(ToolsApi.pasだと思います)を使用すると便利です。ユニットのインターフェースを見てください。
とても簡単。 Createを呼び出します。例:
procedure test
var
b : TButton;
begin
b:=TButton.Create(nil);
b.visible:=false;
end;
これにより、実行時にコンポーネント(TButtonはコンポーネント)が作成され、プロパティが表示されるように設定されます。
コンストラクタの場合:メモリを自分で管理する場合はnilを渡します。他のコンポーネントが破棄されたときにそれを破棄させたい場合は、別のコンポーネントにポインターを渡します。
一部のコンポーネントは「Loaded」メソッドをオーバーライドします。実行時にインスタンスを作成する場合、このメソッドは自動的に呼び出されません。フォームファイル(DFM)からの読み込みが完了すると、Delphiによって呼び出されます。
メソッドに初期化コードが含まれている場合、アプリケーションを実行時に作成すると、予期しない動作が発生する可能性があります。この場合、コンポーネントライターがこのメソッドを使用しているかどうかを確認してください。
勝利コントロールをグループボックス/ページコントロール/その他...にネストする場合、親グループボックスも所有者にすることは有益だと思います。オーナーが常にメインフォームであるのとは対照的に、これを行うとウィンドウのクローズ時間が大幅に減少することに気づきました。