[ vortex77 @ 18.04.2007. 10:36 ] @
Problem je sledeci:

Imam aplikaciju u kojoj dinamicki kreiram frejmove ( u run-time-u). Da bih to uradio deklarisao sam globalnu promenjivu Frame : TFrame i panel (Holder) koji mi sluzi kao parent za kreiranje frejma. Sve ovo radi super dok se isti frejm ne pozove cetiri puta uzastopce (pozivanje frejma sam odradio na onClick button-a). Kada cetvrti put pritisnem dugme, funkcija Free, koja bi trebala da unisti prethodno napravljen frejm, izbaci error "Invalid pointer operation". Posle ovoga prilikom kreiranja frejma (logicno) izlece greska "A component already exists" i cela aplikacija poludi.

Da bih malo razjasnio.. evo i koda :

Code:

var
  Frame : TFrame; 

procedure TForm1.Button1Click(Sender: TObject);
begin
  try
    Frame.Free;
  except
    //
  end;

  Frame := TMojFrame.Create(Self); {TMojFrame je unapred napravljeni frejm}
  Frame.Parent := Holder;
end;


Kako da ovo resim?????
[ Milan Milosevic @ 18.04.2007. 11:07 ] @
Umesto free koristi proceduru FreeAndNil tako kad sledeci put zelis da ponistis klasu iz memorije proveri dali uopste postoji If TMojFrame <> nil then FreeAndNil(TMojFrame) .
Moj ti je savet da izbegavas dinamicko kreiranje objekata tako ces sebe da postedis slicnih gresaka.

To se i meni ranije cesto desavalo pa sam taj nacina programiranja batalio.
[ X Files @ 18.04.2007. 11:54 ] @
Ne bih baš mogao da se složim sa savetom da se izbegava dinamičko kreiranje objekata.

Tačno je da to može da pravi probleme, ali se to uglavnom događa iz nekog razloga u kome
je autor koda projektovao softver tako da nema punu kontrolu nad onime što se dešava
'iza scene'.

Što se tiče TFrame-a, slažem se sa savetom da je poželjno (ponekad možda i neophodno)
Nil-ovali obrisani objekat. Takođe ako se dobro sećam, pri dinamičkom kreiranju više objekata
izvedenih iz istog Frame-a potrebno je promeniti i Name osobinu za svaki novi TFrame, drugim
rečima dati mu novo, jedinstveno ime.
[ Milan Milosevic @ 18.04.2007. 13:12 ] @
Slazem se da nemozemo uvek da izbegnemo dinamicko programiranje. Ponekad je cak i neophodno, ali ga treba svesti na najmanju mogucu meru.
Meni se desavalo da sve radi kako treba. I da se problemi pocnu javljati posle 100-ne i 100 redova koda. A kad to krene nema kraja problemima. Krpis jednu rupu a javljaju se jos dve.
Treba uzeti u obzi upozorenja compajlera i na vreme ih eliminisati. To moze mnogo da pomogne. Inicirati promenjive i.t.d.
[ Miloš Baić @ 18.04.2007. 13:17 ] @
Nisam radio sa TFrame, ali sam na brzinu isprobao jednu varijantu.
Dakle, imamo TForm1 i TFrame, nazovimo ga "FrameTest". Na TForm1 imamo TButton:
Code:

...
procedure TForm1.Button1Click(Sender: TObject);
var FrameTest: TFrame;
begin
 FrameTest:= TFrameTest.Create(nil);
 FrameTest.Parent:= Form1;
end;
...

Na TFrameTest postavimo TButton:
Code:

...
procedure TFrameTest.Button1Click(Sender: TObject);
begin
 Destroy;
end;

procedure TFrameTest.FrameExit(Sender: TObject);
begin
 Free;
end;
...

Možda ti nešto od ovoga pomogne.

[Ovu poruku je menjao Miloš Baić dana 18.04.2007. u 14:38 GMT+1]
[ vortex77 @ 18.04.2007. 13:38 ] @
Mislim da je to TO!

U stvari problem je bio u nekim modifikacijama koje sam odradio na delphi native fajlovima, ali sam u medjuvremenu pronasao i otkonio bug. Dinamicko kreiranje mi je trenutno neophodno i koristim ga samo za prikaz podataka koje izvlacim iz baze. Ostatak aplikacije (koja sada vec ima oko 100-tinjak faljova) baziran je uglavnom na formovima.

Bilo kako bilo, Hvala na brzim i opseznim odgovorima
[ morlic @ 19.04.2007. 14:39 ] @
Destroy metod ne treba nikad, ali nikad, zvati direktno. Metod Free to radi za nas i proverava da li je pokazivac na Self koji ima ispravan pointer, u smislu da li je NIL ili nije. Tu dolazi do smisla ona FreeAndNil varijanta. Na taj nacin sve je lepo uvezano.

Ja podrzavam dinamicko kreiranje, samo napominjem da pre toga treba dobro izuciti na koji nacin klase funkcionisu, kako "egzistiraju" objekti memoriji, sta je sta je TReader, TWriter, sta je TPersistent, kako VCL vrsi enkapsulaciju Windows GDI objekata itd. Ima tu svasta.

Cim se sa vizuelnog editora forme "sidje" u kod, potrebno je pristojno poznavanje navedenih stvari, da bi se dobio naravno kvalitetan rezultat.
[ Miloš Baić @ 19.04.2007. 16:28 ] @
Ajd, kad smo kod ovog problema, razmotrimo sledeći primer, koji bi možda mogao nekad iskoristiti. Hteo bih više fejmova koristiti na TForm u okviru jednog TPanel -a, u zavisnosti od potrebe.

Imamo dva TFrame -a:
1) FrameTest1
2) FrameTest2

Na oba imamo TButton, TEdit, TListBox, etc., samo je koncepcija drugačija. Na TForm1 imamo TPanel na kojem želimo prikaz jednog od ova dva TFrame -a u zavisnosti od potrebe.

Zbog jednostavnosti, na frejmovima imamo samo:
Code:

...
initialization
  RegisterClass (TFrameTest1); //na drugom frejmu RegisterClass (TFrameTest2);

end.

Na TForm1 imamo TPanel i dva TRadioButton -a, TButton(OnClick), za primer:
Code:

...
  public
    { Public declarations }
    Frame: TFrame;
    procedure ShowFrame(FrameName: string);
...
type
  TFrameClass = class of TFrame;
...
procedure TForm1.ShowFrame(FrameName: string);
var
  FrameClass: TFrameClass;
begin
    FrameClass := TFrameClass (FindClass ('T' + FrameName));
    Frame := FrameClass.Create (Self);
    Frame.Parent := Panel1;
    Frame.Visible := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Frame.Free;

 if RadioButton1.Checked then
   ShowFrame('FrameTest1')
 else
   ShowFrame('FrameTest2');
end;
...

Predlozi za neko elegantnije rešenje?

[ priki @ 21.04.2007. 08:43 ] @
prva stvar
stavio si ovo:
Code:

  TMojFrame.Create(Self)


sto znaci, kad ti se parent forma oslobodi, oslobadja se i frame
ako si tako organizovao aplikaciju , to ne ide tako
(malo ti je memory handling sa formama i frame-ovima nikakav)

kad vise puta pozivas neku formu ili frame
OBAVEZNO moras proveravati da li je ta forma vec postoji u memoriji,
ako postoji, moras je osloboditi ili
ako ne postoji, ne smes je oslobadjati

jer ako oslobadjas nesto sto nema ili
kreiras nesto sto je vec kreirano, naravno da je greska

neko to radi ovako
Code:

if _frame<>nil then
  FreeAndNil(_frame)


ja ti preporucujem funkciju Assigned:
jer je mnogo sigurnije kad radis sa formama i pointerima
procitaj u Helpu

Code:

  if assigned(_frame) then
    _frame.Free


Tvoje drugo pitanje
recimo, ja bi napravio neki spisak frame-ova koji bi svaki put
ucitavao u neku globalnu string listu i kad mi zatrebao neki frejm,
malo bi procunjao po StringListi da li postoji, ako postoji,
onda bi ga "pustio" kroz neki Frame pooler gde bi prethodne frameove ili frejm
oslobadjao iz memorije a novi kreirao frameove i "lepio" za tu parent
formu odakle sam ga pozvao

nemas potrebe za registerclass i tome slicno

pozdrav