如何在運行時創建組件然後使用它(更改屬性等)?在運行時創建組件 - Delphi
回答
它取決於它是否是視覺或非視覺組件。原理是一樣的,但是對於每種組件都有一些額外的考慮。
對於非可視化組件
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 IST最適合,也看看從評論到這個答案的建議)
如何分配事件處理程序:
你必須創建一個事件處理方法,並將其分配給活動屬性。
procedure TForm1.MyButtonClick(Sender: TObject);
var
Button: TButton;
begin
Button := Sender as TButton;
ShowMessage(Button.Caption + ' clicked');
end;
B := TButton.Create;
//...
B.OnClick := MyButtonClick;
非常容易。致電創建。示例:
procedure test
var
b : TButton;
begin
b:=TButton.Create(nil);
b.visible:=false;
end;
這會在運行時創建一個組件(TButton是一個組件)並將該屬性設置爲可見。
對於構造函數:如果您想自己管理內存,則傳遞nil。如果您希望在另一個組件被銷燬時銷燬它,則傳遞另一個組件的指針。
爲了簡化運行時組件的創建過程,您可以使用GExperts。
- 以可視方式創建組件(或多個組件)並設置其屬性。
- 選擇一個或多個組件並執行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;
但是,如果我不肯定知道我要多少組件來創建,例如如果這取決於用戶的決定。那麼我怎樣才能動態地聲明組件?
答案已經被提出 - 最簡單的方法是對象列表(組件)。 TObjectList是最簡單的使用(在單元連續)。列表非常棒!
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;
對象列表可以包含可視或不屬於任何對象,但是,讓你整理出哪些項目是其中的一個額外的開銷 - 最好是有相關的列表,如果你想在例如類似面板多個動態控制。
注意:與其他評論者一樣,爲了簡潔起見,我可能會過度簡化,但我希望您能理解這個想法。您需要一種機制來管理對象,一旦它們被創建,列表就非常適合這些東西。
某些組件重寫'Loaded'方法。如果您在運行時創建實例,則不會自動調用此方法。當從表單文件(DFM)加載完成時,它將由Delphi調用。
如果該方法包含初始化代碼,則在運行時創建應用程序時可能會顯示意外的行爲。在這種情況下,檢查組件編寫器是否使用了此方法。
如果你在組合框/頁面控件/其他中嵌套win控件,我認爲讓父組框也是所有者是有益的。我注意到這樣做時窗戶關閉時間急劇減少,而不是讓所有者始終成爲主要窗體。
在「使用基於xml的模板創建delphi表單」的研究中,我發現了一些有用的指出RTTI並使用開放工具api(ToolsApi.pas我認爲)的方法。查看設備中的接口。
我只想補充一點,當動態添加控件時... 按照@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;
您需要將Unit'Contnrs'添加到您的Uses列表中。 I.e System.Contnrs.pas基礎容器單元 而且您可以有許多對象列表。 我建議對每種類型的控件使用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;
這樣您就可以再使用該控件 的方法和屬性,不要忘了創建TObjectLists,也許在表單中創建活動...
checkBoxCntrlsList := TObjectList.Create;
comboboxCntrlsList := TObjectList.Create;
這是例子如何在Evernote上模擬按鈕標記
unit Unit7;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, CHButton, Vcl.ExtCtrls, RzPanel, CHPanel, RzCommon,RzBmpBtn, Vcl.StdCtrls;
type
// This is panel Button
TButtonClose = class (TRzPanel)
CloseButton : TRzBmpButton;
procedure CloseButtonClick(Sender: TObject);
procedure CloseButtonMouseEnter(Sender: TObject);
procedure MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TForm7 = class(TForm)
CHButton1: TCHButton;
RzPanel1: TRzPanel;
RzBmpButton1: TRzBmpButton;
procedure CHButton1Click(Sender: TObject);
procedure RzBmpButton1Click(Sender: TObject);
procedure RzPanel1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure RzPanel1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure RzPanel1MouseEnter(Sender: TObject);
procedure RzBmpButton1MouseEnter(Sender: TObject);
procedure FormMouseEnter(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form7: TForm7;
MyCloseButton : TButtonClose;
implementation
{$R *.dfm}
// constructor for on the fly component created
constructor TButtonClose.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// Set Events for the component
Self.OnMouseEnter := Self.CloseButtonMouseEnter;
Self.OnMouseDown := Self.MouseDown;
Self.OnMouseUp := Self.MouseUp;
Self.Height := 25;
// Close button on top panel Button
// Inherited from Raize Bitmap Button
CloseButton := TRzBmpButton.Create(self);
// Set On Click Event for Close Button
CloseButton.OnClick := Self.CloseButtonClick;
// Place Close Button on Panel Button
CloseButton.Parent := self;
CloseButton.Left := 10;
CloseButton.Top := 5;
CloseButton.Visible := False;
// Setting the image for the button
CloseButton.Bitmaps.Up.LoadFromFile(ExtractFilePath(Application.ExeName)+'\close.bmp');
end;
procedure TButtonClose.CloseButtonClick(Sender: TObject);
begin
// Free the parent (Panel Button)
TControl(Sender).Parent.Free;
end;
procedure TButtonClose.CloseButtonMouseEnter(Sender: TObject);
begin
// Show the Close button
CloseButton.Visible := True;
end;
procedure TButtonClose.MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
// Emulate Button down state, since it is panel
TRzPanel(Sender).BorderOuter := fsLowered;
end;
procedure TButtonClose.MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
// Emulate Button up state, since it is panel
TRzPanel(Sender).BorderOuter := fsRaised;
end;
destructor TButtonClose.Destroy;
begin
inherited Destroy;
end;
procedure TForm7.FormCreate(Sender: TObject);
begin
// Create Panel Button on the fly
MyCloseButton := TButtonClose.Create(self);
MyCloseButton.Caption := 'My Button';
MyCloseButton.Left := 10;
MyCloseButton.Top := 10;
// Don't forget to place component on the form
MyCloseButton.Parent := self;
end;
procedure TForm7.FormMouseEnter(Sender: TObject);
begin
if Assigned(RzBmpButton1) then
RzBmpButton1.Visible := False;
// Hide when mouse leave the button
// Check first if myCloseButton Assigned or not before set visible property
if Assigned(MyCloseButton.CloseButton) then
MyCloseButton.CloseButton.Visible := False;
end;
procedure TForm7.RzBmpButton1Click(Sender: TObject);
begin
TControl(Sender).Parent.Free;
end;
procedure TForm7.RzBmpButton1MouseEnter(Sender: TObject);
begin
RzBmpButton1.Visible := True;
end;
procedure TForm7.RzPanel1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
TRzPanel(Sender).BorderOuter := fsLowered;
end;
procedure TForm7.RzPanel1MouseEnter(Sender: TObject);
begin
RzBmpButton1.Visible := True;
end;
procedure TForm7.RzPanel1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
TRzPanel(Sender).BorderOuter := fsRaised;
end;
procedure TForm7.CHButton1Click(Sender: TObject);
begin
FreeAndNil(Sender);
end;
end.
- 1. Delphi組件運行時創建
- 2. 在運行時創建的對象上雙擊事件 - Delphi
- 3. Delphi組件創建設計時間
- 4. Flex動態組件運行時創建
- 5. Delphi 2009 - 在運行時創建TPanel並更改其顏色
- 6. 在運行時根據類類型創建Delphi對象
- 7. 在運行時創建jrxml文件並在運行時修改
- 8. 我在運行時創建的Swing組件不顯示在JPanel
- 9. 在運行時創建控件
- 10. 放在運行時創建的控件
- 11. 如何在運行時創建控件?
- 12. 在運行時創建用戶控件
- 13. 在運行時創建控件
- 14. 在運行時創建並填充ImageList
- 15. 在運行時創建Tframes:
- 16. 在運行時創建TabView?
- 17. 創建它在運行時
- 18. 防止Delphi IDE在設計時創建組件圖標
- 19. 創建運行時
- 20. 在Java運行時創建具有監聽器組件
- 21. 角度,在運行時編譯和創建組件
- 22. 在運行時創建的複合Android組件
- 23. 在運行時獲取新創建組件的名稱
- 24. 在運行時創建組件傳播viewModel
- 25. 如何引用在運行時創建的組件,而不是在表單設計器中創建的組件?
- 26. Flex在運行時組件
- 27. 創建WPF運行時控件
- 28. 在TFS下運行Delphi構建MSBuild
- 29. 將圖形添加到運行時創建的組件
- 30. 爲本機Windows運行時組件創建nuget包
需要將指針傳遞給元素的所有者。 TButton.Create(所有者); – 2009-06-17 06:17:13
此代碼不會編譯 – 2009-06-17 06:24:11
>需要所有者 不一定。 TButton.Create(無);是有效的代碼。但是你現在需要明確地銷燬它。用零業主創建可視化組件有時候很有用。 – Despatcher 2009-06-17 13:30:02