100 tane tform nesnesi yaratıyorum, kapatırken hata oluyor..

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

100 tane tform nesnesi yaratıyorum, kapatırken hata oluyor..

Mesaj gönderen huseyinkucuk »

arkadaşlar merhaba... Şöyle bi kod yazdım:

Tform1.button1click(sender:tobject);
var
formlar:array of tform;
formsayisi:integer;
begin
formsayisi:=high(formlar)+2;
setlength(formlar,formsayisi);
formlar[formsayisi-1]:=tform1.create(form1); //mevcut form "form1" bu arada :)
formlar[formsayisi-1].onclose:=formclose;
formlar[formsayisi-1].show;
end;


procedure TForm1.formclose(Sender: TObject; var Action: TCloseAction);
begin
tform(sender).Free;
end;


şimdi ben button1e basarak bir sürü form yapıyorum (hatta başka bi düğmede button1.clicki kullanarak bi kerede 100 form birden falan yapıyorum) sonra bu oluşan 100 tane formu tek tek kapamaya başlıyorum, arada bir "access violation" hatası veriyor... Sonra ben düşündüm, heralde dedim formlar değişkenini lokal tanımladık diye böyle oluyo, sonra prosedürün dışında tanımladım (lokal olmayarak yani), ama değişen hiçbirşey olmadı... Private ya da publicde denersem belki olur ama benim merak ettiğim bu şekilde niye hata veriyor? Saygılarımla...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
Murat DİCLE
Kıdemli Üye
Mesajlar: 702
Kayıt: 19 Nis 2006 04:12
Konum: İstanbul
İletişim:

Mesaj gönderen Murat DİCLE »

Merhabalar,

Kod: Tümünü seç

.
.
.
var 
   Form1 : TForm1;
   //bunu global değişken olarak tanımlıyoruz..
   Formlar : Array of TForm1;  //te-form-bir

imlepementation
.
.
.
TForm1.Button1Click(Sender:TObject); 
Var 
   FS : integer; //kısa isim makbuldür.
begin 
   FS := High(Formlar) + 2; //güzel kullanmışsın..
   SetLength(Formlar, FS); 
   Formlar[High(Formlar)] := TForm1.create(Application);
   //ya da Formlar[FS-1]
   {
   //buna gerek yok, çünkü Formlar dizisini zaten TFORM1 olarak
   //tanımladık. Bizim Form1 adlı tutamacımız zaten TForm1 nesnesinden
   //türetilmiş, kaldıki Fom1'i create ederken ayrıca
   //Form1.OnCloSe := FormClose diyor muyuz?
   Formlar[High(Formlar)].OnClose := FormClose;
   }
   Formlar[High(Formlar)].Show; 
end; 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
   //Bu formun kapandıktan sonra FREE edilmesini sağlıyacaktır..
   Action := caFree;
end; 
şimdi verdiğin örneğin daha doğru olanını yapalım, çünkü Formlaradlı Tform1 dizisi boşaltılamıyor. Başka bir açıdan bunu şöyle yapalım. Tam kodu veriyorum..

Kod: Tümünü seç

unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm3 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure BaslikYaz;
  end;

var
  Form3: TForm3;
  Formlar : TList;

implementation

{$R *.dfm}

{$DEFINE YontemBir}
//ikinci yöntemi kullanmak isterseniz yukarıkini iptal ediniz.
//ve aşağıdakinin başındaki kesmeleri siliniz..
//{$DEFINE YontemIki}

procedure TForm3.BaslikYaz;
begin
   //Ana formun başlığına bilgi yazıyoruz..
   Application.MainForm.Caption := 'Form Sayısı: ' + IntToStr(Formlar.Count);
end;

procedure TForm3.Button1Click(Sender: TObject);
Var
   F : TForm3;
begin
{$IFDEF YontemBir}
   //biliyorum extreme bir kullanımdır..
   F := TForm3(Formlar.Items[Formlar.Add(TForm3.Create(Application))]);
{$ELSE}
   F := TForm3.Create(Application);
   Formlar.Add(F);
{$ENDIF}
   F.Show;
   BaslikYaz;
end;

procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
var i : integer;
begin
   Action := caFree;
   i := Formlar.IndexOf(Sender);
   if i <> -1 then Formlar.Delete(i);
   BaslikYaz;
end;

initialization
   Formlar := TList.Create;

finalization
   Formlar.Free;

end.
Burada iki farklı yöntem kullandım, ikiside aynı kapıya çıkıyor..
İkinci yöntemi kullanmak isterseniz //{$DEFINE YontemIki} yazan satırın başındaki // işaretlerini kaldırın. Ve Yöntem birin başına bu işaretleri koyun.. Sakın her ikisinin de başındaki işaretleri kaldırmayın. Sadece biri aktif olmalıdır..

Forumlar adlı dizi işinize yaramayacaksa gereksiz ise en pratik yöntem aşağıdaki gibidir...

Kod: Tümünü seç

TForm1.Button1Click(Sender:TObject); 
begin 
   with TForm1.create(Application) do Show;
end; 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
   //Bu formun kapandıktan sonra FREE edilmesini sağlıyacaktır..
   Action := caFree;
end;
Görüldüğü gibi Button1'e bastıkça yeni bir TForm1 sınıfından form üretilir.

De haydi kolay gelsin...
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

muratdicle abi, tek kelimeyle harikasın... sanırım hata mesajı formclose prosedürü içine yazdığım formlar.free'den kaynaklanıyomuş, action:=caFree yaptım, oldu... Bi de formları privatede değil de global tanımladım (ama bunu testetmedim, belki privatede de olurdu, kanımca olurdu). Tabi muhtemelen en iyisi senin tavsiye ettiğin yöntemdir, ama önişlemci komutlarını maalesef henüz bilmiyorum... İnşallah ilerde o da...

Abi, şimdi ben aşağıdaki gibi yaptım... Kod birazcık dağınık oldu, gereksiz şeyler var içinde biliyorum ama şimdilik öğrendiğim için sadece temel mantığını kapmaya çalışıyorum, yine kendimce dağınıklıktan da uzak duruyorum tabi, şimdi senden hemen cevap alabilmek için hemen 'kopyala, yapıştır' yaptım. Sen önceki örneğimde, "formlar kapatılınca hafızayı serbest bırakmıyo" demiştin. setlength ile onu halletmeye çalıştım. Acaba halledebilmiş miyim? Bana "olmuş" ya da "olmamış" dersen sevenirim (olmamışsa niye olmadığını da söylersen sevincim 2 katına çıkar), tabi "olmuş" dersen de sevincim maksimum olur... ama sen yine de doğruyu söyle :) Kod aşağıda abi...

var
Form1: TForm1;
pencere:array of tform;
implementation

{$R *.dfm}

procedure TForm1.Button11Click(Sender: TObject);
var
penceresayisi:integer;
begin
penceresayisi:=high(pencere)+2; //oluşması gereken pencere sayisi...
setlength(pencere,penceresayisi);
pencere[penceresayisi-1]:=tform.Create(Form1);
pencere[penceresayisi-1].OnClose:=formclose; //bunu yaptım çünkü kendi yaptığım formclose prosedüründe hafızayı serbest bırakıcam. Ama kanımca mantıksız gibi, çünkü nesne kendi prosedürüyle kendini nasıl yok edicek?
pencere[penceresayisi-1].Show;
end;

procedure TForm1.formclose(Sender: TObject; var Action: TCloseAction);
var
penceresayisi:integer;
begin
penceresayisi:=high(pencere)+2; //beni bilgilendirmek için...
Action:=caFree;
setlength(pencere,penceresayisi-2);//high(pencere) ile aynı ama dedim ki caFree olunca high(pencere) azalır belki dedim (gerçi azalmaması lazım, madem hafızada kalıyo bunlar) o yüzden başka bi değişken kullandım...
showmessage('bu form kapanınca kalan pencere sayısı '+inttostr(high(pencere)+1));//beni bilgilendirmek için
end;
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

özür dileyerek belirtmek istiyorum... Sorum muratdicle'ye özel soruyomuşum gibi olmuş ama ben tabii ki foruma soruyorum... 'muratdicle' adını kullanmamın sebebi az önceki cevabına istinaden... Diğer arkadaşlar da yardımcı olabilirse çok sevinirim... Teşekkürler... Herkese kolay gelsin...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
Murat DİCLE
Kıdemli Üye
Mesajlar: 702
Kayıt: 19 Nis 2006 04:12
Konum: İstanbul
İletişim:

Mesaj gönderen Murat DİCLE »

Merhaba,

setlength(pencere,penceresayisi-2); yerine setlength(pencere,penceresayisi-1); olması gerekiyor..

ama yinede en iyisi öncesindebir kontrol yapmaktır. İşi garantiye almak için

Kod: Tümünü seç

if high(pencere) >= 0 then SetLength(pencere, High(pencere);
Bu daha güvenli olacaktır. Bu arada FormClose olayının içinde henüz form içindeki hiç bir şey free edilmemiş olmaktadır, bu nedenle form içindeki hertürlü bileşene erişmen mümkündür.

Saygılar,
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

penceresayisi:=high(pencere)+2;
//yaptığım için
setlength(pencere,penceresayisi-2);
//yaptım...

Çok teşekkür ederim... Kolay gelsin...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
tuanna
Üye
Mesajlar: 582
Kayıt: 06 Ara 2004 05:01
Konum: Ankara
İletişim:

Mesaj gönderen tuanna »

konu yanlış anlamadım ise....neden söle bir sey yapmadın

form nesnesinin tag özelliği var...oluşturduğunda buraya deger vererek çok daha rahat edebilirisin...
Siz hayal edin...Biz yapalım TuannaSoft...
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

???

Mesaj gönderen huseyinkucuk »

???
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
tuanna
Üye
Mesajlar: 582
Kayıt: 06 Ara 2004 05:01
Konum: Ankara
İletişim:

Re: ???

Mesaj gönderen tuanna »

huseyinkucuk yazdı:???
neyi anlamadığınıda yazarsanız.?
Siz hayal edin...Biz yapalım TuannaSoft...
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

tag değişkenine niye değer girmeliyim... Yani bana nasıl yardımcı olur bu? Örneğin oluşturduğum formun numarasını buraya mı girmeliyim, "böylece işlem yaparken elimdeki formun tag özelliğinden kaçıncı form olduğunu anlarım" diye mi? Anlamadığım nokta buydu... Cevabın için teşekkürler (ve de verebileceğin cevaplar için teşekkürler)... Kolay gelsin...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Cevapla