문제

런타임에 구성 요소를 생성한 다음 작업(속성 변경 등)하려면 어떻게 해야 합니까?

도움이 되었습니까?

해결책

시각적이거나 시각적이지 않은 구성 요소인지 여부에 따라 다릅니다. 원리는 동일하지만 각 종류의 구성 요소에 대해 몇 가지 추가 고려 사항이 있습니다.

비 시각 구성 요소의 경우

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;

다른 팁

런타임 구성 요소 생성 프로세스를 단순화하려면 사용할 수 있습니다. gexperts.

  1. 구성 요소 (또는 더 많은 구성 요소)를 시각적으로 생성하고 속성을 설정하십시오.
  2. 하나 이상의 구성 요소를 선택하고 코드에 대한 구성 요소, 구성 요소를 실행하십시오.
  3. 생성 된 코드를 응용 프로그램에 붙여 넣습니다.
  4. 시각적 형태 디자이너에서 구성 요소를 제거하십시오.

예제 (이러한 방식으로 생성 된 Tbutton-kreation 코드) :

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' 유닛을 추가해야 합니다.IE 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;

이렇게하면 해당 제어의 메소드와 속성을 사용할 수 있습니다. 아마도 양식 작성 이벤트에서 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를 가리키고 Open Tools API (ToolSapi.Pas)를 사용하는 유용한 것이 있습니다. 장치의 인터페이스를 살펴보십시오.

매우 쉽습니다. Cale Create를 호출하십시오. 예시:

procedure test
var
  b : TButton;
begin
  b:=TButton.Create(nil);
  b.visible:=false;
end;

이것은 런타임에 구성 요소 (tbutton은 구성 요소)를 생성하고 속성을 볼 수 있습니다.


생성자의 경우 : 메모리를 직접 관리하려면 NIL을 통과하십시오. 다른 구성 요소가 파괴 될 때 파괴하려면 다른 구성 요소를 전달하십시오.

일부 구성 요소는 '로드 된'방법을 무시합니다. 런타임에 인스턴스를 만드는 경우이 메소드는 자동으로 호출되지 않습니다. 양식 파일 (DFM)에서로드 할 때 Delphi가 호출합니다.

메소드에 초기화 코드가 포함 된 경우 런타임에 생성 될 때 응용 프로그램에 예기치 않은 동작이 표시 될 수 있습니다. 이 경우 구성 요소 작성자 가이 방법을 사용했는지 확인하십시오.

그룹 상자/페이지 컨트롤/etc에서 컨트롤을 둥지하면 부모 그룹 상자도 소유자가되는 것이 유리하다고 생각합니다. 소유자가 항상 주요 형태가되는 것과는 달리이 작업을 수행 할 때 창 가까운 시간이 급격히 감소하는 것을 보았습니다.

이것은 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.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top