关于treeview动态生成目录树及图标问题

时间:2023-01-26 12:32:52
  如何用TreeView从数据库读取数据形成目录树,并根据数据库里图标字段变换Item的图标?   
  数据库数下:
  ID    Name   Pid  Images
------------------------------
  1     湖南   0     1.bmp
  2     广东   0     2.bmp
  3     深圳   2     3.bmp


我要显示如下

1.bmp  湖南
2.bmp  广东
     3.bmp  深圳
意思就是在生成树的同时图标也根据数据库动态生成.

14 个解决方案

#1


你这种形式,图标就得自己画上去了

建议第一次只都去最*记录,然后在treeview的expanding事件中对节点展开时,都去下一层节点

#2


这样效率太低了,只能自己画,看看能不能用别的方法

#3


这个不难呀。
你想问什么?
怎么实现?

#4


我想我说得比较清楚了!
我想实现的结果是
比如根据数据库形成目录树
然后在加载每个节点的图标

#5


用递归,参考代码:

procedure TfrmMain.CreateTree(sNode: TTreeNode );
var
  s1: TTreeNode;
  node : TTreeNode;
  sql:string;
  PNode: PNodeData;
begin
  FrmDm.AQDepartment.Close;
  FrmDm.AQDepartment.SQL.Clear;

  if( sNode = nil ) then sql := '0'
  else sql :=   (PNodeData(sNode.Data)^).serial;

  FrmDm.AQDepartment.SQL.Text := 'select * from Department where parent = '''+ sql +''' and IsDeleted <> ''1'' ';

  FrmDm.AQDepartment.Open;
  FrmDm.AQDepartment.First;
  while not FrmDm.AQDepartment.Eof do
  begin
    New(PNode);
    if( sNode = nil ) then
    begin
      node := TreeView1.Items.Add(  sNode, FrmDm.AQDepartment.Fieldbyname( 'Name' ).AsString );
      node.ImageIndex := 0;
    end
    else
    begin
      node := TreeView1.Items.AddChild( sNode, FrmDm.AQDepartment.Fieldbyname( 'Name' ).AsString );
      node.ImageIndex := 1;
      node.SelectedIndex := 1;
    end;

    PNode^.serial :=  FrmDm.AQDepartment.FieldByName( 'serial').AsString;
    node.Data := PNode;

    FrmDm.AQDepartment.Next;
  end;
  FrmDm.AQDepartment.Close;
  if sNode = nil then
    s1 := TreeView1.Items.GetFirstNode
  else
   s1 := sNode.getFirstChild;

  while s1<>nil do
  begin
    CreateTree(s1);
    s1 := s1.getNextSibling;
  end;
end;

#6


我没测试你的代码,但是我估计你的代码能实现的就是两个图标间的转换
但是我要的是每个节点的图标不是固定的
是我动态添加到数据库里的
或者能读注册表来添加也可以,但是如果别人的系统里没有这个图标呢?
形象点比喻就像QQ的好友列表一样,每个好友是不同的图标.
这样我想应该够明白了吧?

#7


引用 6 楼 chrysalis 的回复:
我没测试你的代码,但是我估计你的代码能实现的就是两个图标间的转换
但是我要的是每个节点的图标不是固定的
是我动态添加到数据库里的
或者能读注册表来添加也可以,但是如果别人的系统里没有这个图标呢?
形象点比喻就像QQ的好友列表一样,每个好友是不同的图标.
这样我想应该够明白了吧?


动态的存在数据库里的图标,你读出来加载到TreeView就行了,用流出读来
TBlobField(query1.FieldByName('Images')).SaveToStream(XXStream);   

#8


没人能解决?

#9


两种都成
1. 可以自绘TreeView
2. 也可以把图标添加到ImageList中,不用自己绘制

#10



type pID = ^string;

procedure initTreeView(tv: TTreeView);
var
  Cds: TClientDataSet;
  sSQL: string;
  ParentNode: TTreeNode;
  id: pID;
  function FindNodeByID(T: TTreeView; id: string): TTreeNode;
  var i: integer;
  begin
    result := nil;
    for i := 0 to T.Items.Count - 1 do
      if string(T.Items[i].Data^) = id then
      begin
        result := T.Items[i];
        exit;
      end;
  end;
begin
  cds := TClientDataSet.Create(nil);
  sSQL := 'Select InvSortCode,InvSortName,ParentCode,Codelevel,EndFlag From Kf_InvSort';
  screen.Cursor := crAppStart;
  try
    getDataFormServer(cds, sSQL, -1);
    Application.ProcessMessages;
    cds.DisableControls;
    while not cds.Eof do
    begin
      ParentNode := FindNodeByID(tv, cds.FieldByName('ParentCode').AsString);
      new(id);
      id^ := cds.FieldByName('InvSortCode').AsString;
      //Node := tv.items.AddChildObject(ParentNode, cds.FieldByName('InvSortName').asString, id);
      tv.items.AddChildObject(ParentNode, cds.FieldByName('InvSortName').asString, id);
      cds.Next;
    end;
  finally
    screen.Cursor := crDefault;
    FreeAndNil(cds);
  end;
end;
--画树
procedure TFrmGy.tvGoodsTypeGetImageIndex(Sender: TObject;
  Node: TTreeNode);
begin
  inherited;
  if node.HasChildren then
    node.ImageIndex := 0
  else
    node.ImageIndex :=  1;
end;
--父节点和子节点不同的图标
procedure TFrmGy.tvGoodsTypeChange(Sender: TObject;
  Node: TTreeNode);
begin
  inherited;
  if not node.HasChildren then
    node.SelectedIndex :=  2;//选中时图标
end;

#11


哈哈,我是进来学习的

#12


来关注下。

#13


学习

#14


是东方红 

#1


你这种形式,图标就得自己画上去了

建议第一次只都去最*记录,然后在treeview的expanding事件中对节点展开时,都去下一层节点

#2


这样效率太低了,只能自己画,看看能不能用别的方法

#3


这个不难呀。
你想问什么?
怎么实现?

#4


我想我说得比较清楚了!
我想实现的结果是
比如根据数据库形成目录树
然后在加载每个节点的图标

#5


用递归,参考代码:

procedure TfrmMain.CreateTree(sNode: TTreeNode );
var
  s1: TTreeNode;
  node : TTreeNode;
  sql:string;
  PNode: PNodeData;
begin
  FrmDm.AQDepartment.Close;
  FrmDm.AQDepartment.SQL.Clear;

  if( sNode = nil ) then sql := '0'
  else sql :=   (PNodeData(sNode.Data)^).serial;

  FrmDm.AQDepartment.SQL.Text := 'select * from Department where parent = '''+ sql +''' and IsDeleted <> ''1'' ';

  FrmDm.AQDepartment.Open;
  FrmDm.AQDepartment.First;
  while not FrmDm.AQDepartment.Eof do
  begin
    New(PNode);
    if( sNode = nil ) then
    begin
      node := TreeView1.Items.Add(  sNode, FrmDm.AQDepartment.Fieldbyname( 'Name' ).AsString );
      node.ImageIndex := 0;
    end
    else
    begin
      node := TreeView1.Items.AddChild( sNode, FrmDm.AQDepartment.Fieldbyname( 'Name' ).AsString );
      node.ImageIndex := 1;
      node.SelectedIndex := 1;
    end;

    PNode^.serial :=  FrmDm.AQDepartment.FieldByName( 'serial').AsString;
    node.Data := PNode;

    FrmDm.AQDepartment.Next;
  end;
  FrmDm.AQDepartment.Close;
  if sNode = nil then
    s1 := TreeView1.Items.GetFirstNode
  else
   s1 := sNode.getFirstChild;

  while s1<>nil do
  begin
    CreateTree(s1);
    s1 := s1.getNextSibling;
  end;
end;

#6


我没测试你的代码,但是我估计你的代码能实现的就是两个图标间的转换
但是我要的是每个节点的图标不是固定的
是我动态添加到数据库里的
或者能读注册表来添加也可以,但是如果别人的系统里没有这个图标呢?
形象点比喻就像QQ的好友列表一样,每个好友是不同的图标.
这样我想应该够明白了吧?

#7


引用 6 楼 chrysalis 的回复:
我没测试你的代码,但是我估计你的代码能实现的就是两个图标间的转换
但是我要的是每个节点的图标不是固定的
是我动态添加到数据库里的
或者能读注册表来添加也可以,但是如果别人的系统里没有这个图标呢?
形象点比喻就像QQ的好友列表一样,每个好友是不同的图标.
这样我想应该够明白了吧?


动态的存在数据库里的图标,你读出来加载到TreeView就行了,用流出读来
TBlobField(query1.FieldByName('Images')).SaveToStream(XXStream);   

#8


没人能解决?

#9


两种都成
1. 可以自绘TreeView
2. 也可以把图标添加到ImageList中,不用自己绘制

#10



type pID = ^string;

procedure initTreeView(tv: TTreeView);
var
  Cds: TClientDataSet;
  sSQL: string;
  ParentNode: TTreeNode;
  id: pID;
  function FindNodeByID(T: TTreeView; id: string): TTreeNode;
  var i: integer;
  begin
    result := nil;
    for i := 0 to T.Items.Count - 1 do
      if string(T.Items[i].Data^) = id then
      begin
        result := T.Items[i];
        exit;
      end;
  end;
begin
  cds := TClientDataSet.Create(nil);
  sSQL := 'Select InvSortCode,InvSortName,ParentCode,Codelevel,EndFlag From Kf_InvSort';
  screen.Cursor := crAppStart;
  try
    getDataFormServer(cds, sSQL, -1);
    Application.ProcessMessages;
    cds.DisableControls;
    while not cds.Eof do
    begin
      ParentNode := FindNodeByID(tv, cds.FieldByName('ParentCode').AsString);
      new(id);
      id^ := cds.FieldByName('InvSortCode').AsString;
      //Node := tv.items.AddChildObject(ParentNode, cds.FieldByName('InvSortName').asString, id);
      tv.items.AddChildObject(ParentNode, cds.FieldByName('InvSortName').asString, id);
      cds.Next;
    end;
  finally
    screen.Cursor := crDefault;
    FreeAndNil(cds);
  end;
end;
--画树
procedure TFrmGy.tvGoodsTypeGetImageIndex(Sender: TObject;
  Node: TTreeNode);
begin
  inherited;
  if node.HasChildren then
    node.ImageIndex := 0
  else
    node.ImageIndex :=  1;
end;
--父节点和子节点不同的图标
procedure TFrmGy.tvGoodsTypeChange(Sender: TObject;
  Node: TTreeNode);
begin
  inherited;
  if not node.HasChildren then
    node.SelectedIndex :=  2;//选中时图标
end;

#11


哈哈,我是进来学习的

#12


来关注下。

#13


学习

#14


是东方红