[Delphi] Usuwanie komponentu z innej procedury

0

Tworze sobie komponent dynamicznie, np:

procedure TfrmMain.WstawListB(X,Y:integer);
var
ListaAuto: TListBox;
begin
ListaAuto:=TListBox.Create(FormAuto);
ListaAuto.Parent:=FormAuto;
ListaAuto.Align:=alClient;
ListaAuto.Items:=ListBox1.Items;
ListaAuto.OnClick:=OnListaAutoClick;
FormAuto.Show;
end;

Teraz czy da sie usunąć ten komponent ListaAuto.Free z zupełnie innej prcedury, ale tak żebym nie musiał tej zmiennej dawać jako globalnej?

0

Możesz ją do tej procedury przekazać jako parametr.

0

Jestem początkujący i chyba nie bardzo wiem jak to zrobić :(

0

To do Newbie :P

procedure ZwalniamyListBoxa(var ListBox: TListBox);
begin
  // ...
  ListBox.Free;
  Integer(ListBox) := 0;
end;

Zastosowałem przekazywanie przez referencję tylko dlatego, żeby ustawić potem wartość nil dla zmiennej. Jeśli możesz obejść się bez ustawiania wartości nil, usuń słówko var przy parametrze ListBox.
Teraz w funkcji WstawListB() klepiesz ZwalniamyListBoxa(ListaAuto); i wszystko.

// EDITED:
Chyba Cię nie zrozumiałem, chcesz usunąć później tego ListBoxa, bez odwołania do tej procedury usuwającej z tej tworzącej, tak? To w takim wypadku pozostanie tablica FormAuto.Controls[] .

// EDITED 2:
{PIT}, przekazanie przez referencję nie jest konieczne, bo przekazujesz wskaźnik na obiekt (liczbę 32-bitową); jeśli nie chcesz zmienić tego wskaźnika (w sensie wartości tej liczby, nie modyfikacji obiektu), wystarczy przekazywanie przez wartość. Ja wykorzystałem referencję, bo na końcu wyzerowałem wskaźnik.

0

Przekazujesz swój utworzony obiekt do procedury zwalniającej przez referencję a nastepnie w tej procedurze go zwalniasz tzn.:

procedure TworzObiekt;
var
  obiekt: TJakisObiekt;
begin
  obiekt:=TJakisObiekt.Create;
  ZwolnijObiekt(obiekt);
end;

procedure ZwolnijObiekt(var obj: TJakisObiekt);
begin
  obj.Free;
end;

:)

//Dopisane: Spóźniłem się z odpowiedzią ;)

//Dopisane2: brodny - dzieki za cenna wskazówke :)

0

Chodziło o to że np. tworze komponent:

procedure TfrmMain.WstawListB;
var
ListaAuto: TListBox;
begin
ListaAuto:=TListBox.Create(FormAuto);
ListaAuto.Parent:=FormAuto;
ListaAuto.Align:=alClient;
ListaAuto.Items:=ListBox1.Items;
ListaAuto.OnClick:=OnListaAutoClick;
FormAuto.Show;
end;

Teraz mam np. inną procedure

procedure TfrmMain.OnButtonClick(Sender: TObject);
begin
ListaAuto.Free //tutaj wlasnie chcialbym jakos "wdostac" sie do procedury WstawListB i usunąć listboxa
end;

BTW: Nie wiecie dlaczego jak usuwam dynamiczną forme na której jest dynamiczny ListBox poprzez Form.Free to mi wywala błąd ? Nosi nazwe "Abstract Error"

0
for i := 0 to ListaAuto.ControlCount-1 do ListaAuto.Controls[i].Free;
ListaAuto.Free;
0

Błąd mi dalej wywala :-/

0
  1. zamiast robić ją globalną daj ją do sekcji private formy
  2. jeśli zwalniasz dynamiczną kontrolkę ręcznie to ovnera daj jej nil
  3. obiektu nie trzeba do procedur przekazywać przez var - tak naprawdę przez parametr przekazywany jest tylko wskaźnik do tego obiektu a nie jego kopia więc czy będzie var czy nie to i tak zmienia się ten sam obiekt
0

1. zamiast robić ją globalną daj ją do sekcji private formy
A czy to zmniejszy troche wykrozystanie pamieci ?

0
Dibo84 napisał(a)

1. zamiast robić ją globalną daj ją do sekcji private formy
A czy to zmniejszy troche wykrozystanie pamieci ?

masz trochę mylne pojęcie o obiektach i zajmowaniu przez nie pamięci. A więc tak obiekt zajmuje pamięć do momentu, kiedy tej pamięci nie zwolnisz przez

Obiect.Free

lub FreeAndNil(Obiect)

 nie ważne, gdzie zostanie zadeklarowany.
0

Tak tylko że np. przy tworzeniu dynamicznie listboxa pamieci zostaje przydzielana wtedy kiedy faktycznie jego uzywam/potrzebuje/tworze oraz zwalniana wtedy kiedy nie potrzebuje. Jak dam w sekcji private to pamiec zostanie przydzielona na samym starcie programu, a moze znowu sie myle ? :)

0

Mylisz się (tzn nie do końca), bo deklarując obiekt w sekcji private formy, deklarujesz tylko wskaźnik do niego (czyli zajmuje on 4 bajty). Pamięć dla obiektu alokowana jest dopiero przy wywołaniu konstruktora i zwalniana przy użyciu Free().

0

Poruszone zostały tutaj 2 ciekawe problemy.

Dibo94 napisał(a)

BTW: Nie wiecie dlaczego jak usuwam dynamiczną forme na której jest dynamiczny ListBox poprzez Form.Free to mi wywala błąd ? Nosi nazwe "Abstract Error"

Wyjątek "Abstract Error" występuje w przypadku wywołania metody abstrakcyjnej obiektu. Jest to w skrócie mówiąc niezaimplementowana metoda, która ma być podstawą przedefiniowana w klasie pochodnej. Kompilator chyba nie wyłapuje tego jako błędu (co najwyżej pokaże ostrzeżenie, ale nie jestem tego pewny, możliwe, że bez piśnięcia przejdzie obok takiego kodu) ze względu na polimorfizm.

Misiekd napisał(a)
  1. obiektu nie trzeba do procedur przekazywać przez var - tak naprawdę przez parametr przekazywany jest tylko wskaźnik do tego obiektu a nie jego kopia więc czy będzie var czy nie to i tak zmienia się ten sam obiekt

Nie przeczytałeś, co napisałem. A napisałem, że nie trzeba przekazywać przez var, ale zrobiłem tak, gdyż chciałem wyzerować zmienną tak, aby nie pokazywała na przypadkowy fragment pamięci. Odwołanie się do pustego wskaźnika (zerowego, nil) spowoduje zawsze wyjątek EAccessViolation, natomiast odwołanie do "losowej" pamięci jest nieprzewidywalne w skutkach. Jeśli nie chcesz zmieniać zawartości samej zmiennej (w sensie wartości wskaźnika, a nie wywoływać metody obiektu) - nie musisz przekazywać go przez referencję.

0

Wow ale sie zakręciłem :D . Chyba zrobie tak że zadeklrauje w sekcji private ibedzie po kłopocie (musze w tej sekcji chyba dopisać VAR nie ?). A co do tego błędu to jak to z nim jest, bo dla mne troche za fachowo napisane :D

0
procedure TfrmMain.WstawListB(X,Y:integer);
var
ListaAuto: TListBox;
begin
ListaAuto:=TListBox.Create(FormAuto);
ListaAuto.Name := 'TwojaNazwa';
ListaAuto.Parent:=FormAuto;
ListaAuto.Align:=alClient;
ListaAuto.Items:=ListBox1.Items;
ListaAuto.OnClick:=OnListaAutoClick;
FormAuto.Show;
end;

procedure TfrmMain.DelLista;
begin
  FormAuto.FindComponent('TwojaNazwa').Free;
end;
0
type
  TForm1 = class(TForm)
  ...
  private
    ListBox: TListBox;
    ...
  end;

żadnego var nie trzeba

Edit: Deti tylko wiesz zazwyczaj komponent po cos jest na formie i jeśli chcesz cokolwiek z nim zrobić to FindComponent za każdym razem to nie jest dobre rozwiązanie. Co się tak uparliście, żeby nie mieć zmiennej globalnej tylko lokalną. Czy te 4 bajty powodują taki wielki przyrost pamięci wykozystywanej przez program??

// chciał usunąć - deti

0

Deti a co jak FormAuto bedzie też w tej procedurze zadeklarowana i to wlasnie ją chce usunąć? :) Sprawdzi sie Findwindows itd ?

0

Jak przypiszesz właściciela (Owner) - to tak. (chyba chodzi o właściciela, no nie? :) )

0

Edit: Deti tylko wiesz zazwyczaj komponent po cos jest na formie i jeśli chcesz cokolwiek z nim zrobić to FindComponent za każdym razem to nie jest dobre rozwiązanie.

Ale dlaczego za każdym razem ma używać FindComponent()? Ja nic takiego nie napisałem, dałem tylko przykład jak usunąć. Zawsze można zadeklarować lokalnie: class of TComponent, przypisać wskaźnik i na nim działać.

0

Zwykły wskaźnik na TComponent powinien starczyć, metaklasa to IMHO przesada.

0

Skoro już zwykły wskaźnik to nie lepiej do TListView?

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