Создание компонентов во время выполнения - Delphi

Как я могу создать компонент во время выполнения, а затем работать с ним (изменение свойств и т. Д.)?

delphi,runtime,components,

19

Ответов: 9


60 ов принято

Это зависит от того, является ли это визуальным или невизуальным компонентом. Принцип тот же, но есть некоторые дополнительные соображения для каждого вида компонента.

Для невизуальных компонентов

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;

23

Чтобы упростить процесс создания компонента времени выполнения, вы можете использовать GExperts .

  1. Создайте компонент (или несколько компонентов) визуально и установите его свойства.
  2. Выберите один или несколько компонентов и выполните команду GExperts, Components to Code.
  3. Вставьте сгенерированный код в ваше приложение.
  4. Удалите компоненты (компоненты) из конструктора визуальной формы.

Пример (код создания 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;

4

Я хотел бы добавить, что при динамическом добавлении элементов управления ... это хорошая идея добавить их в список объектов (TObjectList), как предлагается в <1> by @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;

Вам нужно добавить «Contnrs» в список «Uses». Т.е. 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, возможно, в форме create event ...

checkBoxCntrlsList := TObjectList.Create;
comboboxCntrlsList := TObjectList.Create;

1

Но если я не знаю, сколько компонентов я хочу создать, например, если это зависит от решения пользователя. Итак, как я могу объявить компоненты динамически?

Ответ был предложен - самым простым способом является Список объектов (компонентов). 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;

Список объектов может содержать любой объект визуальный или нет, но это дает дополнительные накладные расходы на сортировку, из каких элементов - лучше иметь связанные списки, если вы хотите, например, использовать несколько динамических элементов управления на аналогичных панелях.

Примечание: как и другие комментаторы, я, возможно, слишком упрощен для краткости, но надеюсь, что вы идете. Вам нужен механизм для управления объектами, когда они созданы, и списки отлично подходят для этого материала.


1

Во время исследования «создание формы delphi с использованием шаблона на основе xml» я нахожу что-то полезное, указывающее RTTI и использую открытые инструменты api (ToolsApi.pas, я думаю). Посмотрите на интерфейсы в блоке.

Дельфы, во время выполнения, компоненты,
Похожие вопросы