Konuyu Oyla:
  • Derecelendirme: 4/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
[Çözüldü] Bileşen var mı yok mu ?
#1
Vertscrollbox içerisine her butona tıklandığında kendisinden önce varsa yanına gelecek şekilde stringgrid oluşturmaya çalışıyorum.  
1) Fakat sorun kendisinden önce oluşturulmuş bir stringgrid varmı yokmu nasıl kontrol ederim bilemedim. Varsa konum bilgisini alıp yanına nasıl oluşturacağım ?
2) Her satır maksimum 5 adet stringgrid bulunabiliyor. Birinci satır doluysa ikinci satıra oluşturmam gerek.

Nasıl bir yol izlemeliyim ? 

( İşin bir diğer ilginç yanı stringgridin margin özelliklerini kullanarak oluşturmaya çalıştım fakat ne tasarım anında nede kod ile etki etmiyor. )



function TFANA.Grid_Ekle(asahibi: TVertScrollBox; kartNo: Integer  ): TStringGrid;
 var

 Kolon:TStringColumn;
 i,satir,sutun:Integer;

begin
  Result := TStringGrid.Create(self);

   with  Result do begin
     Parent := asahibi;       Name:= 'K'+IntToStr(kartNo); Visible := true;
     Position.X := 0;         Position.Y     := 0;
     Width      := 253;       Height         := 100;
     Enabled    := true;      Align          := TAlignLayout.None;
     CanFocus   := true;      DefaultDrawing := true;
     HitTest    :=true;       Margins.Bottom :=0; Opacity    :=1;
     Margins.Top:=0;          Margins.Right  :=0; Margins.Left:=0;
     Options:=[TGridOption.ColumnResize,TGridOption.ColumnMove,TGridOption.ColLines,TGridOption.RowLines,TGridOption.Tabs,TGridOption.AutoDisplacement ];
     RowCount   :=3;          RowHeight  :=30; TabStop:=true;
     StyledSettings:= [];     TextSettings.Font.Family:='Arial'; TextSettings.font.Size:=16; TextSettings.Font.Style:=[TFontStyle.fsBold];
     TextSettings.FontColor:= TAlphaColors.Black; TextSettings.HorzAlign:=TTextAlign.Center; TextSettings.Trimming:=TTextTrimming.Word; TextSettings.VertAlign:=TTextAlign.Center;
     DefaultDrawing := False;
     Enabled:=true;
     OnDrawColumnCell:=KRENK_DEGIS;
     for i := 0 to 8 do begin
        Kolon:=TStringColumn.Create(self);
        with Kolon do begin
         Width:=30;
         Margins.Bottom:=0; Margins.Left:=0;Margins.Right:=0;Margins.Top:=0;
         Padding.Bottom:=3; Padding.Left:=3; Padding.Right:=3; Padding.Top:=3;
         Opacity:=1;
         Visible:=true;
        end;
        AddObject(Kolon);
     end;
    for  satir:= 0 to RowCount -1 do
    for sutun := 0 to ColumnCount -1 do begin
        Cells[sutun,satir]:='1';
    end;

  end;

  Kolon.Free;
end;
Cevapla
#2
Merhaba,
Margins ve Padding gibi özellikler Alignment içerisinde etkili olabiliyor. Aksi durumda Anchors ve Position (X ve Y) değerleri göz önüne alınarak nesne hizalamaları ve yerleştirmeleri yapılır.
Cevapla
#3
Hizalamayı anladım üstadımda, daha önce oluşturulmuş bir bileşen varmı yokmu olayını çözemedim. Hep üst üste geliyor. Onu araştırıyorum.
Cevapla
#4
Merhaba,

Sorunuzun cevabı aslında çok kolay. Daha önce yarattığınız StringGrid'leri bir listede tutun. Interface bölümündeki uses kısmına

System.Generics.Collections

unitini ekleyin. Form sınıfının private kısmına aşağıdaki kodu yazın:

FStringGridList: TList<TStringGrid>;

Formun constructor (ben bu gibi listeler için constructor/destructor tercih ediyorum, ama siz formun OnCreate ve OnDestroy olaylarına da yazabilirsiniz);

constructor TForm1.Create(AOwner: TComponent);
begin
  inherited;
  FStringGridList := TList<TStringGrid>.Create;
end;

destructor TForm1.Destroy;
begin
  FStringGrid.Free;
  inherited;
end;


Son olarak sizin yazdığınız kodun başına aşağıdakine benzer bir iki satır ekleyeceğiz, ama siz zaten şimdiye kadar olayı anlamışsınızdır.

function TFANA.Grid_Ekle(asahibi: TVertScrollBox; kartNo: Integer  ): TStringGrid;
var
  Kolon: TStringColumn;
  i, satir, sutun: Integer;
begin
  Result := TStringGrid.Create(self);
  if FStringGridList.Cout > 0 then
  begin
    // Her 5 gridden sonra alt satıra geçmeyi siz hesaplarsınız Smile Zaten alt tarafı mod 5 yapacaksınız o kadar Smile
    Result.Position.x := FStringGrid.Last.Position.x + GRID_GENISLIGI;
    Result.Position.y := FStringGrid.Last.Position.y;
  end
  else
  begin
    Result.Position.x := 0;
    Result.Position.y := 0;
  end;
  ...
  ...
  ...
  
  // Yeni yaratılan StringGrid'i listemize ekleyelim.
  FStringGridList.Add(Result);

Ama benim bu cevabı yazma nedenim size çözümü göstermek değil. İnanın bu veya buna benzer bir çözüm bulmak ilk başlarda zor gibi gelse de bir süre sonra aslında bazı çözümlerin sanıldığı kadar karmaşık olmadığı öğreniliyor. Ben sizi asıl Delphi söz diziminizden dolayı uyarmak için bu mesaj yazmak istedim. 

- Delphi'ye with/do deyimini getiren programcı kadar benden ah alan programcı olmamıştır. Size kodu yazarken kolay gelebilir, ama aslında değil. Birincisi DEBUG ederken inanılmaz zor oluyor. Mesela sizin yarattığnız StringGrid'in herhangi bir değerine bakmak istediniz diyelim. Maalesef fareyi kodun üstüne getirerek göremeyeceksiniz. Şunu yapmanız gerekecek: CTRL+F7 düğmesine basacaksınız. O pencerede Result.XYZ diyeceksiniz ve değeri göreceksiniz. Ne kadar zahmetli. Hem de ne için? Result. yazmak zor geldiği için mi? (İlgilisine not: With/do deyimi aslında çok kısa ve tek sınıflar için kullanılır ve derleyicinin daha iyi optimizasyon yapmasını sağlar, ama maalesef buradaki kodlar için değil). Daha da tehlikeli bir durum var: with/do için sizin bütün sınıfları çok iyi bilmeniz gerekiyor. Sizin kodunuzda Align := TAlign.Client yazan bir satır olsa ve iki gün sonra sonra StringGrid yerine Align desteklemeyen bir bileşen kullanacak olsanız kodunuz hata vermeyecek, ama aslında yanlış da çalışacak.

- Her satırda bir komut yazın. Yani
Position.X := 0;         Position.Y     := 0;
yerine düzgün düzgün
Position.X := 0;
Position.Y := 0;
yazın. İlk şekilde yazdığınızda satır sayısı daha az olmuş olmuyor. Sadece kodu bir başkasının (bu kişi aradan uzun bir zaman geçtikten sonra siz de olabilirsiniz) okumasını zorlaştırıyor.

- Nereden çıktı bilmiyorum, ama bazı programcılar begin'i alt satıra değil, satırın sonuna yazıyorlar. Delphi'de süslü parantez yerine begin/end kullanmanın en büyük sebebi tanıdık sözcükler sayesinde okumayı ve anlamayı kolaylaştırmak. Siz begin'i son satıra yazdığınızda o bloğun nerede bittiğini kolaylıkla göremiyorsunuz. Aksini iddia etmek sadece gereksiz tartışma olur. Delphi'nin varsayılan söz diziliminde begin sonraki satırdan başlar Smile

- Yine Delphi'nin varsayılan söz dizilimine göre operatörlerden önce ve sonra sadece bir tane boşluk olur. Sizde kimi zaman hiç yok, kimi zaman da (kodun hizalaması tutsun diye) çok fazla var. Hiç gerek yok, zaten her satıra bir komut yazacak olursanız tek boşluk yeterince okunabilir oluyor. Boşluk koymayınca da okunabilirlik düşüyor, özellikle matematiksel hesaplamalarda.

- Bu tamamen kişisel bir yaklaşım Smile Delphi'de CamelCase kullanılıyor. Yani her sözcüğün (ön eklerin, prefixlerin değil) ilk harfi büyük, sonraki harfleri küçük olur. Örneğin StringGrid gibi. Ben de size CamelCase kullanmanızı tavsiye ederim.

İyi çalışmalar
Cevapla
#5
Birdirbir oyununu bilir misiniz. 

Önerim 5 adet string grid'i peşin peşin oluşturun. altıncı gerektiğinde sadece 1 nolu olanın Y / TOP değerini değiştirip içini boşaltın yeni değerleri girin.

Bu illüzyon hem karmaşayı basite indirgeyecek, hem de memory ekonomisi getirecektir.

Hangi stringgrid hangi lokasyonda sorunuza peşinen cevap için bir function ile

1 nolu satıra 1 nolu stringgrid
5 nolu satıra 5 nolu
6 nolu satıra 1 olduğuna göre

iStringGridNo := ( satırno MOD 5 );
matematik hesabı sonucu ile elde edeceğiniz rakam size hangisinin TOP / Y değerini değiştireceğinizi ve içeriği dolduracağınızı verecektir. 

Şimdi sihrinizi kullanma vakti.  Smile
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#6
(19-02-2019, Saat: 07:09)Bahadir.Alkac Adlı Kullanıcıdan Alıntı: Merhaba,

Sorunuzun cevabı aslında çok kolay. Daha önce yarattığınız StringGrid'leri bir listede tutun.

Açıklayıcı ve güzel bir anlatım, çok teşekkürler.


MrMarman, güzel bir mantık teşekkürler, fakat daha önce o pozisyonda oluşturmuş olduğum bir grid varsa iş karışıyor biraz Smile
Belki ben yanlış ilerliyorumdur. Amacımı söylüyeyim de yanlışım varsa sizlerin sayesinde öğrenip düzeltmiş olurum. Aşağıda resimde kart satın al kısmındaki dizilimi el ile oluşturdum. Kullanıcı herhangi birinin üzerine tıkladığında satın aldığı kartın , Kartlarım adındaki tab2 ye bir kopyasını oluşturmak.
Dolayısı ile orada daha önce oluşturulmuş bir kart varmı yokmu bilmeliyim.

pbNa1n.png
Cevapla
#7
Merhaba,
satın alınan kartını parent'ını değiştirerek
kopyalamadan
KART SATIN AL sekmesinden KARTLARIM sekmesine taşıyabilirsin
Cevapla
#8
Teşekkürler fakat aynı kartı bir çok kişi alabilir. O yüzden kopyasını oluşturmaya mecburum
Cevapla
#9
Sorun hizalamada ise neden gridpanel kullanmıyorsunuz? Hem gridpanel’in controlcollection propertisi ile var olanlara da erişirsiniz.
Cevapla
#10
Şimdi resimden görünce yapılmak isteneni anladım.

Kodlarınızı görmedim, ama ekrandaki yapılandan aşağıdaki benzeri bir yapı olduğu çıkarımında bulunarak KART kopyalama ve silme işlemini örneklendirmek için çayımı yanıma aldım, bir kod örneği hazırladım...

Başlığı okuyanlarca bu örnekte bilşen(ler)in dinamik olarak CREATE ve FREE edilme şekillerini göreceksiniz.

YeniStringGrid ( Bir panel ve üzerine Label koyup StringGrid üreten, boyutlandıran, varsayılan değer veren, NIL olan yere bir panel koyarsan onu kopyalayan oluşan karta kopyalayan hepsi bir arada procedure )


procedure TForm1.YeniStringGrid(  aParentScrollBox: TScrollBox;
                                  aDefValue : String;
                                  aCopyFrom:TPanel = nil );
Const
  iColWidth   = 20;
  iRowHeight  = 30;
  iColCount   = 9;
  iRowCount   = 3;
  iTopMargin  = 20;
  iLeftMargin = 4;
var
  i,j,k        : Integer;
  aPanel       : TPanel;
  aLabel       : TLabel;
  aStringGrid  : TStringGrid;
  aButton      : TBitBtn;
  aControl     : TControl;
begin
  aPanel := TPanel.Create(nil);
  With aPanel do begin
    Parent   := aParentScrollBox;
    Width    := ( (iColWidth +2) * iColCount ) + ( iLeftMargin );
    Height   := ( (iRowHeight+2) * iRowCount ) + ( iTopMargin + 5  );
    Left     := ( (aParentScrollBox.ControlCount-1) mod 5 ) * Width;
    Top      := ( (aParentScrollBox.ControlCount-1) div 5 ) * Height;
  end;

  aButton := TBitBtn.Create(nil);
  with aButton do begin
    Parent    := aPanel;
    Width     := 60;
    Height    := 20;
    Caption   := 'Satış';
    Left      := aPanel.Width - iLeftMargin - aButton.Width;
    Top       := 0;
    onClick   := self.OnButtonSatisClick;
  end;

  aLabel := TLabel.Create(nil);
  With aLabel do begin
    Parent   := aPanel;
    Left     := iLeftMargin;
    Top      := 4;
    Caption  :=  'Kart No. ' + IntToStr( aParentScrollBox.ControlCount );
  end;

  aStringGrid := TStringGrid.Create(nil);
  With aStringGrid do begin
    Parent     := aPanel;
    Visible    := True;
    ColCount   := iColCount;
    RowCount   := iRowCount;
    ScrollBars := Vcl.StdCtrls.TScrollStyle.ssNone;
    for i := 0 to Pred(iColCount) do ColWidths[i]  := iColWidth;
    for i := 0 to Pred(iRowCount) do RowHeights[i] := iRowHeight;

    Options    := [ goVertLine, goHorzLine ];

    FixedRows:= 0;
    FixedCols:= 0;
    Width    := ( (iColWidth +2) * iColCount ) - 5;
    Height   := ( (iRowHeight+2) * iRowCount );
    Left     := iLeftMargin;
    Top      := iTopMargin;

    if aDefValue <> '' then
      for i := 0 to Pred(iColCount) do
        for j := 0 to Pred(iRowCount) do
          Cells[i,j] := aDefValue;
  end;


  // Kopyala denmiş ise...
  if aCopyFrom <> nil then
  begin
    aButton.Caption  := 'İade';
    aButton.onClick  := self.onButtonIadeClick;

    for k := 0 to Pred( aCopyFrom.ControlCount) do
    begin
      aControl := aCopyFrom.Controls[k];

      if aControl is TLabel then
      begin
        aLabel.Caption := TLabel(aControl).Caption;
      end;

      if aControl is TStringGrid then
      begin
        for i := 0 to Pred(iColCount) do
          for j := 0 to Pred(iRowCount) do
            aStringGrid.Cells[i,j] := TStringGrid(aControl).Cells[i,j];
      end;
    end; // for
  end; // if
end;



OnButtonSatis ( Panel üzerindeki SATIŞ butonuna basınca kopyalamak için için )

procedure TForm1.OnButtonSatisClick(Sender: TObject);
var
 i : Integer;
 aControl : TControl;
begin
 for i := 0 to Pred( TBitBtn(Sender).Parent.ControlCount) do
 begin
   aControl := TBitBtn(Sender).Parent.Controls[i];

   if aControl is TLabel then
   begin
     if MessageDlg( 'Kopyalamak istediğiniz kart "' + TLabel(aControl).Caption + '" Onaylayınız...',
                      mtConfirmation,
                     [mbOk, mbCancel],
                     0 ) = mrOk
     then
     begin
       YeniStringGrid( ScrollBox2, '', TPanel( TBitBtn(Sender).Parent ) );
     end;
   end;
 end;
end;

OnButtonIade ( Seçilmiş / Kopyalanmış olan kartı silmek için )
procedure TForm1.OnButtonIadeClick(Sender: TObject);
var
  i        : Integer;
  aControl : TControl;
  aPanel   : TPanel;
  aLabel   : TLabel;
begin
  i       := 0;
  aLabel  := nil;
  while ( i <= Pred( TBitBtn(Sender).Parent.ControlCount) ) AND (aLabel = nil) do
  begin
    aControl := TBitBtn(Sender).Parent.Controls[i];
    if aControl is TLabel
      then aLabel := TLabel(aControl);
    inc(i);
  end;

  if aLabel <> nil then
  begin
    if MessageDlg( 'Silmek İstediğiniz kart "' + aLabel.Caption + '" Onaylayınız...',
                     mtConfirmation,
                    [mbOk, mbCancel],
                    0 ) = mrOk
    then
    begin
      aPanel   := TPanel( TBitBtn(Sender).Parent );

      for i := Pred( aPanel.ControlCount ) downto 0
        do aPanel.Controls[i].Free;

      aPanel.Free;
    end; // if Ok
  end;
end;


OnCreate olayına ön hazırlığı koydum...

procedure TForm1.FormCreate(Sender: TObject);
var
   i : Integer;
begin
  for i := 1 to 100
    do YeniStringGrid( ScrollBox1, '0' );
end;


slybcfs3ao1u5bqpw897.gif
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Web butona tıklama - Çözüldü Altıner 2 219 13-03-2024, Saat: 16:42
Son Yorum: Altıner
  Google play Uygulama yükleme hatası [Çözüldü] codder71 3 366 23-02-2024, Saat: 22:42
Son Yorum: codder71
  Delphi 12 Boş Form Derleme Hatası [Çözüldü] codder71 4 538 21-02-2024, Saat: 22:09
Son Yorum: codder71
  Android 33 api sdk güncelleme [ÇÖZÜLDÜ] codder71 4 439 19-02-2024, Saat: 22:38
Son Yorum: codder71
  FMX Android Barkod Scanner - [ÇÖZÜLDÜ] Mesut 21 2.340 20-12-2023, Saat: 21:46
Son Yorum: Jakarta2



Konuyu Okuyanlar: 1 Ziyaretçi