Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Iterating in a TTreeView

580 views
Skip to first unread message

Analian

unread,
Feb 18, 2005, 7:55:11 AM2/18/05
to
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.


Pete Fraser

unread,
Feb 18, 2005, 8:33:37 AM2/18/05
to
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.
http://www.delphi-gems.com/VirtualTreeview/VT.php

HTH Pete

"Analian" <ana...@mail.bg> wrote in message
news:4215...@newsgroups.borland.com...


> I've got this tree view

> I want the number of immediate descendants of a TreeNode so

Analian

unread,
Feb 18, 2005, 11:07:59 AM2/18/05
to

"Pete Fraser" <pete._no_s...@frasersoft.nospam.net> wrote in message
news:4215eeb0$1...@newsgroups.borland.com...

> 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.


Remy Lebeau (TeamB)

unread,
Feb 18, 2005, 2:08:22 PM2/18/05
to

"Analian" <ana...@mail.bg> wrote in message
news:4215...@newsgroups.borland.com...

> 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;

> I get all the children. i.e. 9

No, you will get 2, not 9, since Item[0] is the A1 node.

> num = TreeView1->Items[1].Count;

Again, that will not even compile. IT needs to be this instead:

num = TreeView1->Items->Item[1]->Count;

> I get 0, though I think this must be a pointer to A2

It will be a pointer to B1, not A2

> num = TreeView1->Items[2].Count;
> is an access violation (?)

And again:

num = TreeView1->Items->Item[2]->Count;

> 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.

> 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;

> num = TreeView1->Items->Item[0]->Count;
> I get the number of direct children of A1. OK

Correct.

> 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


Analian

unread,
Feb 18, 2005, 3:53:49 PM2/18/05
to
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?


Remy Lebeau (TeamB)

unread,
Feb 18, 2005, 4:31:02 PM2/18/05
to

"Analian" <ana...@mail.bg> wrote in message
news:4216...@newsgroups.borland.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.

> 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:

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


Analian

unread,
Feb 19, 2005, 8:09:32 AM2/19/05
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:42165e91$1...@newsgroups.borland.com...

>
> "Analian" <ana...@mail.bg> wrote in message
> news:4216...@newsgroups.borland.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.

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

Remy Lebeau (TeamB)

unread,
Feb 19, 2005, 7:09:07 PM2/19/05
to

"Analian" <ana...@mail.bg> wrote in message
news:42173a95$1...@newsgroups.borland.com...

> 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.

> 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.

> 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


Analian

unread,
Feb 20, 2005, 5:33:31 AM2/20/05
to
10x again for help & info
another beer in the list


0 new messages