Autor |
Beitrag |
Pf@nne
      
Beiträge: 24
|
Verfasst: Sa 17.01.04 23:12
Hallo,
ich brauche ein Array of TTreeNode mit DatenPointer auf ein TStringList.
Ich habe mal angefangen, rein bekomme ich die Daten,
leider weiß ich nicht wie ich die daten aus meiner Node beim Ereigniss
TTreeView.Change wieder raus bekomme.
Hat jemand einen Tip???
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls;
type PNode = ^TNode; TNode = class(TTreeNode) private public Info: TStringList; end;
type TDevice = class(TObject) private public Node: PNode; end;
type TForm1 = class(TForm) TreeView1: TTreeView; Button1: TButton; Label1: TLabel; ListBox1: TListBox; procedure Button1Click(Sender: TObject); procedure TreeView1Change(Sender: TObject; Node: TTreeNode); private public Device: Array of TDevice; end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var i: integer; begin for i:= 1 to 4 do begin SetLength(Device,i+1); Device[i]:= TDevice.Create; New(Device[i].Node); Device[i].Node^.Info:= TStringList.Create; Device[i].Node^.Info.Add('Info: '+ inttostr(i)); TreeView1.Items.AddObject(nil, 'Item '+ inttostr(i), Device[i].Node);
ListBox1.Items.Add(Device[i].Node^.Info.Strings[0]); end; end;
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode); begin label1.Caption:= PNode(TreeView1.Selected.data)^.Info.Text; end;
end. |
Danke.............
|
|
tomtom62
      
Beiträge: 278
WIN 2000, XP prof
D5 prof.
|
Verfasst: So 18.01.04 10:03
Ich hatte mal ähnliche Probleme. Ich habe mich dann mit VirtualTreeView von Mike Lischke beschäftigt.
Gibts unter www.delphi-gems.com. Bietet meiner Ansicht nach genau das was Du suchst..
|
|
KidPaddle
      
Beiträge: 351
WinXP,Linux
D7 Prof, XE7
|
Verfasst: So 18.01.04 11:54
Das geht auch ohne. Jeder Node hat eine Property names Data. Beim erstellen des TreeView setzt Du diese Property Data := Device[i].
Delphi-Quelltext 1: 2:
| Node := TreeView1.Items.AddObject(nil, 'Item '+ inttostr(i), Device[i].Node); Node.Data := Device[i]; |
In der OnChange - Methode bekommst Du die Daten wie folgt:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TV.TreeView1Change(Sender: TObject; Node: TTreeNode); begin Device := TDEVICE(Node.Data); end; |
Gruß
KidPaddle
|
|
Pf@nne 
      
Beiträge: 24
|
Verfasst: So 18.01.04 17:24
hast du das mal probiert???
ich bin nicht mal in der lage den code fehlerfrei einzugeben.
ich bin in sachen pointern nicht so bewandert, aber das scheint
mir nicht richtig zu sein.
wenn du zeit hast lass doch den code bei dir mal laufen.
danke......
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Mo 19.01.04 10:19
Es geht auch so wie KidPaddle beschrieben hat mit dem VCL-Treeview über die Data-Eigenschaft, allerdings kann ich dir für solche Sachen ebenfalls den VirtualTreeview nur wärmstens empfehlen! Er ist wesentlich flexibler und schneller, aber dadurch auch etwas komplexer und komplizierter und man sollte sich doch halbwegs mit Pointern auskennen...
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
KidPaddle
      
Beiträge: 351
WinXP,Linux
D7 Prof, XE7
|
Verfasst: Mo 19.01.04 11:00
An welcher Stelle tritt ein Fehler auf?
An dieser:
Delphi-Quelltext 1:
| Node.Data := Device[i]; |
Wenn ja, dann ändere es mal so um:
Delphi-Quelltext 1:
| Node.Data := POINTER(Device[i]); |
@Motzi:
Sicher, TVirtualTreeView setze ich auch ein, aber nur dann, wenn ich sehr viele Daten zum darstellen habe, da TTreeView extrem langsam ist. Als ich zum ersten Mal mit TVirtualTreeView gearbeitet habe, hat es relativ lange gedauert, bis ich das gewünschte Ergebnis hatte. Für einfache Sachen nehme ich immer noch TTreeView.
Gruß
KidPaddle
|
|
Pf@nne 
      
Beiträge: 24
|
Verfasst: Mo 19.01.04 20:12
ist immer noch der selbe fehler, an der selben stelle:
Delphi-Quelltext 1:
| Device[i].Node.Data:= POINTER(Device[i]); |
liegt das problem vieleich bei den dynamischen arrays ???
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Mo 19.01.04 23:31
Pf@nne hat folgendes geschrieben: | ist immer noch der selbe fehler, an der selben stelle:
|
Hallo
entweder bin ich blind, oder du erzählst hier auch erstmal welcher Fehler erscheint
und Device[i].Node.Data := POINTER(Device[i]); hier weiß ich nicht, was du erreichen willst
Mfg Frank
Moderiert von Motzi: Quote- durch Delphi-Tags ersetzt
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Di 20.01.04 10:39
Damit:
Delphi-Quelltext 1:
| Device[i].Node.Data := POINTER(Device[i]); |
castet er einfach das seine Objekt-Instanz (die ja nur ein Zeiger ist) in einen Pointer um in der Data-Eigenschaft der Node zuweisen zu können...
@KidPaddle: du hast schon recht, der VirtualTreeview braucht eine gewisse Einarbeitungszeit und ich kann mich auch noch gut erinnern, dass ich am Anfang sehr damit gekämpft hab, aber sobald man das Prinzip mal durchschaut hat ist es echt ein Genuss damit zu arbeiten! Mit dem VCL-Treeview kommt man zwar schneller zu einfachen Lösungen, aber sobald man mal etwas Flexixibilität braucht lass ich den VCL-Treeview sofort links liegen und benutze den VirtualTreeview..!
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Di 20.01.04 10:57
Motzi hat folgendes geschrieben: | Damit:
Delphi-Quelltext 1:
| Device[i].Node.Data := POINTER(Device[i]); |
castet er einfach das seine Objekt-Instanz (die ja nur ein Zeiger ist) in einen Pointer um in der Data-Eigenschaft der Node zuweisen zu können...
|
ich seh hier nicht durch. er weißt das doch wieder zu seinem Device[i] wieder zu ?
und warum überhaupt der umweg über TNode, die auch noch von treenode abgeleitet ist und nicht gleich die Stringlist in TDevice aufnehmen?
Mfg Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Di 20.01.04 11:59
Also ich hab mir den Code jetzt mal etwas genauer angeschaut und festgestellt, dass da einiges seehr seltsam ist...
1) Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| PNode = ^TNode; TNode = class(TTreeNode) private public Info: TStringList; end; | wozu brauchst du die Klasse TNode die von TTreeNode abgeleitet ist? Und warum deklarierst du PNode als Zeiger auf TNode? Schließlich sind unter Delphi sowieso schon alle Objekte nur Zeiger.. du hättest dann einen Zeiger auf einen Zeiger, "also doppelgemoppelt"...
2) Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| for i:= 1 to 4 do begin SetLength(Device,i+1); Device[i]:= TDevice.Create; New(Device[i].Node); Device[i].Node^.Info:= TStringList.Create; Device[i].Node^.Info.Add('Info: '+ inttostr(i)); TreeView1.Items.AddObject(nil, 'Item '+ inttostr(i), Device[i].Node);
ListBox1.Items.Add(Device[i].Node^.Info.Strings[0]); end; | Was soll der SetLength-Aufruf innerhalb der Schleife? SetLength wird in der Regel einmal am Anfang aufgerufen und höchstens erst im späteren Verlauf wieder für irgendwelche Längenänderunge, aber nicht innerhalb einer Schleife immer wieder um den Array immer um 1 Element zu verlängern! Das ganze sollte also so ausschaun:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| SetLength(Device, 4); for i := 0 to 3 do begin Device[i] := TDevice.Create; ... end; |
3) Delphi-Quelltext 1: 2:
| New(Device[i].Node); Device[i].Node^.Info:= TStringList.Create; | Solche Sachen, die sich eigentlich nur auf die internen deiner Klassen beziehen macht man normalerweise im Konstruktor. Abgesehn davon ist das Feld "Node" ja vom Typ PNode, der wiederum in Zeiger auf eine Klasse TNode ist. Aber da Objekte in Delphi nur Zeiger sind und PNode daher ein Zeiger auf einen Zeiger ist reservierst du in diesem Fall mit New nur 4 Bytes für den Objekt-Zeiger. Es wird aber keine Instanz von TNode erzeugt...
Erklär mal was du vorhast und wofür das ganze gut sein soll...! Dann kann man sich überlegen ob der VCL-Treeview dafür ausreicht oder der VirtualTreeview angebrachter wäre und man kann gezielter eine Lösung suchen als sich mit deinem bisherigen Code herumzuschlagen...
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
KidPaddle
      
Beiträge: 351
WinXP,Linux
D7 Prof, XE7
|
Verfasst: Di 20.01.04 18:06
Schick doch mir mal den Code zu, sofern das kein Riesenprojekt ist. Ich glaube da wird irgendwo der falsche Pointer im TTreeNode gespeichert.
Gruß
KidPaddle
|
|
Pf@nne 
      
Beiträge: 24
|
Verfasst: Di 20.01.04 22:40
Titel: Problem gelöst !!
Hallo,
erst mal danke für eure rege beteiligung
ich habe mich noch mal dran gesetzt und eine lösung gefunden.
Ziel war es ein object zu erstellen was sowohl daten als auch ein treenode enthält. ich möchte während der laufzeit daten sammel und in einem treeview zur anzeige bringen. wird eine node selected möchte ich möglichst einfach auf die zugehörigen daten der node zugreifen können.
dieser code läuft:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls;
type PNodeData = ^TNodeData; TNodeData = record Info: TStringList; Number: integer; Text: String; end;
type TDevice = class(TObject) private public NodeData: PNodeData; Node: TTreeNode; end;
type TForm1 = class(TForm) TreeView1: TTreeView; Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); procedure TreeView1Change(Sender: TObject; Node: TTreeNode); procedure FormClose(Sender: TObject; var Action: TCloseAction); private public Device: array of TDevice; end; var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var i: integer; begin for i:= 1 to 500 do begin SetLength(Device,i+1); Device[i]:= TDevice.Create; New(Device[i].NodeData); Device[i].NodeData^.Info:= TStringList.Create;
Device[i].NodeData^.Info.Add('Item: '+inttostr(i)); Device[i].NodeData^.Number:= i; Device[i].NodeData^.Text:= 'Text: '+inttostr(i);
Device[i].Node:= TreeView1.Items.Add(nil, 'Node: '+inttostr(i)); Device[i].Node.Data:= Device[i].NodeData; end; end;
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode); begin memo1.Clear; Memo1.Lines.Add('StringList: '+PNodeData(Node.Data)^.Info.Text); Memo1.Lines.Add('Number: '+inttostr(PNodeData(Node.Data)^.Number)); Memo1.Lines.Add('Text: '+PNodeData(Node.Data)^.Text); end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin while TreeView1.Items.Count > 0 do begin dispose(PNodeData(TreeView1.Items.Item[0].Data)); TreeView1.Items.Item[0].Delete; end; end;
end. |
einfacher ist es aber so
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls;
type TTreeNode = class(TPersistent) private public Info: TStringList; Number: integer; Text: String; end;
type TForm1 = class(TForm) TreeView1: TTreeView; Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); procedure TreeView1Change(Sender: TObject; Node: TTreeNode); procedure FormClose(Sender: TObject; var Action: TCloseAction); private public DatenNode: Array of TTreeNode; end; var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var i: integer; begin for i:= 1 to 500 do begin SetLength(DatenObj,i+1); DatenObj[i]:= TTreeNode.Create;
DatenObj[i].Info:= TStringList.Create; DatenObj[i].Info.Add('Item: '+inttostr(i));
TreeView1.Items.AddObject(nil, 'Node: '+inttostr(i),DatenObj[i]);
DatenObj[i].Number:= i; DatenObj[i].Text:= 'Text: '+inttostr(i); end; end;
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode); begin memo1.Clear; Memo1.Lines.Add(TTreeNode(TreeView1.Selected.Data).Text); Memo1.Lines.Add(IntToStr(TTreeNode(TreeView1.Selected.Data).Number)); Memo1.Lines.Add(TTreeNode(TreeView1.Selected.Data).Info.Text); end;
end. |
Eine Frage hab ich noch:
wie initialisiere ich ein TTreeView den ich nur als platzhalter für meine nodes benutzen will und später einem Tree in meinem form zuweisen will
Delphi-Quelltext 1:
| FormTreeView.Items:= PlaceHolderTreeView.Items; |
ist ein TreeView in meinem form eingebunden übernimmt das delphi form diese arbeit für mich;
Delphi-Quelltext 1:
| PlaceHolderTreeView:= TTreeView.Create |
funktioniert leider nicht
hat vieleicht jemand eine idee wie ich im zweiten code
zeiger verbiegen kann.
ich möchte z.b.
Delphi-Quelltext 1:
| DatenNode[1].Date:= DatenNode[3].Data; |
gleichsetzen, geht aber leider nicht
pf@nne.....
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Mi 21.01.04 09:36
Hallo
Zitat: |
for i:= 1 to 500 do
begin
// dynamische vergrößerung um 1
SetLength(Device,i+1);
|
setlength in Schleifen, so was macht man nicht. siehe auch motzis post.
warum gehst du nochmal den umweg TNodeData, nimm doch einfach info,text und number mit in TDevice auf? Ich finde, du machst dir das unnötig kompliziert
Mfg Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Mi 21.01.04 10:26
Keldorn hat folgendes geschrieben: | warum gehst du nochmal den umweg TNodeData, nimm doch einfach info,text und number mit in TDevice auf? Ich finde, du machst dir das unnötig kompliziert |
Dem kann ich nur zustimmen...!
und ich kann mich nur nochmal wiederholen (nachdem meinem obigen Post anscheinend keine Beachtung geschenkt wurde):
Motzi hat folgendes geschrieben: | Erklär mal was du vorhast und wofür das ganze gut sein soll...! Dann kann man sich überlegen ob der VCL-Treeview dafür ausreicht oder der VirtualTreeview angebrachter wäre und man kann gezielter eine Lösung suchen als sich mit deinem bisherigen Code herumzuschlagen... |
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Pf@nne 
      
Beiträge: 24
|
Verfasst: Mi 21.01.04 19:08
Hallo,
@Keldorn
Zitat: | setlength in Schleifen, so was macht man nicht. siehe auch motzis post. |
die Schleife war nur zum testen, zur laufzeit wende ich setlength natürlich nur dann an wenn ich ein neues datenobject brauche.
@ Motzi
wozu ich dieses object brauche habe ich hier versucht zu erklären:
Zitat: | Ziel war es ein object zu erstellen was sowohl daten als auch ein treenode enthält. ich möchte während der laufzeit daten sammel und in einem treeview zur anzeige bringen. wird eine node selected möchte ich möglichst einfach auf die zugehörigen daten der node zugreifen können. |
den umweg über TNodeData wähle ich weil ich verschiedene daten objecte
brauche. dabei geht es weniger um den variablen typ als um die bezeichner. die baumstructur wird realativ komplex, da ist es schön wenn unterschidliche datentypen unterschiedliche bezeichner haben.
danke für eure anregungen.....
pf@nne
P.S. ich bräuchte noch mal Hilfe bei diesen Fragen:
Zitat: | wie initialisiere ich ein TTreeView den ich nur als platzhalter für meine nodes benutzen will und später einem Tree in meinem form zuweisen will
Delphi-Quelltext 1:
| FormTreeView.Items:= PlaceHolderTreeView.Items; |
ist ein TreeView in meinem form eingebunden übernimmt das delphi form diese arbeit für mich;
Delphi-Quelltext 1:
| PlaceHolderTreeView:= TTreeView.Create |
funktioniert leider nicht
hat vieleicht jemand eine idee wie ich im zweiten code
zeiger verbiegen kann.
ich möchte z.b.
Delphi-Quelltext 1:
| DatenNode[1].Date:= DatenNode[3].Data; |
gleichsetzen, geht aber leider nicht
|
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Do 22.01.04 10:03
Pf@nne hat folgendes geschrieben: |
den umweg über TNodeData wähle ich weil ich verschiedene daten objecte
brauche. dabei geht es weniger um den variablen typ als um die bezeichner. die baumstructur wird realativ komplex, da ist es schön wenn unterschidliche datentypen unterschiedliche bezeichner haben.
|
versteh ich trotzdem nich. du kannst dir trotzdem unterschiedliche Objekte definieren und ggf. vererben. Beim zugreifen kannst du mit is prüfen, welcher Objtekttyp hinter der treenode.data hinterlegt ist. Irgenwie finde ich es unglücklich, wenn du mit Objekten und mit Zeiger auf Records arbeitest.
P.S. ich bräuchte noch mal Hilfe bei diesen Fragen:
Zitat: | wie initialisiere ich ein TTreeView den ich nur als platzhalter für meine nodes benutzen will und später einem Tree in meinem form zuweisen will
Delphi-Quelltext 1:
| FormTreeView.Items:= PlaceHolderTreeView.Items; |
ist ein TreeView in meinem form eingebunden übernimmt das delphi form diese arbeit für mich;
Delphi-Quelltext 1:
| PlaceHolderTreeView:= TTreeView.Create |
funktioniert leider nicht
hat vieleicht jemand eine idee wie ich im zweiten code
zeiger verbiegen kann.
ich möchte z.b.
Delphi-Quelltext 1:
| DatenNode[1].Date:= DatenNode[3].Data; |
gleichsetzen, geht aber leider nicht
|
[/quote]
sorry, ich lese hier:
Zitat: |
funktioniert leider nicht
|
Zitat: |
gleichsetzen, geht aber leider nicht
|
keine Fehlerbeschreibung, du sagt nicht, was genau nicht funktioniert und erwartest da jetzt wirklich eine antwort?
Wenn du einen Platzhalter brauchst, ist vielleicht eine Objectlist geeignet. Erstelle und verwalte deine TDevice dort und bei dem angezeigten Treeview ist bei der Data-Eigenschaft dann nur der verweis auf den entsprechenden Objectlist-eintrag.
Zitat: |
DatenNode[1].Data:= DatenNode[3].Data; |
was ist denn jetzt DatenNode[1].Data?
wenn du eine Objekte, wie z.B. eine Stringlist mit drin hast, kannst du nicht Stringlist1:=Stringlist2; schreiben. richtig wäre
Delphi-Quelltext 1:
| Stringlist1.assign(Stringlist2); |
Mfg Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
|