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

如何在 TTreeView的 Node 里关联自己的数据

 
pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-01-10 18:33:06 IP:219.134.xxx.xxx 未訂閱
如何在 TTreeView的 Node 里关联自己的数据    使用 TreeView,通常想把自己的数据关联到Node上去。比如,选中一个Node,就显示一串对应这个Node的文字。    我搜索了一下,网上讲这个问题的文章,通常的做法是利用TTreeNode.Data来保存一个外部的Object的Pointer.    大概的代码如下:    先定义一个用来保存你自己的数据的类:
type TPropStore = class (TObject)
  private
    { Private declarations }
  public
    { Public declarations }
    AUserString: String;
    //add your own properties to this object
    constructor Create;
  end;    然后,这样把你自己的数据放进TTreeView里去:    procedure TForm1.AddItem;
var
  AProp: TPropStore;
begin
  AProp:= TPropStore.Create;
  TreeView1.Items.AddObject(nil,'Item',AProp); <---用 AddObject 方法来产生一个新的Node,顺便把一个外部的对象的Pointer保存进去。
  AProp.AUserString:='Hello,world!';
end;    然后,要从选中的Node读回来自己的数据,这样做:
procedure TForm1.SpeedButton4Click(Sender: TObject);
var
  SelNode : TTreeNode;
begin
  SelNode:=TreeView1.Selected;
  if SelNode<>nil then
  begin
    Form2.Edit1.Text:=SelNode.Text;
    Form2.Edit2.Text:=TPropStore(SelNode.Data).AUserString; <---这里,把SelNode.Data这个Pointer强制转换为TPropStore类型,然后读它的AUserString
    if Form2.ShowModal=mrOk then
    begin
    SelNode.Text:=Form2.Edit1.Text;
    TPropStore(SelNode.Data).AUserString:=Form2.Edit2.Text;
    end;
  end else
  ShowMessage('Select an item in the treeview before trying to edit');
end;
  
以上代码来自Borland Code Center里的一个例子。Written by Dr Steve Evans (steve@lociuk.com)
  
但是,我不喜欢这种做法。我不喜欢明显地看到Pointer,尽管一个Object就是一个Pointer。 一般来说,我自己用到一个TreeView,多半就是用它来保存同样的一类数据。因此,我用了另外一个办法:继承TTreeNode,产生一个可以包含自己的数据的新的类:
type
  TMyNode = class (TTreeNode)
  private
    FID: Integer;
  protected
    procedure SetID(const Value: Integer); virtual;
    function GetID: Integer; virtual;
  public
    property ID: Integer read GetID write SetID;
  end;
  
  
然后,我就可以任意在TreeView里用Node来关联/保存我自己的数据了。首先,生成一个Node:
  MyNode:=TreeView1.Items.Add(nil,Fields[2].AsString) as TMyNode; 
  MyNode.ID:=ID;
  
这里,直接用TTreeView.Items.Add增加一个Node,和普通的操作完全一样,只不过这个新增加的Node是一个可以包含我自己的数据的TMyNode    要把自己的数据从Node读出来就更简单了:
  ID:=TMyNode(TreeView1.Selected).ID;
直接把选中的TTreeNode转化为TMyNode,然后就可以读到TMyNode里的自己的数据了。 这样做,没有Pointer的操作,完全是对象的操作,看起来更舒服,也更直观。 究竟哪个方法更好,请高人指点。
Chance36
版主


發表:31
回覆:1033
積分:792
註冊:2002-12-31

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-01-10 23:00:31 IP:211.20.xxx.xxx 未訂閱
pcplayer99 你好    你有測試過了嗎?
我測的結果 底下一行編譯就不過了
  MyNode:=TreeView1.Items.Add(nil,Fields[2].AsString) as TMyNode;  // 編譯不過
  MyNode.ID:=ID;    改成如下 (強制轉型):編譯ok  了 後續的操作好像也沒問題,但別高興的太早
  MyNode:=TMyNode(TreeView1.Items.Add(nil,Fields[2].AsString) );  // 編譯OK
  MyNode.ID:=ID;    當程式要結束時,程式就會出現 [Invalid Pointer Operation] 的錯誤    主要是TreeView1.Items.Add(nil,Fields[2].AsString) 建立的object 是TTreeNode 
假設TTreeNode位用100Byte記憶體,而自定義的TMyNode 至少佔用104Byte,將TTreeNode 強制轉型成子類別
那TMyNode.ID 到底會存取到什麼地方呢?這應該就是系統出錯的地方;物件的轉型只能將子類別轉型成父類別吧!!
若強制將父類別轉型為子類別,出錯就只能怪自己了。    個人意見,若有謬誤,請勿見怪! 
    _______________________________________
<>深藍的魚,祝您好運..........連連
        
pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-01-11 12:45:04 IP:219.134.xxx.xxx 未訂閱
你好,这段代码我是从我自己正在用的一个我自己写的 TDBTreeView 里摘下来的,肯定是能编译通过的。我用的是D7。
pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-01-11 18:33:28 IP:219.134.xxx.xxx 未訂閱
不好意思,我再次检查了我自己那段可以运行的代码,忘记了还需要这个: 在TTreeView的Event里,要写上: OnCreateNodeClass(Sender: TCustomTreeView; var NodeClass: TTreeNodeClass); NodeClass:=TMyNode; 这样一来,就没问题啦。
系統時間:2024-07-01 15:30:05
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!