Làm cách nào để tạo một thành phần trong thời gian chạy và sau đó làm việc với nó (thay đổi các thuộc tính, vv)?Tạo các thành phần khi chạy - Delphi
Trả lời
Nó phụ thuộc nếu nó là một thành phần trực quan hoặc không trực quan. Nguyên tắc là như nhau, nhưng có một số cân nhắc bổ sung cho từng loại thành phần.
Đối với các thành phần không nhìn
var
C: TMyComponent;
begin
C := TMyComponent.Create(nil);
try
C.MyProperty := MyValue;
//...
finally
C.Free;
end;
end;
Đối với các thành phần hình ảnh:
Về bản chất các thành phần thị giác được tạo ra trong cùng một cách như các thành phần không nhìn. Nhưng bạn phải đặt một số thuộc tính bổ sung để hiển thị chúng.
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;
Một vài giải thích cho đoạn code trên:
- Bằng cách đặt các chủ sở hữu của các thành phần (các tham số của các nhà xây dựng) các thành phần bị phá hủy khi các hình thức sở hữu bị phá hủy.
- Đặt thuộc tính
Parent
làm cho thành phần hiển thị. Nếu bạn quên nó, thành phần của bạn sẽ không được hiển thị. (Thật dễ dàng để bỏ lỡ một :))
Nếu bạn muốn nhiều thành phần bạn có thể làm tương tự như trên nhưng trong một vòng lặp:
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;
này sẽ bổ sung thêm 10 nút ở bên trái đường viền của biểu mẫu. Nếu bạn muốn sửa đổi các nút sau này, bạn có thể lưu chúng trong một danh sách. (TComponentList ist tốt nhất phù hợp, nhưng cũng hãy nhìn vào các đề xuất từ các ý kiến để câu trả lời này)
Làm thế nào để gán xử lý sự kiện:
Bạn cần phải tạo ra một phương pháp xử lý sự kiện và gán nó vào thuộc tính sự kiện.
procedure TForm1.MyButtonClick(Sender: TObject);
var
Button: TButton;
begin
Button := Sender as TButton;
ShowMessage(Button.Caption + ' clicked');
end;
B := TButton.Create;
//...
B.OnClick := MyButtonClick;
Rất dễ dàng. Gọi Tạo. Ví dụ:
procedure test
var
b : TButton;
begin
b:=TButton.Create(nil);
b.visible:=false;
end;
Điều này tạo thành phần (TButton là một thành phần) trong thời gian chạy và đặt thuộc tính hiển thị.
Đối với nhà xây dựng: vượt qua nếu bạn muốn tự quản lý bộ nhớ. Vượt qua một con trỏ khác thành phần nếu bạn muốn có nó bị phá hủy khi các thành phần khác bị phá hủy.
Cần chuyển con trỏ đến chủ sở hữu phần tử. TButton.Create (chủ sở hữu); –
Mã này không biên dịch –
> cần cho chủ sở hữu Không nhất thiết. TButton.Create (nil); là mã hợp lệ. nhưng bây giờ bạn cần phải tiêu diệt nó một cách rõ ràng. Tạo các thành phần trực quan với một chủ sở hữu nil đôi khi hữu ích. – Despatcher
Để đơn giản hóa quá trình tạo thành phần thời gian chạy, bạn có thể sử dụng GExperts.
- Tạo thành phần (hoặc nhiều thành phần) trực quan và đặt thuộc tính của nó.
- Chọn một hoặc nhiều thành phần và thực thi GExperts, Components thành Code.
- Dán mã được tạo vào ứng dụng của bạn.
- Xóa (các) thành phần khỏi trình thiết kế biểu mẫu trực quan.
Ví dụ:
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;
Mẹo hay! Đó là chính xác những gì tôi đã đề nghị. GExperts là một công cụ tuyệt vời để sử dụng với Delphi. –
... hoặc bạn có thể thiết kế nó trong trình chỉnh sửa trực quan và sau đó lấy một đỉnh vào tệp .dfm. Về cơ bản, điều tương tự cũng có trong văn bản – Earlz
Gracias. Tôi thích viết tất cả mọi thứ một mình (tôi biết đó có thể là phát minh lại bánh xe nhưng tôi cảm thấy có nhiều kiểm soát hơn) dù sao dường như công cụ GExpert không thay đổi trong mã thuần và âm thanh tốt. Cảm ơn một lần nữa để được tư vấn. – QMaster
Nhưng nếu tôi không chắc chắn biết có bao nhiêu thành phần tôi muốn tạo, ví dụ nếu nó phụ thuộc vào quyết định của người dùng. Vậy làm thế nào tôi có thể khai báo các thành phần động?
Câu trả lời đã được đề xuất - cách dễ nhất là Danh sách đối tượng (thành phần). TObjectList là đơn giản nhất để sử dụng (trong đơn vị contnrs). Danh sách rất tuyệt!
In Form1 Public
MyList: TObjectList;
procedure AnyButtonClick(Sender: TObject);
// Bạn có thể tinh vi hơn và khai báo // TNotifyevents và chỉ định chúng nhưng hãy để đơn giản :) . . .
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;
Danh sách đối tượng có thể chứa bất kỳ đối tượng nào - tốt hơn để có danh sách liên quan nếu bạn muốn nhiều điều khiển động trên các bảng tương tự chẳng hạn.
Lưu ý: giống như những người nhận xét khác, tôi có thể đã đơn giản hóa quá mức cho ngắn gọn nhưng tôi hy vọng bạn định vị ý tưởng đó. Bạn cần một cơ chế để quản lý các đối tượng khi chúng được tạo ra và danh sách là tuyệt vời cho công cụ này.
Một số thành phần ghi đè phương thức 'Đã tải'. Phương thức này sẽ không được gọi tự động nếu bạn tạo một cá thể khi chạy. Nó sẽ được gọi bởi Delphi khi tải từ tệp biểu mẫu (DFM) hoàn tất.
Nếu phương pháp chứa mã khởi tạo, ứng dụng của bạn có thể hiển thị hành vi không mong muốn khi được tạo khi chạy. Trong trường hợp này, hãy kiểm tra xem nhà văn thành phần đã sử dụng phương pháp này chưa.
Nếu bạn lồng điều khiển thắng trong Hộp nhóm/Điều khiển trang/v.v ..., tôi nghĩ có lợi khi có hộp nhóm chính cũng là chủ sở hữu. Tôi đã nhận thấy một sự sụt giảm mạnh trong thời gian đóng cửa sổ khi làm điều này, trái với việc chủ sở hữu luôn là hình thức chính.
Trong một nghiên cứu về "tạo biểu mẫu delphi sử dụng mẫu dựa trên xml", tôi tìm thấy điều gì đó hữu ích chỉ ra RTTI và sử dụng các công cụ mở api (ToolsApi.pas tôi nghĩ). Có một cái nhìn tại các giao diện trong đơn vị.
Tôi chỉ muốn thêm điều đó khi tự động thêm điều khiển ... làm ý tưởng tốt để thêm chúng vào danh sách đối tượng (TObjectList) như được đề xuất trong < 1> bởi @Despatcher.
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;
Bạn cần thêm đơn vị 'Contnrs' vào danh sách Sử dụng. I.e System.Contnrs.pas Vùng chứa Đơn vị cơ sở Và bạn có thể có nhiều danh sách đối tượng. Tôi khuyên bạn nên sử dụng TObjectList cho từng loại điều khiển mà bạn sử dụng ví dụ:
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
điều này cho phép bạn dễ dàng thao tác/quản lý từng điều khiển vì bạn sẽ biết loại điều khiển nào, ví dụ:
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;
này cho phép bạn sau đó sử dụng các phương pháp và thuộc tính của điều khiển mà Đừng quên để tạo ra các TObjectLists, có lẽ trong các hình thức tạo sự kiện ...
checkBoxCntrlsList := TObjectList.Create;
comboboxCntrlsList := TObjectList.Create;
Đây là ví dụ cách mô phỏng thẻ nút trên 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. Các thành phần cần tránh trong Delphi
- 2. Chỉ tạo một thành phần VCL trong Delphi
- 3. Delphi - TXMLTài liệu được tạo tại thời gian chạy tạo AV, với thành phần trên biểu mẫu đang hoạt động
- 4. Đặt chiều rộng thành phần Flex thành 100% khi chạy?
- 5. Tạo thành phần - Tham gia các thành phần cùng nhau?
- 6. thành phần delphi để hiển thị/ẩn các điều khiển trong thời gian chạy
- 7. TWAIN quét thành phần cho Delphi
- 8. Các thành phần kiểm tra chính tả cho Delphi
- 9. Trạng thái thành phần Delphi XE2 TurboPower
- 10. Thành phần ZIP miễn phí cho Delphi 2010/Delphi XE?
- 11. Các thành phần Delphi để sử dụng với SQlite
- 12. JQuery fadeIn() khi tạo thành phần DOM?
- 13. Cài đặt Inno: Ẩn/Tắt thành phần khi chạy
- 14. Tạo thành phần Liên minh và kiểu Macrodef với nội dung động khi chạy trong Ant
- 15. Delphi Designer, Thành phần có được kế thừa không?
- 16. Thành phần cập nhật tự động tốt nhất cho Delphi
- 17. Nhân bản các thành phần tại thời gian chạy
- 18. Lớp cơ sở nào để sử dụng khi phát triển thành phần VCL Delphi?
- 19. Tạo thành phần sao chép các giá trị trường từ một thành phần khác
- 20. Cách cài đặt gói thành phần Delphi từ dòng lệnh?
- 21. Hình ảnh thành phần không trực quan delphi
- 22. Delphi và hoàn thành mã trong khi gỡ lỗi
- 23. Có các thành phần xuất OpenOffice.org nào cho Delphi (không phải là OLE) không?
- 24. Neo các thành phần GUI vào FireMonkey
- 25. Chuyển tiếp CSS3 thành các phần tử được tạo động
- 26. Làm thế nào để xử lý các thành phần dự án cụ thể trong Delphi?
- 27. Điều khiển trục z/đưa lên trước khi chạy (Delphi)
- 28. jquery xác thực trên các thành phần chưa được tạo
- 29. Delphi 2007 tạo các thông báo SOAP không chính xác
- 30. Sử dụng các thành phần nhận thức dữ liệu Delphi - ưu và nhược điểm
Nhưng nếu tôi không chắc chắn có bao nhiêu thành phần tôi muốn tạo, ví dụ: nếu nó phụ thuộc vào quyết định của người dùng. Vậy làm thế nào tôi có thể khai báo các thành phần động? –
Sự khác biệt có nên truyền nil hay một thành phần khác vì chủ sở hữu không có gì liên quan đến thành phần đang hiển thị hay không, chỉ với tuổi thọ của đối tượng. Một thành phần vô hình không được giải phóng trong cùng một phương thức có thể được tạo giống như trong đoạn thứ hai của bạn và được chủ sở hữu tự động giải phóng. – mghie
s/visible/visual/g – mghie