Gelişmiş TreeView

Yapmak istediğiniz işle ilgili doğru bileşeni bulmak için burayı kullanabilirsiniz. Sadece bulmak için, diğer sorular Programlama forumuna lütfen.
Forum kuralları
Bu forum sadece yapacağınız işle alakalı doğru bileşeni bulmak içindir. Şöyle bir şey yapmam lazım, hangi bileşeni kullanıyım diyorsanız, doğru yerdesiniz.
Cevapla
superco
Üye
Mesajlar: 68
Kayıt: 05 Haz 2005 06:47
Konum: Düzce

Gelişmiş TreeView

Mesaj gönderen superco »

S.A.

Kullanımı normal treeview gibi olan ama biraz daha gelişmiş bir treeview arıyorum.Mesela normal treeviewde bir node a sadece bir değer atayabiliyorum bunu ikiye çıkartmanın bir yolu var mı?Ayrıca savetofile yaptığımda sadece karakterler çıkıyor imageindex selectedindex gibi şeyleri kaydetmiyor.

Bu özelliklere ve fazlasına sahip olan bi Virtual Treeview var fakat oda çok zor bişey anlamadım.

Bu özelliklere sahip bildiğiniz bedava bir bileşen var mı?
Allah herkesin sırtına kaldırabileceği kadar yük koyar
t-hex
Kıdemli Üye
Mesajlar: 531
Kayıt: 18 Mar 2005 02:45
Konum: İstanbul/Antalya
İletişim:

Mesaj gönderen t-hex »

normal treeviewde bir node a sadece bir değer atayabiliyorum bunu ikiye çıkartmanın bir yolu var mı?
Her Node'un Data diye propertysi var. Bu özelliği kullanarak her node'a bir data bağlayabilirsiniz ve bu data'da istediğiniz kadar değer saklayabilirsiniz. Delphi Help'de bu tür kullanım için örnek mevcut.
Ayrıca savetofile yaptığımda sadece karakterler çıkıyor imageindex selectedindex gibi şeyleri kaydetmiyor.
Eğer sorun oluşturmayacaksa SelectedIndex gibi değerleri ayrı bir dosyaya kaydedebilirsiniz. Eğer tek dosyaya kaydetmek istiyorsanız SaveToFile metodu yerine SaveToStream metodunu kullanıp, bu streamdeki ve selectedindex + diğer istediğiniz bilgileri kaydedebilirsiniz.
Bu özelliklere ve fazlasına sahip olan bi Virtual Treeview var fakat oda çok zor bişey anlamadım.
Buna katılmıyorum, ilk bakışta çok karışık gibi geliyor ama bunun sebebi alıştığımız TTreeViewden çalışma prensibi olarak farklı olması. Takıldığınız konularda yardımcı olabilirim.

İyi çalışmalar.
Kullanıcı avatarı
sadettinpolat
Moderator
Mesajlar: 2131
Kayıt: 07 Ara 2003 02:51
Konum: Ankara
İletişim:

Mesaj gönderen sadettinpolat »

delphi 7 de varolan node sınıfından yeni bir sınıf üreterek buna istediğiniz özellikleri verebilirsiniz. daha sonrada bu yeni nodeyi treeviewe ekleyebilirsiniz. marco cantu delphi 7 de vardı örneği.
"Sevmek, ne zaman vazgececegini bilmektir." dedi, bana.

---
http://sadettinpolat.blogspot.com/
superco
Üye
Mesajlar: 68
Kayıt: 05 Haz 2005 06:47
Konum: Düzce

Mesaj gönderen superco »

Öncelikle cevaplarınız için teşekkürler.
Her Node'un Data diye propertysi var. Bu özelliği kullanarak her node'a bir data bağlayabilirsiniz ve bu data'da istediğiniz kadar değer saklayabilirsiniz. Delphi Help'de bu tür kullanım için örnek mevcut.
Data propertysi pointer tipinde. şöyle bir deneme yaptığımda

Kod: Tümünü seç

procedure TForm1.Button1Click(Sender: TObject);
var
a:TTreeNode;
b:integer;
begin
for b:=0 to 10 do
  begin
    with TreeView1.Items.Add(nil,'ali'+IntToStr(b)) do
      begin
        Data:=pchar('veli'+inttostr(b));
      end;
  end;
end;

Kod: Tümünü seç

ShowMessage(pchar(TreeView1.Selected.data));
Mesela ali6 ya tıkladığım zaman bana göstermesi gereken veli6 yerine veli$ mesajını gösteriyor.Pointerlar hakkında hiç tecrübem yok sizin dikkatinizi çeken bişey var mı?
Buna katılmıyorum, ilk bakışta çok karışık gibi geliyor ama bunun sebebi alıştığımız TTreeViewden çalışma prensibi olarak farklı olması. Takıldığınız konularda yardımcı olabilirim.
Takıldığım konu çok basit.Node eklemek. :)

Mesela master-detail olarak ilişkilendirilmiş iki tabloyu treeview'e eklemek istediğimde:

Kod: Tümünü seç

var
a:node;
begin
tblmaster.first;
tbldetail.first;
while not tblmaster.eof do
   begin
   a:=treeview1.items.add(nil,tblmasterISIM.Asstring);
   a.imageindex:=3;
   a.selectedindex:=3;
   while not tbldetail.eof do
       begin
           treeview1.items.addchild(a,tbldetailSoyad.AsString);
           tbldetail.next;     
       end;
   tbldetail.next;
   end;
şeklinde bir kod yazıyorum,bunun basitçe Virtual Treeview karşılığı nedir?
delphi 7 de varolan node sınıfından yeni bir sınıf üreterek buna istediğiniz özellikleri verebilirsiniz. daha sonrada bu yeni nodeyi treeviewe ekleyebilirsiniz. marco cantu delphi 7 de vardı örneği.
Bahsettiğiniz örneği buldum.Eğer Marco Cantu'nun kitabı olmayan varsa bahsedilen örnek kendi sitesinde var(05\CustomNodes)
http://www.marcocantu.com/md7/md7code.zip


İkinizede tekrar teşekkür ederim.
Allah herkesin sırtına kaldırabileceği kadar yük koyar
t-hex
Kıdemli Üye
Mesajlar: 531
Kayıt: 18 Mar 2005 02:45
Konum: İstanbul/Antalya
İletişim:

Mesaj gönderen t-hex »

Nodelara data eklerken PChar kullanmayın çünkü her node'da datanın aynı boyutta olması lazım. onun yerine

Kod: Tümünü seç

type
  TNodeData = class
    Adi :String;
    Soyadi : String;
  end;
buna benzer bir sınıf tanımlayın. Daha sonra

Kod: Tümünü seç

 node.Data := TNodeData.Create;
 with TNodeData(node.Data) do begin
   Adi := 'adi';
   Soyadi := 'soyadi';
 end;
gibi bir kodla data bağlayabilirsiniz. hatta alan sayısını istediğiniz kadar artturabilirsiniz. Yalnız bu yarattığınız sınıfları hafızadan silmeyi atlamamnız lazım. Bunu da TreeView'in OnDelete olayını kullanarak yapabilirsiniz.

Kod: Tümünü seç

procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
  if assigned(Node.Data) then begin
    TNodeData(Node.Data).Free;
    Node.Data:=nil;
  end;
end;
Virtual Tree Viewde verdiğiniz örnektekine benzer AddChild fonksiyonu var.

Kod: Tümünü seç

VAR
 VTNode : PVirtualNode;
begin
 VTNode := VirtualStringTree1.AddChild(VirtualStringTree1.RootNode);
 VirtualStringTree1.AddChild(VTNode);
end;
ama bu kullanım önerilen yöntem değil. Onun yerine OnInitNode, OnInitChildren olaylarına kod yazarak bu işin yapılması isteniyor.

Mesela, master tablodaki kadar kayıt eklemek için

Kod: Tümünü seç

  VirtualStringTree1.RootNodeCount := tblMaster.RecordCount;
kullanabilirsiniz. Bu durumda master tabloda kaç kayıt varsa onun kadar node eklenecek ve hemen onInitNode olayına yazdığınız kod çağrılacak. Örneğin

Kod: Tümünü seç

procedure TForm1.VirtualStringTree1InitNode(Sender: TBaseVirtualTree;
  ParentNode, Node: PVirtualNode;
  var InitialStates: TVirtualNodeInitStates);
begin
 // bu node'un childnode'u olduğunu berlitmek için  
InitialStates :=   InitialStates + [ivsHasChildren]; 
end;
procedure TForm1.VirtualStringTree1InitChildren(Sender: TBaseVirtualTree;
  Node: PVirtualNode; var ChildCount: Cardinal);
begin
  ChildCount := 5;
end;
yazın ve açıldıkça açıldığını görün :)
superco
Üye
Mesajlar: 68
Kayıt: 05 Haz 2005 06:47
Konum: Düzce

Mesaj gönderen superco »

t-hex yazdı:Nodelara data eklerken PChar kullanmayın çünkü her node'da datanın aynı boyutta olması lazım. onun yerine

Kod: Tümünü seç

type
  TNodeData = class
    Adi :String;
    Soyadi : String;
  end;
buna benzer bir sınıf tanımlayın. Daha sonra

Kod: Tümünü seç

 node.Data := TNodeData.Create;
 with TNodeData(node.Data) do begin
   Adi := 'adi';
   Soyadi := 'soyadi';
 end;
gibi bir kodla data bağlayabilirsiniz. hatta alan sayısını istediğiniz kadar artturabilirsiniz. Yalnız bu yarattığınız sınıfları hafızadan silmeyi atlamamnız lazım. Bunu da TreeView'in OnDelete olayını kullanarak yapabilirsiniz.

Kod: Tümünü seç

procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
  if assigned(Node.Data) then begin
    TNodeData(Node.Data).Free;
    Node.Data:=nil;
  end;
end;
Hocam node.data örneği için teşekkürler.İşimi gördü :)

Lakin önceden tavsiye ettiğiniz stream nesnesiyle uğraşırken TStream'de savetofile gibi bir metodunu göremedim.Helpten baktığımda savetofile metodu olan bi TMemoryStream vardı bende

Kod: Tümünü seç

var
a:TMemoryStream;
begin
a:=tMemoryStrem.create;
Treeview1.SaveToStream(a);
a.SaveToFile('c:\stream.txt');
a.free;
şeklinde bişeyler yazdım.Ama treeview'in kendi savetofile metodundan bir farkı yok direk text değerlerini saklıyor.Sanırım stream yerine memory stream kullandığımdan ötürü oldu.Tstream nesnesini direk diske nasıl kaydedebilirim.(Programcılıkta yeni sayılırım daha önce tstream kullanmamıştım.)
Virtual Tree Viewde verdiğiniz örnektekine benzer AddChild fonksiyonu var.

Kod: Tümünü seç

VAR
 VTNode : PVirtualNode;
begin
 VTNode := VirtualStringTree1.AddChild(VirtualStringTree1.RootNode);
 VirtualStringTree1.AddChild(VTNode);
end;
ama bu kullanım önerilen yöntem değil. Onun yerine OnInitNode, OnInitChildren olaylarına kod yazarak bu işin yapılması isteniyor.

Mesela, master tablodaki kadar kayıt eklemek için

Kod: Tümünü seç

  VirtualStringTree1.RootNodeCount := tblMaster.RecordCount;
kullanabilirsiniz. Bu durumda master tabloda kaç kayıt varsa onun kadar node eklenecek ve hemen onInitNode olayına yazdığınız kod çağrılacak. Örneğin

Kod: Tümünü seç

procedure TForm1.VirtualStringTree1InitNode(Sender: TBaseVirtualTree;
  ParentNode, Node: PVirtualNode;
  var InitialStates: TVirtualNodeInitStates);
begin
 // bu node'un childnode'u olduğunu berlitmek için  
InitialStates :=   InitialStates + [ivsHasChildren]; 
end;
procedure TForm1.VirtualStringTree1InitChildren(Sender: TBaseVirtualTree;
  Node: PVirtualNode; var ChildCount: Cardinal);
begin
  ChildCount := 5;
end;
yazın ve açıldıkça açıldığını görün :)
Hocam göremedim :oops: Biraz daha çalışmam lazım Virtual Treeview üzerine.

Tekrar teşekkürler hocam.

Not:Bu arada Virtual Treeview baya gelişmiş bir bileşen.Delphi'de olmayan birçok bileşenin(Object inspector,Quantumgrid tarzı grid vs..) yerine geçebilecek kadar ayrıntılı.
Allah herkesin sırtına kaldırabileceği kadar yük koyar
t-hex
Kıdemli Üye
Mesajlar: 531
Kayıt: 18 Mar 2005 02:45
Konum: İstanbul/Antalya
İletişim:

Mesaj gönderen t-hex »

TStream sınıfı TFileStream,TMemoryStream,TStringStream gibi sınıfların atasıdır ve abstract metodlar içerir, o yüzden direk TStream kullanamazsınız. Bu durumda sizin kullanmanız gereken TMemoryStream.

Ama sizin sorununuz TreeView'in her şeyi kaydetmemesi. Zaten help içerisinde de SaveToFile veya SaveToStream metodlarını kullandığınızda kaydedilenin sadece text olacağı, bağladığınız data ve benzeri bilgilerin kaydedilmeyeceği yazıyor. Bu yüzden en mantıklısı bu kaydetme işini yapacak kodu sizin yazmanızdır.

Kod: Tümünü seç

var
 node : TTreeNode;
begin
  node := TreeView1.Items.GetFirstNode;
  while node <> nil do begin
    NodeKaydet(Node); // bu prosedür nasıl kaydetcekseniz öyle yazılmalı.
    node := node.GetNext;
  end;
bu yapıdaki bir kodla TreeViewdeki bütün nodelara ulaşabilirsiniz.

Kolay gelsin.
superco
Üye
Mesajlar: 68
Kayıt: 05 Haz 2005 06:47
Konum: Düzce

Mesaj gönderen superco »

Teşekkürler hocam.
Allah herkesin sırtına kaldırabileceği kadar yük koyar
heavy
Üye
Mesajlar: 67
Kayıt: 07 May 2005 03:31

Mesaj gönderen heavy »

NodeKaydet(Node);

procedure'ü için nasıl bir kod uyguladınız ?
Cevapla