Board index » cppbuilder » Iterating in a TTreeView

Iterating in a TTreeView


2005-02-18 08:55:11 PM
cppbuilder95
I've got this tree view
A1
B1
B2
A2
B1
B2
B3
A3
A4
int num;
num = TreeView1->Items->Count;
now num is 9, cause it's the total number of TreeNode s in the TreeView
I want the number of immediate descendants of a TreeNode so
I can iterate trough them
TreeNode->Count is what I need.
But I want to get a TreeNode* from the TreeNodes property of the TreeView,
so I can use it's Count property. But
when I do
num = TreeView1->Items[0].Count;
I get all the children. i.e. 9
num = TreeView1->Items[1].Count;
I get 0, though I think this must be a pointer to A2
num = TreeView1->Items[2].Count;
is an access violation (?)
Here I don't understand if Items[int] is a TreeNode, why the code above
doesn't work as I expect.
When I try
num = TreeView1->Items->Item->Count;
I get
[C++ Error] Unit1.cpp(89): E2193 Too few parameters in call to '_fastcall
TTreeNodes::GetNodeFromIndex(int)'
(Why?)
When I try
num = TreeView1->Items->Item[0]->Count;
I get the number of direct children of A1. OK
With
num = TreeView1->Items->Item[1]->Count;
I don't get the number of direct children of A2.
Stupid problem but I think I'm not getting right how to use this property.
I'd be grateful if someone could explain this stuff and write a short sample
code. Thanks.
 
 

Re:Iterating in a TTreeView

What you need is:
TreeView->Items->Count // this is the count of ALL nodes in the tree
TreeView->Items->Item[n] Count // this is the count of children of node n in
the tree
Personally, I wouldn't touch TTreeView any more. It uses the MS tree that
relies on passing messages all over the place and so is very slow.
Take a look at VirtualTreeView by Mike Lischke which is very fast (x100?).
It takes a bit of getting used to but if you have large trees it is well
worth while.
www.delphi-gems.com/VirtualTreeview/VT.php
HTH Pete
"Analian" < XXXX@XXXXX.COM >wrote in message
Quote
I've got this tree view
I want the number of immediate descendants of a TreeNode so
I can iterate trough them
TreeNode->Count is what I need.
 

Re:Iterating in a TTreeView

"Pete Fraser" < XXXX@XXXXX.COM >wrote in message
Quote
What you need is:
TreeView->Items->Count // this is the count of ALL nodes in the tree
TreeView->Items->Item[n] Count // this is the count of children of node n
in the tree
OK
I also thought so.
Can you write a sample code that iterates on the parents in the outer cycle
and on the direct children in the inner
Something like
int i, j;
for (i = 0; i < number_of_As; ++i)
for (j = 0; i < A[i].number_of_Bs; ++j) {
TreeView1->Items[i][j];
or
TreeView1->Items[i]->Item[j];
or
TreeView1->Items->Item[i][j];
or
TreeView1->Items->Item[i]->Item[j];
// what shoud I do here?
do_something ();
}
I'd REALLY appreciate help on this stupid question, 'cause I'm already
losing my nerves.
Thanks.
 

{smallsort}

Re:Iterating in a TTreeView

"Analian" < XXXX@XXXXX.COM >wrote in message
Quote
when I do

num = TreeView1->Items[0].Count;
That will not even compile to begin with. It needs to be this instead:
num = TreeView1->Items->Item[0]->Count;
Quote
I get all the children. i.e. 9
No, you will get 2, not 9, since Item[0] is the A1 node.
Quote
num = TreeView1->Items[1].Count;
Again, that will not even compile. IT needs to be this instead:
num = TreeView1->Items->Item[1]->Count;
Quote
I get 0, though I think this must be a pointer to A2
It will be a pointer to B1, not A2
Quote
num = TreeView1->Items[2].Count;
is an access violation (?)
And again:
num = TreeView1->Items->Item[2]->Count;
Quote
Here I don't understand if Items[int] is a TreeNode, why
the code above doesn't work as I expect.
Because you are not using it correctly in the first place.
Quote
When I try
num = TreeView1->Items->Item->Count;
I get
[C++ Error] Unit1.cpp(89): E2193 Too few parameters in call
to '_fastcall TTreeNodes::GetNodeFromIndex(int)'
(Why?)
The Item property needs an index:
num = TreeView1->Items->Item[SomeIndexHere]->Count;
Quote
num = TreeView1->Items->Item[0]->Count;
I get the number of direct children of A1. OK
Correct.
Quote
num = TreeView1->Items->Item[1]->Count;
I don't get the number of direct children of A2.
You are not supposed to. Item[1] is B1, whereas A2 is Item[3] instead. The
Item[] property uses absolute indexing, starting from the top of the tree
and working downwards sequentially, regardless of the levels the nodes
belong to:
Item[0] = A1
Item[1] = B1
Item[2] = B2
Item[3] = A2
Item[4] = B1
Item[5] = B2
Item[6] = B3
Item[7] = A3
Item[8] = A4
If you want to iterate the nodes of just a particular level, then you do not
use the Item[] property for that. You get a pointer to the first node of
the level and then use the GetNextSibling() method instead:
TTreeNode *Node = TreeView1->Items->GetFirstNode();
while( Node )
{
num = Node->Count;
TTreeNode *Child = Node->getFirstChild();
while( Child )
{
num = Child->Count;
Child = Child->GetNextSibling();
}
Node = Node->GetNextSibling();
}
Gambit
 

Re:Iterating in a TTreeView

thanks A LOT! You really saved some white hair on my head from appearing in
our dimension (:
but I still don't get it why do you need the TreeNodes to be in absolute
coordinates and why the Count property should be equal to ALL the children
of the node, not just the direct ones. I only see sense if this absolute
indexing of these nodes could be used to receive the order in which the
nodes shoud appear in a... post script I think. Like you have a tree graph
and you perform a depth first search
something like this:
void dfs (TreeNode *Node) {
static int i = -1;
TreeNode *t;
if (Node == 0)
return;
Node->Text = "Bla" + (AnsiString)i; // here we could do something useful
in the "absolute" order of these nodes
t = Node->getFirstChild ();
for (; t; ) {
dfs (t);
t = t ->getNextSibling();
}
}
I just couldn't think of other senseful usage of this indexing and I'm
curios for any other examle. Got any?
 

Re:Iterating in a TTreeView

"Analian" < XXXX@XXXXX.COM >wrote in message
Quote
but I still don't get it why do you need the TreeNodes to be
in absolute coordinates
The Items collection is a container for ALL nodes. The main
TTreeNodes::Count property is supposed to reflect all nodes. There is no
way to retreive a node at a given level directly, so the Items[] property
uses absolute indexing. If you want to take levels into account, then you
are not supposed to be using the Items[] property. That is why
GetFirst/LastChild(), GetNext/PreviousSibling(), etc. exist for each
individual node.
Quote
why the Count property should be equal to ALL the children of
the node, not just the direct ones.
The TTreeNode::Count does not count all children and grandchildren. Only
immediate children, exactly as you want. You can prove that for yourself:
A1
B1
C1
B2
A2
B3
B4
B5
C2
C3
D1
A3
A4
Given a TTreeNode pointer to A1, its Count is 2, not 3. Given a pointer to
A2, its Count is 3, not 6. And so on.
Quote
I only see sense if this absolute indexing of these nodes
could be used to receive the order in which the nodes
shoud appear in a... post script I think. Like you have a
tree graph and you perform a depth first search
something like this:
That code is not using absolute indexing at all. That is using recursion to
loop through the individual levels. Absolute indexing would be the
following instead:
void dfs(TreeNode *Node)
{
if( Node )
{
TTreeNodes *Nodes = Node->Owner;
int index = Node->AbsoluteIndex;
int last;
TTreeNode *t = Node->GetNextSibling();
if( t )
last = t->AbsoluteIndex;
else
last = Nodes->Count;
while( index < last )
{
t = Nodes->Item[index];
t->Text = "Bla" + (AnsiString)index;
++index;
}
}
}
Alternatively:
void dfs(TreeNode *Node)
{
if( Node )
{
TTreeNode *Last = Node->GetNextSibling();
while( Node != Last )
{
Node->Text = "Bla" + (AnsiString)Node->AbsoluteIndex;
Node = Node->GetNext();
}
}
}
Gambit
 

Re:Iterating in a TTreeView

"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"Analian" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>but I still don't get it why do you need the TreeNodes to be
>in absolute coordinates

The Items collection is a container for ALL nodes. The main
TTreeNodes::Count property is supposed to reflect all nodes. There is no
way to retreive a node at a given level directly, so the Items[] property
uses absolute indexing. If you want to take levels into account, then you
are not supposed to be using the Items[] property. That is why
GetFirst/LastChild(), GetNext/PreviousSibling(), etc. exist for each
individual node.
I understood that the previous time. OK. Just don't see the reason why this
TreeView class is implemented in such a way.
I find the other methods of accessing more convenient to use. That's all.
Quote
>why the Count property should be equal to ALL the children of
>the node, not just the direct ones.

The TTreeNode::Count does not count all children and grandchildren. Only
immediate children, exactly as you want. You can prove that for yourself:

A1
B1
C1
B2
A2
B3
B4
B5
C2
C3
D1
A3
A4

Given a TTreeNode pointer to A1, its Count is 2, not 3. Given a pointer
to
A2, its Count is 3, not 6. And so on.

>I only see sense if this absolute indexing of these nodes
>could be used to receive the order in which the nodes
>shoud appear in a... post script I think. Like you have a
>tree graph and you perform a depth first search
>something like this:
That code is not using absolute indexing at all. That is using recursion
to
loop through the individual levels. Absolute indexing would be the
following instead:
I mean it doesn't use absolute indexing, but generates an order of the
Nodes, so they can retrievie such consequent numbering.
void dfs (TreeNode *Node) {
static int i = -1;
TreeNode *t;
if (Node == 0)
return;
Node->Text = "Bla" + (AnsiString) (++i); // here we could do something
useful in the "absolute" order of these nodes
// I forgot the ++
here
// and I say that if this fuction is used it will generate this absolute
indexing, that's all. And I was wondering what benefit
// could one have from this indexing, when he can write a recursive function
to access any node he needs
t = Node->getFirstChild ();
for (; t; ) {
dfs (t);
t = t ->getNextSibling();
}
}
 

Re:Iterating in a TTreeView

"Analian" < XXXX@XXXXX.COM >wrote in message
Quote
I understood that the previous time. OK. Just don't see the
reason why this TreeView class is implemented in such a way.
Because that is the way Microsoft implements TreeView controls in general.
TTreeView is just a thin wrapper around the Win32 API TreeView control.
Most of TTreeView's functionality is controlled by Windows, not the VCL.
Quote
I find the other methods of accessing more convenient to use. That's all.
Then use them. Nobody is forcing you to use the Items[] property. There
are situations where it can be useful, though.
Quote
I mean it doesn't use absolute indexing, but generates an order
of the Nodes, so they can retrievie such consequent numbering.
Nodes are already numbered in an orderly fashion. TTreeNode has both Index
and AbsoluteIndex properties. Index is the index relative to the Parent
node. AbsoluteIndex is the index relative to the entire TreeView as a
whole.
Gambit
 

Re:Iterating in a TTreeView

10x again for help & info
another beer in the list