Dynamiczne utworzenie nieznanej liczby komponentów

0

Witam,
chcę utworzyć dynamicznie komponenty, ale ich ilość ma wprowadzić użytkownik np w Edit.
Lecz po ich stworzeniu, chciałbym mieć możliwość ich usunięcia.

Pierwszą część można zrobić tak:

 
    for I :=1 to ilosc_komponentow do
    begin

        Edit:=TEdit.Create(Form_wydatkow);
        Edit.Parent:=Form_wydatkow; // rodzic przycisku
        Edit.Width := 60;
        Edit.Height := 21;
        Edit.Left := MaskEdit1.Left;
        Edit.Top := MaskEdit1.Top + i*(Edit.Height+10);
        Edit.Visible := True;
        Edit.Name := 'Edit'+IntToStr(i+2);
    end;

Ale nie wiem jak je teraz mogę usunąć, więc chyba to rozwiązanie odpada.

Proszę o pomoc!

3

Obiekty wszystkich utworzonych komponentów wpakuj do tablicy dynamicznej, całość zrób w pętli od 0 to n-1, gdzie n to liczba komponentów, którą podaje użytkownik; Przy usuwaniu komponentów skorzystaj z tej tablicy;

TForm1 = class(TForm)
{..}
private
  FEditsArr: array of TEdit;
{..}
end;


{ tworzenie listy editów }
var
  intEditIdx: Integer;
begin
  SetLength(FEditsArr, {tu ilość editów do utworzenia});

  for intEditIdx := Low(FEditsArr) to High(FEditsArr) do
  begin
    FEditsArr[intEditIdx] := TEdit.Create({tu Twój formularz});
    {..}
  end;
end;


{ usuwanie listy editów }
var
  intEditIdx: Integer;
begin
  for intEditIdx := Low(FEditsArr) to High(FEditsArr) do
    FEditsArr[intEditIdx].Free();

  SetLength(FEditsArr, 0);
end;
6

Ja do tego raczej wykorzystałbym TObjectList jest to lepsze rozwiązanie od tablicy ponieważ pozwala na większą kontrolę:

  • właściwość OwnObjects aby pozbyć się wszystkich kontrolek wystarczy usunąć listę
  • możliwość usunięcia w dowolnym momencie dowolnego obiektu
  • w nowych Delphi (obsługujących typy generyczne możemy sobie zdefiniować typ TEditList = TObjectList<TEdit> i już mamy listę Editów co pozwala nam odnosić się do nich bez rzutowania
  • nie wiem co jeszcze bo za wcześnie i nawet kawy jeszcze nie wypiłem ;)
    Przykład dla nowych Delphi:
//do uses Generics.Collections
type
  TEditList = TObjectList<TEdit>;
//...
  private
    { Private declarations }
    fEditList: TEditList;
//...
var
  i, iEditCount: Integer;
  Edit: TEdit;
begin
  iEditCount:= 3;
  fEditList:= TEditList.Create(); //dzieki OwnObjects aby pozbyc sie wszyskich editow wystarczy usunac liste
  for i:=0 to Pred(iEditCount) do
  begin
    Edit:= TEdit.Create(Form1);

    Edit.Parent:= Form1; // rodzic przycisku
    Edit.Width:= 60;
    Edit.Height:= 21;
    Edit.Left:= 10;
    Edit.Top:=  10 + i *(Edit.Height + 10);
    Edit.Visible:= True;
    Edit.Name:= 'Edit'+IntToStr(i +2 );

    fEditList.Add(Edit);
  end;

  fEditList.Items[0].Text:= 'Test'; //przyklad odwolania sie do Edita

  fEditList.Delete(0); //przyklad usuniecia tylko jednego (w tym wypadku pierwszego) edita

  fEditList.Free; //usuwanie wszyskich editow
end;
0

Dzięki!

A Pytanie jeszcze takie:
Jak ustawić dla nich zdarzenie KeyPress ?

1

Tak samo jak przypisuje się nowe metody zdarzeniom dla pojedynczych komponentów; Tutaj jedyna różnicą jest to, że odwołujesz się poprzez element listy, a nie bezpośrednio poprzez identyfikator komponentu;

fEditList.Items[TuIndeks].OnKeyPress := TwojaMetodaKeyPress;

Ewentualnie przypisz ją w pętli, posługując się zmienną pomocniczą Edit:

Edit.OnKeyPress := TwojaMetodaKeyPress;

Pamiętaj, że TwojaMetodaKeyPress musi mieć takie same argumenty jak standardowe zdarzenie; Zadeklaruj sobie ją w klasie formularza:

private
  procedure TwojaMetodaKeyPress(Sender: TObject; var Key: Char);

i zdefiniuj według własnego uznania.

1

Tak przy okazji to może podam rozwiązanie dla Free Pascala (a dokładnie dla Lazarusa); Do tej pory nie korzystałem z generyków - Delphi7 ich nie wspierało, a przez ostatnie kilka lat pisania dla FPC jakoś nie potrzebowałem ich używać;

Popatrzyłem trochę do dokumentacji i manuali Free Pascala i... składnia jest zupełnie inna niż w przypadku obecnego standardu Delphi; Ale to dotyczy tylko deklaracji typu - w dalszej części użycie listy jest takie samo jak w Delphi;

Poniżej podaję przykład robiący to samo co pokazał @kAzek, tyle że w Lazarusie:

uses
  {..}, FGL, {..};

type
  generic TEditsList<TEdit> = specialize TFPGObjectList<TEdit>;

type
  TForm1 = class(TForm)
    btnGenerate: TButton;
    seEditsCount: TSpinEdit;
    procedure btnGenerateClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FEditsList: TEditsList;
  private
    procedure OwnEditKeyPress(Sender: TObject; var Key: Char);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FEditsList := TEditsList.Create();
end;

procedure TForm1.btnGenerateClick(Sender: TObject);
var
  edtNew: TEdit;
  intEditIdx: Integer;
begin
  FEditsList.Clear();

  for intEditIdx := 0 to seEditsCount.Value - 1 do
  begin
    edtNew := TEdit.Create(Self);

    edtNew.Parent := Self;
    edtNew.OnKeyPress := @OwnEditKeyPress;

    edtNew.Width := 100;
    edtNew.Height := 21;
    edtNew.Left := 16;
    edtNew.Top := 50 + intEditIdx * 25;
    edtNew.Text := Format('Edit no %d', [intEditIdx]);

    FEditsList.Add(edtNew);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FEditsList.Free();
end;

procedure TForm1.OwnEditKeyPress(Sender: TObject; var Key: Char);
begin
  if not (Key in ['A' .. 'Z']) then
    Key := #0;
end;

end.

Wszystko działa - pola edycyjne tworzą się prawidłowo, nowe zdarzenie filtruje poprawnie wprowadzane znaki; Czyli wszystko działa tak jak należy; Muszę się w końcu więcej pobawić tymi generykami.

1 użytkowników online, w tym zalogowanych: 0, gości: 1