Delphi Can
Runtime Create edilen nesnenin Parent erişim sorunu - Baskı Önizleme

+- Delphi Can (https://www.delphican.com)
+-- Forum: Delphi (https://www.delphican.com/forumdisplay.php?fid=3)
+--- Forum: Mobil Platform - FireMonkey (FMX) (https://www.delphican.com/forumdisplay.php?fid=7)
+--- Konu Başlığı: Runtime Create edilen nesnenin Parent erişim sorunu (/showthread.php?tid=6001)



Runtime Create edilen nesnenin Parent erişim sorunu - 41linea41 - 16-05-2021

Merhaba

Çalışma zamanında aşağıdki ekranı oluşturuyorum.Var olan grid4x4 isimli  GridPanelLayout üzerine Tcircle nesneleri create ediyorum.

Fakat aşağıdaki kod ile create edilen Tcicrle nesnesinin Parent özellliğini " if sorgusu" yakalayamıyor.
[attachment=1756]

 for I := 1 to Resimsayisi do
  begin

    grid4x4.BeginUpdate;
  daire:=TCircle.Create(Application);
  daire.Parent:=grid4x4;
  try
    daire.BeginUpdate;
    daire.Align:=TAlignLayout.Client;
    daire.Fill.Kind:=TBrushKind.Bitmap;//   bkBitmap;
    daire.Fill.Bitmap.WrapMode:=TWrapMode.TileStretch;
    daire.Tag:=0;
    daire.Name:='Daire_4_'+IntToStr(I);
    daire.EndUpdate;
  except on E: Exception do
   // ShowHintFrame(frmana,'Hata:'+e.Message);
  end;
   grid4x4.EndUpdate;

  end;


 for I := 0 to ComponentCount -1  do
  begin
   if(components[I] is TCircle)  then
    begin
      Listbox1.Items.Add((components[I] as TCircle).Parent.Name) ;//gridpanellayout u parent olarak görmüyor.
        if (Components[I] as Tcircle).Parent=grid4x4 then//if TCircle(Components[I]).Parent=grd4x4 then
         begin
          ...
           ....
         ....

Bu if sorgusunu geçemiyor kod. Parent özelliğini kontrol edemiyor.

İyi çalışmalar.

,


Runtime Create edilen nesnenin Parent erişim sorunu - mrmarman - 16-05-2021

ComponentCount ile Components üzerinden yürümek yerine ControlCount ile Controls üzerinden yürüyebilirsiniz. 


   for I := 0 to grid4x4.ControlsCount -1  do
   begin
     if( grid4x4.Controls[I] is TCircle )  then
     begin
       Showmessage( grid4x4.Controls[I].Parent.Name );
     end;
   end;





Cvp: Runtime Create edilen nesnenin Parent erişim sorunu - savasabd - 17-05-2021

(16-05-2021, Saat: 21:23)41linea41 Adlı Kullanıcıdan Alıntı: Merhaba

Çalışma zamanında aşağıdki ekranı oluşturuyorum.Var olan grid4x4 isimli  GridPanelLayout üzerine Tcircle nesneleri create ediyorum.

Fakat aşağıdaki kod ile create edilen Tcicrle nesnesinin Parent özellliğini " if sorgusu" yakalayamıyor.


 for I := 1 to Resimsayisi do
  begin

    grid4x4.BeginUpdate;
  daire:=TCircle.Create(Application);
  daire.Parent:=grid4x4;
  try
    daire.BeginUpdate;
    daire.Align:=TAlignLayout.Client;
    daire.Fill.Kind:=TBrushKind.Bitmap;//   bkBitmap;
    daire.Fill.Bitmap.WrapMode:=TWrapMode.TileStretch;
    daire.Tag:=0;
    daire.Name:='Daire_4_'+IntToStr(I);
    daire.EndUpdate;
  except on E: Exception do
   // ShowHintFrame(frmana,'Hata:'+e.Message);
  end;
   grid4x4.EndUpdate;

  end;


 for I := 0 to ComponentCount -1  do
  begin
   if(components[I] is TCircle)  then
    begin
      Listbox1.Items.Add((components[I] as TCircle).Parent.Name) ;//gridpanellayout u parent olarak görmüyor.
        if (Components[I] as Tcircle).Parent=grid4x4 then//if TCircle(Components[I]).Parent=grd4x4 then
         begin
          ...
           ....
         ....

Bu if sorgusunu geçemiyor kod. Parent özelliğini kontrol edemiyor.

İyi çalışmalar.

,

Çünkü siz sadece formun çocuklarını  dolaşıyorsunuz, (Components[I] yazmakla Self.Components[I] yada FormX.Components[I] yazmak arasında bir fark yok) oysa TCircle'lar formun torunları oluyorlar.Smile.Muharrem Bey'in dediği yol bence de en mantıklısı ama illa Muharrem Bey'in dediği yoldan gitmeyecekseniz şöyle bir yoldan ilerleyebilirsiniz:

var
daire:TCircle;
i:integer;
begin
for I := 1 to Resimsayisi  do
 begin

   grid4x4.BeginUpdate;
 daire:=TCircle.Create(Application);
 daire.Parent:=grid4x4;
 try
   daire.BeginUpdate;
   daire.Align:=TAlignLayout.Client;
   daire.Fill.Kind:=TBrushKind.Bitmap;//   bkBitmap;
   daire.Fill.Bitmap.WrapMode:=TWrapMode.TileStretch;
   daire.Tag:=0;
   daire.Name:='Daire_4_'+IntToStr(I);
   daire.EndUpdate;
 except on E: Exception do
  // ShowHintFrame(frmana,'Hata:'+e.Message);
 end;
  grid4x4.EndUpdate;

 end;


    GetParent(self);


end;

procedure TForm1.GetParent(obj: TFmxObject);
var
i:integer;
begin

for I := 0 to obj.ChildrenCount -1  do
 begin
  if(obj.Children[I] is TCircle)  then
   begin
     Listbox1.Items.Add((obj.Children[I] as TCircle).Parent.Name) ;//gridpanellayout u parent olarak görmüyor.
       if (obj.Children[I] as Tcircle).Parent=grid4x4 then//if TCircle(Components[I]).Parent=grd4x4 then
        begin

          // 
        end;

   end;
      GetParent(obj.Children[i]);
 end;

end;



Runtime Create edilen nesnenin Parent erişim sorunu - ozcanm - 17-05-2021

procedure TForm1.Circle_islemleri;
var
 i: Integer;
begin
 for i := ComponentCount - 1 downto 0 do
 begin
   if (Components[i] is TCircle) and (TCircle(Components[i]).Parent = grid4x4)
   then
   Begin
     TCircle(Components[i]).Name := 'AAA';
     TCircle(Components[i]).Tag  := 0;
     // işlemler.
     // işlemler.
     // işlemler.
   end;
 end;
end;



Runtime Create edilen nesnenin Parent erişim sorunu - mrmarman - 17-05-2021

Merhaba.

@ozcanm üstadım, TCircle'in owner eğer form olsaydı bu şekilde sonuç alınabilirdi. Burada TCircle FORM değil de Application altında create edilmiş...


Kod:
    daire         :=  TCircle.Create(Application);
    daire.Parent  :=  Fgrid4x4;


Diğer yandan bu Application değil de self olsaydı @ozcanm sizin dediğiniz şekilde olurdu...

Kod:
   daire         :=  TCircle.Create(self);
   daire.Parent  :=  Fgrid4x4;


* ComponentCount sadece bileşen tarafından sahip olduklarının (owner oldukları) listesini getirecektir. 

Burada aramak için OWNER eğer Application ise o zaman ComponentCount değil Application.ComponentCount olmalıydı. Components[i] yerine de Application.Components[i].....
   
Bu durumda da @savasabd belirttiği gibi onun child seviyesindekileri görmek için bir tane daha iç döngü açıp, elde edilen her Components[i]'nin ControlCount ile adedi bulunup Controls[j] gibisinden aramak veya TFMXObject şeklinde yürüyüp direkt child objeckt üzerine yoğunlaşmak sonuç döndürür.

- Başlığı / sorunu / sorunsalı anlayamayanlar olabilir diye yukarıdaki örneği ortaya çıkarak bir senaryo aşağıda verilmiştir. 

- Boş bir FMX proje oluşturup, forma sadece ve sadece bir button koyup aşağıdaki kodu yapıştırın. Aşağıda birebir verilen örnek üzerinden bir yaklaşımı göreceksiniz. Burada amaç sonuç alamadığımızı ve de neyi alabildiğimizi test etmek.

- CircleIslemleri procedure başına // koyarak comment altına alıp aşağıdaki exit'i kaldırınca bir de diğer türlüsünü görebilirsiniz. 


Uses FMX.Objects;

Const
  Resimsayisi =  16;
  Rows        =   4;
  Cols        =   4;

var
  Fgrid4x4 : TGridPanelLayout;

procedure TForm1.Button1Click(Sender: TObject);
var
  i     : Integer;
  daire : TCircle;
begin
  // Önce yoksa bir layout kurgulayalım...
  PanelLayoutOlustur();

  for I := 1 to Resimsayisi do
  begin
    Fgrid4x4.BeginUpdate;
    daire         :=  TCircle.Create(Application); // self olmadığından ComponentCount ile çıkmaz. Application.ComponentCount ile olacaktır.
    daire.Parent  :=  Fgrid4x4;
    try
      daire.BeginUpdate;
      daire.Align                 :=  TAlignLayout.Client;
      daire.Fill.Kind             :=  TBrushKind.Bitmap;//   bkBitmap;
      daire.Fill.Bitmap.WrapMode  :=  TWrapMode.TileStretch;
      daire.Tag                   :=  0;
      daire.Name                  :=  'Daire_4_'+IntToStr(I);
      daire.EndUpdate;
    except on E: Exception do
     // ShowHintFrame(frmana,'Hata:'+e.Message);
    end;
    Fgrid4x4.EndUpdate;
  end;

   Circle_islemleri();

Exit;
   for I := 0 to Fgrid4x4.ControlsCount -1  do
   begin
     if( Fgrid4x4.Controls[I] is TCircle )  then
     begin
       Showmessage( Fgrid4x4.Controls[I].Name );
     end;
   end;
end;

procedure TForm1.Circle_islemleri;
var
  i: Integer;
begin
  for i := ComponentCount - 1 downto 0 do
  begin
    if (Components[i] is TCircle) and (TCircle(Components[i]).Parent = Fgrid4x4)
    then
    Begin
      Showmessage('Bulduk'); // buraya bu örnekte hiç gelmeyecek....
      TCircle(Components[i]).Name := 'AAA';
      TCircle(Components[i]).Tag  := 0;
      // işlemler.
      // işlemler.
      // işlemler.
    end else begin
      Showmessage( Components[i].Name );
    end;
  end;
end;

procedure TForm1.PanelLayoutOlustur();
var
  i : Integer;
begin
  // Eğer yoksa örnek TGridLayout oluştur...
  if NOT Assigned( Fgrid4x4 ) then begin
    Fgrid4x4 := TGridPanelLayout.Create(self);
    Fgrid4x4.Parent     := self;
    Fgrid4x4.Name       := 'grid4x4';
    Fgrid4x4.Position.X := 10;
    Fgrid4x4.Position.Y := 100;
    Fgrid4x4.Width      := 300;
    Fgrid4x4.Height     := 300;

    while Fgrid4x4.RowCollection.Count     < Rows do
      Fgrid4x4.RowCollection.Add;

    while Fgrid4x4.ColumnCollection.Count  < Cols do
      Fgrid4x4.ColumnCollection.Add;

    repeat
      for i := 0 to Pred(Rows) do begin
        Fgrid4x4.RowCollection.Items[i].SizeStyle    := TGridPanelLayout.TSizeStyle.Percent;
        Fgrid4x4.RowCollection.Items[i].Value    := 100 / Rows;
      end;
      for i := 0 to Pred(Cols) do begin
        Fgrid4x4.ColumnCollection.Items[i].SizeStyle := TGridPanelLayout.TSizeStyle.Percent;
        Fgrid4x4.ColumnCollection.Items[i].Value := 100 / Cols;
      end;
    until ( Fgrid4x4.RowCollection.Items[0].Value    <= 100 / Rows )
        or( Fgrid4x4.ColumnCollection.Items[0].Value <= 100 / Cols ) ;
  end;
end;




Cvp: Runtime Create edilen nesnenin Parent erişim sorunu - ozcanm - 17-05-2021

(17-05-2021, Saat: 09:56)mrmarman Adlı Kullanıcıdan Alıntı: Merhaba.

@ozcanm üstadım, TCircle'in owner eğer form olsaydı bu şekilde sonuç alınabilirdi. Burada TCircle FORM değil de Application altında create edilmiş...

Kod:
    daire         :=  TCircle.Create(Application);
    daire.Parent  :=  Fgrid4x4;

Diğer yandan bu Application değil de self olsaydı @ozcanm sizin dediğiniz şekilde olurdu...

Hocam estağfurullah,
Öncelikle;
Eğer, "Üstad" diye hitap edilecekse buna siz ve sizin gibi hocalarımız layıktır. Ben burada acemiyim.

Acemi olmasaydım zaten yukarıda    "daire :=  TCircle.Create(Application);" kullandığını fark ederdim.
Ben genel kullanımda  "daire :=  TCircle.Create(Self);" kullanılır düşüncesi ile tam kontrolsüz bir paylaşım yapmış oldum. Rolleyes  Rolleyes