全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1552
推到 Plurk!
推到 Facebook!

Treeview的小问题

答題得分者是:william
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-07-25 12:36:09 IP:218.88.xxx.xxx 未訂閱
各位高手,小弟再此有一个小问题:如果知道treeview的一个选相(Items)的具体名称,那么我怎样才能知道它所对应的索引号(就是Items[i]中的i所对应的具体数字)?
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-07-25 12:41:24 IP:147.8.xxx.xxx 未訂閱
You need to search the TreeNodes yourself.... If you know the item (e.g. TreeNode) then the index is TreeNode.AbsoluteIndex
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-07-25 12:49:17 IP:218.88.xxx.xxx 未訂閱
treenode是什么东西呀?
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-07-25 13:53:21 IP:218.88.xxx.xxx 未訂閱
还有,我想问一下怎样判断一个节点是否是根节点呢?怎样确定一个节点的具体位置呢?我觉得这些问题很头疼!
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-07-25 14:09:31 IP:147.8.xxx.xxx 未訂閱
TTreeView is the treeview. TTreeNodes is a collection of nodes of a treeview. TTreenode is a node inside a treeview. e.g. Assume TreeView1 is a treeview. TreeView1.Items is a TTreeNodes. TreeView1.Selected is a TTreeNode. if TreeView1.Selected.Level=0 then { selected node is a root node} { showing the index of the selected node } ShowMessage(TreeView1.Selected.AbsoluteIndex);
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-07-25 14:39:06 IP:218.88.xxx.xxx 未訂閱
谢谢先进!你的回答很精彩,其实我现在遇到的问题是想把数据库里面的资料分层次的显示在TreeView上,是这样的,我先显示最上层的,然后在显示第二层,然后在显示第三层.......我的程序如下,但是始终没有如愿,本来每一层下面都有子节点的,但是我的程式没有达到那样的要求,应该怎么作呢? procedure TForm1.FormShow(Sender: TObject); var i,m:integer; key:string; ddd:Tstrings; begin with query1 do begin close; sql.Clear; unprepare; sql.Add('select text from linerelation where layer=:layer'); params[0].AsInteger := 1; prepare; open end; query1.First; for i:=0 to query1.RecordCount-1 do begin treeview1.Items.Add(nil,query1.fieldbyname('text').AsString); query1.Next; end; for i:= 0 to treeview1.Items.Count-1 do begin treeview1.Selected := treeview1.Items[i]; with query1 do begin close; sql.Clear; unprepare; sql.Add('select key from linerelation where text=:text'); params[0].AsString := treeview1.Items[i].Text; prepare; open end; key := query1.fieldbyname('key').AsString; with query1 do begin close; sql.Clear; unprepare; sql.Add('select text from linerelation where layer=2 and parent=:key'); params[0].AsString := key; prepare; open end; query1.First; for m:=0 to query1.RecordCount-1 do begin treeview1.Items.AddChild(treeview1.Items[i],query1.fieldbyname('text').AsString); query1.Next; end; treeview1.Items[i].Expanded := false; end; treeview1.Items[0].Expanded := false; end;
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-07-25 14:58:27 IP:147.8.xxx.xxx 未訂閱
Something like that, not tested anyway.... BTW, I think you would better not use RecordCount (not reliable). maybe
while not query1.Eof do begin
{....}
    query.Next;
end;
and I remember there is a bug in some version of Delphi calling First immediately after opening a query will move the cursor to the 2nd record... You may also be interested in the BeginUpdate and EndUpdate method of TTreeNodes.
procedure TForm1.FormShow(Sender: TObject);
var i,m:integer;
    key:string;
    ddd:Tstrings;
    ANode: TTreeNode;
begin
    with query1 do
    begin
        close;
        sql.Clear;
        unprepare;
        sql.Add('select text from linerelation where layer=:layer');
        params[0].AsInteger := 1;
        prepare;
        open
    end;
   query1.First;
    for i:=0 to query1.RecordCount-1 do
    begin
        treeview1.Items.Add(nil,query1.fieldbyname('text').AsString);
        query1.Next;
    end;
    if treeview1.Items.Count>0 then
        ANode := treeview1.Items[0]
    else
        ANode := nil;
    while Assigned(ANode) do
    begin
        with query1 do
        begin
            close;
            sql.Clear;
            unprepare;
            sql.Add('select key from linerelation where text=:text');
            params[0].AsString := treeview1.Items[i].Text;
            prepare;
            open
        end;
        key := query1.fieldbyname('key').AsString;
        with query1 do
        begin
            close;
            sql.Clear;
            unprepare;
            sql.Add('select text from linerelation where layer=2 and parent=:key');
            params[0].AsString := key;
            prepare;
            open
        end;
        query1.First;
        for m:=0 to query1.RecordCount-1 do
        begin
            treeview1.Items.AddChild(ANode,query1.fieldbyname('text').AsString);
            query1.Next;
        end;
        ANode.Expanded := false;
        ANode := ANode.GetNextSibling;
    end;
    treeview1.Items[0].Expanded := false;
end;
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-07-25 15:19:13 IP:218.88.xxx.xxx 未訂閱
非常感谢Willian前辈,不过,小弟还有一些疑问, if treeview1.Items.Count>0 then ANode := treeview1.Items[0] else ANode := nil; while Assigned(ANode) do 上面的If语句是什么意思呢?还有while Assigned(ANode) do的作用是什么? ANode := ANode.GetNextSibling这句又是什么意思? 上面的程式只实现了两层,我想实现三层,四层是不是以此类推?
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-07-25 16:00:58 IP:147.8.xxx.xxx 未訂閱
引言: 非常感谢Willian前辈,不过,小弟还有一些疑问, if treeview1.Items.Count>0 then ANode := treeview1.Items[0] else ANode := nil; Get the ROOT node (i.e. the very first node) while Assigned(ANode) do Assigned(ANode) is same as (ANode<>nil) 上面的If语句是什么意思呢?还有while Assigned(ANode) do的作用是什么? ANode := ANode.GetNextSibling这句又是什么意思? Get the next node at the same level. 上面的程式只实现了两层,我想实现三层,四层是不是以此类推?
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-07-25 16:41:29 IP:218.88.xxx.xxx 未訂閱
谢谢!但是我的疑问还没有解决,只有再麻烦前辈了! 下面的代码是查询符合下一层的子节点的条件,所有的节点都放在一个表中。 with query1 do begin close; sql.Clear; unprepare; sql.Add('select key from linerelation where text=:text'); params[0].AsString := treeview1.Items[i].Text; prepare; open end; key := query1.fieldbyname('key').AsString; with query1 do begin close; sql.Clear; unprepare; sql.Add('select text from linerelation where layer=2 and parent=:key'); params[0].AsString := key; prepare; open end; 本来,第三层是在第二层的基础上产生的(两个条件,1:上面第二个查询的layer=3,二:第二个查询的Parent附值为第二层节点的名称(TEXT)),可不可以通过上面的代码直接实现?我想了半天,觉得不可能,重新写代码的话,怎么直接取出第二层节点,然后在在这基础上增加第三层节点呢?不知道我的思路正确否,程式具体应该怎么实现呢?
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#11 引用回覆 回覆 發表時間:2003-07-25 17:18:57 IP:147.8.xxx.xxx 未訂閱
You can search on the treeview (although slow ) < class="code">function GetFirstNode(Level: integer): TTreeNode; var i: integer; f: boolean; begin i := 0; f := False; while (not f) and (i Now GetFirstNode(0) = root node, GetFirstNode(1) = 1st level 1 node, GetFirstNode(2) = first level 2 node.... use GetNextSibling afterwards.
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#12 引用回覆 回覆 發表時間:2003-07-28 10:03:50 IP:218.88.xxx.xxx 未訂閱
Thanks William!谢谢前辈!根据你的指点我把程式写完了(下面),达到了我所要的功能,但不知程式是否合理,还请William前辈看看:) procedure TForm1.FormShow(Sender: TObject); var i,m,max_layer:integer; key:string; ddd:Tstrings; ANode: TTreeNode; begin with query1 do begin close; sql.Clear; unprepare; sql.Add('select text from linerelation where layer=:layer'); params[0].AsInteger := 1; prepare; open end; query1.First; for i:=0 to query1.RecordCount-1 do begin treeview1.Items.Add(nil,query1.fieldbyname('text').AsString); query1.Next; end; with query1 do begin close; sql.Clear; unprepare; sql.Add('select max(layer) as maxlayer from linerelation'); prepare; open end; max_layer := query1.fieldbyname('maxlayer').AsInteger; query1.Close; for i := 0 to max_layer -1 do begin anode := getfirstnode(i); while Assigned(anode) do begin with query1 do begin close; sql.Clear; unprepare; sql.Add('select key from linerelation where text=:text'); params[0].AsString := anode.Text; prepare; open end; key := query1.fieldbyname('key').AsString; with query1 do begin close; sql.Clear; unprepare; sql.Add('select text from linerelation where parent=:key and layer=:layer'); params[0].AsString := key; params[1].AsInteger := i 2; prepare; open end; query1.First; for m:=0 to query1.RecordCount-1 do begin treeview1.Items.AddChild(ANode,query1.fieldbyname('text').AsString); query1.Next; end; ANode.Expanded := false; ANode := ANode.GetNextSibling; end; end; end;
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#13 引用回覆 回覆 發表時間:2003-07-28 10:33:02 IP:147.8.xxx.xxx 未訂閱
The codes should be fine as long as it get the job done  class="code"> procedure TForm1.FormShow(Sender: TObject); {....} begin treeview1.Items.BeginUpdate; try {....} finally treeview1.Items.EndUpdate; end; end;
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#14 引用回覆 回覆 發表時間:2003-07-28 10:50:28 IP:218.88.xxx.xxx 未訂閱
谢谢前辈这么快就给出指点,我还有几个问题劳烦一下
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#15 引用回覆 回覆 發表時間:2003-07-28 10:59:56 IP:218.88.xxx.xxx 未訂閱
William前辈,不好意思,我又发现一个问题:程式运行的时候,Root的第一个节点里面的第二层,第三层都有只节点,但是Root的第二个节点一直到最后一个Root节点只有第二层节点,没有第三层节点,但是我在数据库里看过,它们都有子节点,难道是有地方疏忽了?还是程式的算法还不到位?还请前辈指点
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#16 引用回覆 回覆 發表時間:2003-07-28 12:22:33 IP:147.8.xxx.xxx 未訂閱
my 2 cents  >>, >> >>, >> >> >>
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#17 引用回覆 回覆 發表時間:2003-07-28 14:49:30 IP:218.88.xxx.xxx 未訂閱
linerelation的结构是这样的:key char(6) parent char(6) text char(30) layer int 其中,parent存放的是这条记录的上一节点的代码,key存放的是记录本身的代码,text是那条记录的名称,layer就是该记录所在的层次,layer=0时是根节点,layer=1时第二层,layer=2时是第三层……以此类推。 不过那上面的那段代码,只能解决第一个根节点的所有层次。
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#18 引用回覆 回覆 發表時間:2003-07-28 14:50:38 IP:218.88.xxx.xxx 未訂閱
linerelation的结构是这样的:key char(6)                            parent  char(6)                            text  char(30)                            layer int 其中,parent存放的是这条记录的上一节点的代码,key存放的是记录本身的代码,text是那条记录的名称,layer就是该记录所在的层次,layer=0时是根节点,layer=1时第二层,layer=2时是第三层……以此类推。 不过那上面的那段代码,只能解决第一个根节点的所有层次。起他的根节点,只能解决第二层,但是第三层就不能显示出来?                            
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#19 引用回覆 回覆 發表時間:2003-07-29 10:11:38 IP:147.8.xxx.xxx 未訂閱
Do you mean you have multiple nodes of level 0? I think GetNextSibling (and probably some other GetXXX) can only work on the same tree  class="code">function MyGetNextSibling(Node: TTreeNode): TTreeNode; begin if Assigned(Node) then Result := Node.GetNext else Result := nil; while Assigned(Result) and (Node.Level<>Result.Level) do Result := Result.GetNext; end;
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#20 引用回覆 回覆 發表時間:2003-07-29 10:51:30 IP:218.88.xxx.xxx 未訂閱
谢谢< >,不过程序是有点慢就是了,不知前辈能不能给我讲件整个程序的实现思路?特别是你写的那两个函数,简直是太绝了!我也求助了我的一个好朋友,他想了一天多,得出的结论和我一样< >!如果,我想在程序里面加上Image的话,那么该怎么作呢?说真的我是第一次这么深入的用TreeView!麻烦前辈了
Rain
資深會員


發表:31
回覆:236
積分:268
註冊:2003-02-17

發送簡訊給我
#21 引用回覆 回覆 發表時間:2003-07-29 11:07:15 IP:218.5.xxx.xxx 未訂閱
建議把整個樹型結構做為一個欄位(text類型),然後通過流載入保存, 這樣就簡單多了 //保存和載入整個樹型結構到資料庫的實現我以前有在另一個帖子貼了一段,參考看看:http://delphi.ktop.com.tw/topic.php?TOPIC_ID=33287 發表人 - Rain 於 2003/07/29 11:57:38
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#22 引用回覆 回覆 發表時間:2003-07-29 11:41:06 IP:218.88.xxx.xxx 未訂閱
建議把整個樹型結構做為一個欄位(text類型),然後通過流載入保存, 這樣就簡單多了 --------------------------------------------------------------------- 这样可行吗?不过听你说起来好象很复杂一样?要是采用Rain兄你说的办法,那具体实现该怎么实现呢?
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#23 引用回覆 回覆 發表時間:2003-07-29 11:50:06 IP:147.8.xxx.xxx 未訂閱
引言: 谢谢< >,不过程序是有点慢就是了,不知前辈能不能给我讲件整个程序的实现思路?特别是你写的那两个函数,简直是太绝了!我也求助了我的一个好朋友,他想了一天多,得出的结论和我一样< >!如果,我想在程序里面加上Image的话,那么该怎么作呢?说真的我是第一次这么深入的用TreeView!麻烦前辈了< face="Verdana, Arial, Helvetica"> TTreeView has a Images property (set it to an ImageList). Setting the ImageIndex and SelectedIndex of a TTreeNode should be enough then. The functions I created previously are simply straight forward. All nodes are accessible using TTreeView.Items and the toppest one has an index value of 0 and next one (i.e. index 1, visible or not) is the one below it and so on... For example... treeview1.GetFirstNode = treeview1.Items[0] Node.GetNext = treeview1.Items[Node.AbsoluteIndex 1] Borland's VCL wrapper of treeview is VERY SLOW (hence there are many 3rd party faster treeview components). Your program is slow becasue it needs to search though the treeview and do the insertion.
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#24 引用回覆 回覆 發表時間:2003-07-29 15:17:31 IP:218.88.xxx.xxx 未訂閱
William前辈,还有没有更好一点的算法,因为如果表linerelation中的记录多了,那么频繁的操作,速度肯定会受影响,你认为呢?
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#25 引用回覆 回覆 發表時間:2003-07-29 15:52:37 IP:147.8.xxx.xxx 未訂閱
引言: William前辈,还有没有更好一点的算法,因为如果表linerelation中的记录多了,那么频繁的操作,速度肯定会受影响,你认为呢?
If linerelation is generated by somebody else, I think you probably want to build the treeview node by node instead of layer by layer in order to minimize searching through the treeview. If linerelation is used only to store the tree structure, as Rain said, it would be better to use the SaveToStream, SaveToFile, LoadFromStream, LoadFromFile method of treeview.
railgunman
初階會員


發表:59
回覆:121
積分:36
註冊:2003-03-31

發送簡訊給我
#26 引用回覆 回覆 發表時間:2003-07-29 16:04:48 IP:218.88.xxx.xxx 未訂閱
谢谢!
系統時間:2024-05-16 1:00:14
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!