关于TreeView的问题(50分)

S

snow

Unregistered / Unconfirmed
GUEST, unregistred user!
我在使用TreeView时出现了下面的问题:
我在删除TreeView的一个结点并释放它后,发现TreeView的count并没有减1,
导致我用for i:=0 to TreeView.items.count-1 时出错,提示i越界,但在程序
关闭时用上面一句时却没问题
请问:这是怎么回事?如何才能使count减1?
 
反过来,用
for i:=TreeView.items.count-1 downto 0 一试。
 
我的意思是说在TreeView的count个结点中有一个可能已经删除了,但TreeView似乎
没有刷新,但刷新也没用。使用一个已经删除的结点,当然会出错。
 
你用什么版本的delphi? delphi 2?
我试过delphi3, delphi4都没有该问题.
 
把TreeView.items.count的值放到一个变量x里面
i:=0;
x:=TreeView.items.count;
while i<x-1
begin
...
删除节点;
x:=TreeView.items.count
...
end
//这样x会动态改变导致循环次数动态改变

如果你的意思是要循环删除某些节点,那么
kokusan的方法好,很简单,因为是反过来删除
已经删除的节点不影响未删除的节点号
不会影响
 
不好意思,用了个小于号
如果你的意思是循环删除一些节点的话,
kokusan的方法可以实现,已经删除的节点
不会影响未删除的节点
我上面的程序的意思是,如果你向动态改变
循环次数的话,删除的节点后,在while循环
中把x 的值重新赋值一次.
用for的话,一上来,循环次数就定了
 
treeview没有该问题, 是你删除的指令写错了吧?
 
同意kokusan
是这样:
for i:=0 to TreeView.items.count-1
循环次数在第一次已经从Count读入,不会再变了,所以到后来i会大于实际的Count
倒过来就没事了。看看Delphi的source,都是这么写的
 
with TreeView1.items do
for i:=count-1 downto 0 do
delete(item);
 
//papaya seasky
snow没说要全删掉
再说这样也行:
with TreeView1.items do
while Count>0 do delete(item[Count-1]);
省个变量的说
 
用 for i:=TreeView.items.count-1 downto 0
没错,你怎么学的。
 
To Snow(s);
你的问题应该出在这里: 当一个Item 被删除后, 该Item之后的
所有Item的索引号都会自动减1, 这时你仍然按删除前的索引号
进行引用,最终会导致出错。 所以比较好的方法是从后到前的循环。
 
对不起一直上不上来,所以拖到现在!
我将那段程序贴过来,请各位大虾帮忙改错
我做的是一个公交公司的营运管理系统,公司包括几个分公司,每个分公司又包括几条线路,用TreeView
做分公司、线路的添加和删除功能。
如果我不进行删除操作,插入一个分公司或线路时程序没有问题,但如果我先进行删除操作,
接着进行插入操作时,程序就出错,提示如下:
Project yybb.exe raised exception class EAccessViolation with message 'Access violation
at address 0040AD29 in module 'YYBB.EXE'. Read of address FFFFFFFF'.Process stopped.User Step
or Run to continue.

插入程序段:
j:=0;
for i:=0 to TreeView1.Items.count-1 do
begin
//下面一句出错
if ((j<integer(TreeView1.Items.Data^)) and (integer(TreeView1.Items.Data^)<9)) then
j:=integer(TreeView1.Items.Data^);
end;
j:=j+1;
new(id);
id^:=j;
ParentNode:=TreeView1.items.AddChildObject(nil,InsertDlg.InputEdit.Text,id);
ParentNode.ImageIndex:=13;
ParentNode.SelectedIndex:=13;
//添加P小计、K小计、合计
AddChildItem(ParentNode,'P小计',j*100+97,16,16,Table1,'0');
AddChildItem(ParentNode,'K小计',j*100+98,16,16,Table1,'0');
AddChildItem(ParentNode,'合计',j*100+99,16,16,Table1,'0');
end;
end
删除程序段:
if MessageBox(handle,'是否要删除此线路?','警告',MB_YESNO+MB_ICONWARNING+MB_DEFBUTTON2)=IDYes then
begin
if (TreeView1.Selected).parent=nil then
Table1.locate('Line;Units',VarArrayof([(TreeView1.Selected).text,'']),[])
else Table1.locate('Line;Units',VarArrayof([(TreeView1.Selected).text,(TreeView1.Selected).parent.text]),[lopartialKey]);
Table1.Delete;
TreeView1.Selected.Delete;
dispose(TreeView1.Selected.data);
TreeView1.Selected.data:=nil;
end;
到底是插入有问题,还是删除有问题?请各位大虾帮忙找错!
以上只是两个过程的一部分,因代码有些长,没有贴上来,如果哪位大虾想仔细研究,请发个E-mail,我
把程序给你E-mail过去!
 
//下面一句出错
if ((j<integer(TreeView1.Items.Data^)) and (integer(TreeView1.Items.Data^)<9)) then
j:=integer(TreeView1.Items.Data^);
end;
j:=j+1;
new(id);
id^:=j;
ParentNode:=TreeView1.items.AddChildObject(nil,InsertDlg.InputEdit.Text,id);
ParentNode.ImageIndex:=13;
ParentNode.SelectedIndex:=13;
//添加P小计、K小计、合计
AddChildItem(ParentNode,'P小计',j*100+97,16,16,Table1,'0');
AddChildItem(ParentNode,'K小计',j*100+98,16,16,Table1,'0');
AddChildItem(ParentNode,'合计',j*100+99,16,16,Table1,'0');
end;
end
删除程序段:
if MessageBox(handle,'是否要删除此线路?','警告',MB_YESNO+MB_ICONWARNING+MB_DEFBUTTON2)=IDYes then
begin
if (TreeView1.Selected).parent=nil then
Table1.locate('Line;Units',VarArrayof([(TreeView1.Selected).text,'']),[])
else Table1.locate('Line;Units',VarArrayof([(TreeView1.Selected).text,(TreeView1.Selected).parent.text]),[lopartialKey]);
Table1.Delete;
TreeView1.Selected.Delete;
dispose(TreeView1.Selected.data);
TreeView1.Selected.data:=nil;
end;
到底是插入有问题,还是删除有问题?请各位大虾帮忙找错!
以上只是两个过程的一部分,因代码有些长,没有贴上来,如果哪位大虾想仔细研究,请发个E-mail,我
把程序给你E-mail过去!

 
if ((j < pinteger(TreeView1.Items.Data)^) and
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ try this
(pinteger(TreeView1.Items.Data)^ < 9)) then
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ and this
j:=pinteger(TreeView1.Items.Data)^;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
end;
j:=j+1;
new(id);
^^^^^^^^ what's id???? var id: PInteger?
id^:=j;
ParentNode:=TreeView1.items.AddChildObject(nil,InsertDlg.InputEdit.Text,
id^);
^^^
ParentNode.ImageIndex:=13;
ParentNode.SelectedIndex:=13;
//添加P小计、K小计、合计
AddChildItem(ParentNode,'P小计',j*100+97,16,16,Table1,'0');
AddChildItem(ParentNode,'K小计',j*100+98,16,16,Table1,'0');
AddChildItem(ParentNode,'合计',j*100+99,16,16,Table1,'0');
end;
end
删除程序段:
if MessageBox(handle,'是否要删除此线路?','警告',MB_YESNO+MB_ICONWARNING+MB_DEFBUTTON2)=IDYes then
begin
if (TreeView1.Selected).parent=nil then
Table1.locate('Line;Units',VarArrayof([(TreeView1.Selected).text,'']),[])
else Table1.locate('Line;Units',VarArrayof([(TreeView1.Selected).text,(TreeView1.Selected).parent.text]),[lopartialKey]);
Table1.Delete;
TreeView1.Selected.Delete;
^^^^^^^^^^^^^^^^^^^^^^^^^^^ 这句和下一句顺序错了?
treeview1.selected.delete了(所有相关内
存已经释放了), 怎么还能找到
treeview1.selected.data?. 到此处应该
出现错误了.
dispose(TreeView1.Selected.data);
TreeView1.Selected.data:=nil;
end;

而且您用treeview.selected.delete只是释放了该node的占用内存. treeview中还
有个nil节点, 所以treeview.items.count不会变.

建议用treeview1.items.delete(treeview1.selected)比较好
 
哎!TREEVIEW是我唯一了解较多的东西可惜来晚了。 :~(
 
>用 for i:=TreeView.items.count-1 downto 0
>没错,你怎么学的。
还是有问题吧?循环总数不变,其实items.count已经变了,还是要出事的。
比如说,你在循环体第一次执行中就一口气删了好几个节点,后面的几次循环
不出错才怪!

如tqz所说,关键是for语句在循环执行前已经定好了终值,是不会重新计算的。
应该是使用while强制每次都重新比较。

这是pascal语言中最基础的部分啦。
 
请问:
删除一个结点并释放内存,到底要执行哪几步?
 
果然是删除和释放结点的顺序搞错了
谢谢Another_eYes!
 
接受答案了.
 
顶部