说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

如何给运行中生成节点的treeview控件加图标?????

编辑:说三道四文库 发布时间:2017-05-24 04:58
HTML文档下载 WORD文档下载 PDF文档下载
在运行中生成treeview的节点,然后个他们加上imagelist里面的图标,使用不相同的索引值。可是,当点击字节点的时候,图标会改变成父节点的图标,只是为什么?怎样才能使父节点和子节点有不同,且不改变的图标?
要看效果:http://www.comprg.com.cn/wz055.htm

Delphi环境下灵活的数据库树表实现 

 林琪

   我们目前正在开发的军队武器装备科技档案信息管理网络系统是面对全军的,管理全军武器装备科技档案的信息管理网络系统,由于全军在武器装备科技档案的管理模式上千变万化,对管理系统的需求也不相同,特别是,从调研的结果看:各单位的项目分类(信息分类)的级数是不定的,因此实现时一方面要考虑到通用性,另一方面也要保证用户使用的灵活性。

  

1 数据结构设计

在设计时可以采用两种数据存储方式(数据结构)。

1)信息分类表采用一个分类作为表的一条记录的方式进行存储,并由父类编号建立各类之间的关系,即:

分类号 
 类的含义 
 父类的编号 
 
0001 
 计算机 
   
 
0002 
 无线电 
   
 
… … 
 … … 
 … … 
 

2)这种分类表结构的建立不用动态生成表结构,但使用时相对麻烦。我们采用以下的表结构建立信息分类关系。这样的结构可以实现任意级的树型结构,如M层的一个结构:其中M是本单位的分类最大深度。类号要唯一识别每一个类。最上一级的分类号为全宗号+本级的分类代号,其他任意级的类其类号都为上一级的分类号+本级的分类代号。用户根据本单位档案的信息分类情况输入类信息,由系统动态创建表。

信息分类号
 全宗号
 类1含义
 类2含义
 类M含义
 分类深度
 
0001
 Zzb20
 电子
 计算机
   
 2
 
0002
 Zzb20
 电子
 无线电
   
 2
 
0003
 Zzb20
 通信
 卫星
   
   
 
0004
 Zzb20
 通信
 遥感
   
   
 
C4
 C6
 C20
 C20
 C20
 C1
 
XXFLH
 QZH
 L1
 L2
 LM
 FLSD
 

       在下面的例子中由于安全要求,对数据库表的结构作了简化,同时只使用了一些模拟数据以作说明。

  

2 树表外形设计

       由于Delphi提供的树表控件比较简单,外观不很美观,因此需要作一些“修饰”工作。为了强调重点,忽略了数据库操作如查询等,在例程中只使用了有关树表控件。

1)增加色彩

一般的树表控件没有底图,没有色彩,因此首先要解决色彩问题。解决的方法就是在树表控伯的ONDraw事件响应中增加底图显示代码。

procedure TForm1.Tree1CustomDraw(Sender: TCustomTreeView; const ARect: TRect; var DefaultDraw: Boolean);

begin

     with tree1.Canvas do                        //取树表控件的显示底板

     begin

     brush.color:=RGB(200,200,255);              //设置画笔颜色

     FillRect(ARect);                               //填充底板

 
  

     end; 

end;

这里仅为树表控件设置的底板颜色,实际上还可以设置底图,但由于底图的色彩不易控制,在调整树表结点时,容易出现颜色混乱的情况,而且只设置其颜色使树表控件的显示更加简洁。但只在ONDraw事件中设置颜色是不够的,还需要在其子项(结点)的显示事件中增加以下代码:

procedure TForm1.Tree1CustomDrawItem(Sender: TCustomTreeView;

  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);

var

 Noderect:TRect;

begin

     with tree1.Canvas do

     begin

          case Node.Level of                  //根据不同的层次,设置不同的结点字体颜色

          0:   font.Color:=clBlue;

          …

          5:   font.Color:=clGreen;

          end;

      if node=tree1.Selected then       //为突出选中的结点,将选中结点字体颜色设置为红色

          font.Color:=clRed;

          NodeRect:=Node.DisplayRect(false);              //设置结点的显示方式

          brush.Color:=RGB(200,200,255);

          fillrect(NodeRect);                         //将结点的背景色与控件底板色设置为一致

     end;

end;

      

2)设置图标

       图像列表控件与树表控件可以算是“老搭档”,即为了显示不同层次的结点就需要为树表控件设置一个对应的图像列表,其设置方法比较简单,可以参见有关的Delphi程序设计手册。由于树结构层次不定,因此不能象常规的方法那样建立了树表与图像列表之间的关系即大功告成,这里还需要做的是建立树表结点与图像列表的关系,可以通过以下两个函数实现。

procedure TForm1.Tree1GetImageIndex(Sender: TObject; Node: TTreeNode);

begin

     node.ImageIndex:=node.Level;    //由结点的层次决定其对应图标在图像列表中的位置

end;

  

procedure TForm1.Tree1GetSelectedIndex(Sender: TObject; Node: TTreeNode);

begin

     node.SelectedIndex:=node.ImageIndex;

end;

  

3)  窗体激活事件响应

响应窗体激活事件时,需要作一些设置。由于在原系统中,此窗体涉及的功能和控件较多,许多功能的完成都需要激活另外的窗体。因此需要避免对数据库信息的重复设置。可以如下实现:

procedure TForm1.FormActivate(Sender: TObject);

var

 i:integer;

begin

 if first_in=false then            //区别是否首次激活,从而决定是否需要设置初始状态

 begin

  hint.Caption := '    提示: 正在准备,请稍候...';

  application.ProcessMessages ;

  tree1.Items.Clear;                    //设置第一个树表状态和颜色

  tree1.Color:=RGB(200,200,255);

  tree2.Items.Clear;                    //设置第一个树表状态和颜色

  tree2.Color:=RGB(100,200,255);

  qznode:=nil;                         //为了显示动态结构的分类层次,将各层树结点初始化为空

  for i:=0 to 5 do

   last_node[i]:=nil;

   stackdepth:=0;                       //设置栈初始深度为0

  show_tree1(0);          //调用show_tree1显示分类内容,参数0表示从第一层开始显示

  hint.Caption:='    提示: 数据成功调入';

  Application.ProcessMessages;

  end;

    first_in:=true;        

end;

  

4)  树表内容显示

由于树表结点层次的不确定,我们采用了递归显示的方法完成树表内容的显示。这里设置了4个变量,其含义为;

变量
 类型
 含义
 可选范围
 
cur_cds
 TQuery
 当前的查询集
 dbmd.qz,dbmd.fl1,dbmd.fl2,

dbmd.fl3,dbmd.fl4,dbmd.fl5
 
cur_str
 string
 当前的查询语句
   
 
num_str
 String
 当前的层次数查询语句
   
 
cur_level
 Integer
 当前层次
   
 
cur_node
 TTreeNode
 当前结点
   
 

这里利用栈确定父结点与子结点的关系,若某结点对应的分类深度比当前深度要大,就需要将此结点入栈,并惟此结点为父结点,以插入孩子结点方式递归地显示它的下一层结点,若当前层的结点都已显示完毕,就需要退栈,回到上一层次再作计算。主要的实现过程如下:

procedure TForm1.show_tree1(level:integer);

…                //变量声明

begin

  case level of              //根据输入参数,确定当前数据集、结点和查询语句

  0:

  begin

    cur_cds:=dbmd.qz;

    cur_node:=qznode;

    cur_str:='select distinct QZH from XXFLB ';

  end;

  1:

  begin

    cur_cds:=dbmd.fl1;

    cur_str:='select distinct L1 from XXFLB ';

    cur_str:=cur_str +' where  QZH= '+''''+dbmd.qz.Fields.Fields[0].value+'''';

  end;

  …

  end;

   cur_cds.close;                              //实现查询

   cur_cds.SQL.clear;

   cur_cds.SQL.Add(cur_str);

   cur_cds.open;

       for i:=1 to cur_cds.RecordCount do                     //遍历当前层的所有结点

          begin

            if level=0 then                             //若为第一层则调用add方法创建结点

               cur_node := tree1.Items.Add(cur_node,cur_cds.Fields.Fields[0].value)

            else                //否则,在上一结点基础上调用AddChild方法创建其子结点

      cur_node:=tree1.Items.AddChild(last_node[stackdepth-1],cur_cds.Fields.Fields[0].value);

          if level<5 then            //根据当前结点层次及结点内容确定当前类的分类深度

          begin

          case level of

          0:

          begin

          num_str:='select  FLSD from XXFLB ';

          num_str:=num_str +' where  QZH= '+''''+dbmd.qz.Fields.Fields[0].value+'''';

          end;

          1:

           …

          end;

          dbmd.sd.close;                               //执行深度查询

          dbmd.sd.SQL.Clear;

          dbmd.sd.sql.add(num_str);

          dbmd.sd.Open;

          val(dbmd.sd.Fields.Fields[0].value,cur_level,code); //取其深度

           if  cur_level>level then          //若当前层次未达到其分类深度

            begin

                      last_node[stackdepth]:=cur_node;     //当前结点入栈

                      stackdepth:=stackdepth+1;

                      show_tree1(level+1);                       //递归显示下一层次结点

             end;

           end;

           cur_cds.Next;          //取当前结果集中的下一条记录

           if i > cur_cds.RecordCount -1  then            //若当前层中全部记录显示完毕则退栈

                stackdepth:=stackdepth-1;

          end;

 
  

end; 

       另外第二个树表的内容显示的基本方法与此类似,所不同的是第二个树表的显示函数所带的参数为串型参数,该参数有两种可能,即为‘’或由点击第一个树表的事件产生串参数。若参数为空串,则要在第二个树表中显示所有项目,否则要根据参数创建过滤条件选择显示项目。具体方法可以参见源代码。

  

5)  树表调整

 
  

树表的调整即是对树表当前结点的条件,可以由两种事件产生,即树结点的扩展和点击树结点。由于一个全宗号下的分类种类很多,层次也可能很大,因此用户希望打开一个类时,与其无关的类就关闭,这样就可以保证仅有目前所选择的结点,而不需要用户利用滚动条在打开的结点中寻找。其实现要充分利用树结点的方法和属性。特别强调的是在对点击树表结点的响应事件中用到了结点的扩展方法,尽管对结点扩展事件的响应函数所实现的功能与之类似,但一定不能加入类似的结点扩展方法,如tree1.Selected.Expand(false)等,因为在扩展事件中调用扩展方法会导致事件循环,甚至死机。 

对第二个树表的调整与第一个树表的处理方式类似,但功能不同,这里不多介绍。

procedure TForm1.Tree1Click(Sender: TObject);

…                 //变量声明

begin

 if Tree1.Selected=nil then                  //若未选择结点,重置

 begin

   tree2.Items.Clear;

   tree2.Refresh;

   exit;

 end

 else

 begin

    tree2.Items.Clear;

    tree2.Refresh;

     str:=Tree1.Selected.Text;                   //取当前结点内容

     fatherNode:=Tree1.Selected.Parent;    //取当前结点父结点

     tempnode:=Tree1.Selected;                //设置当前结点

     while fatherNode<>nil do                  //由当前层开始关闭所有非当前结点,

//同时返回由其第一层祖先到当前结点所组成的串,作为第二个树表显示的参数。

      begin

           str:=fatherNode.Text+','+str;          //取父结点内容与当前结点内容联接

           usenode:=fatherNode.getFirstChild; //遍历父结点的所有儿子结点

           while usenode<>nil do

           begin

                if usenode<>tempnode then          //只要不是当前结点,则取消扩展状态

                   usenode.Collapse(true);

                usenode:=fatherNode.GetNextChild(usenode);

           end;

           tempnode:=fathernode;    //当前层结点处理完毕后,调整父结点为当前结点

           fathernode:=tempnode.Parent; //再取当前结点的父结点

      end;

      sibNode:=tree1.Items[0];          // 第一层结点的处理与其它层稍有差异

      while  sibNode<>nil do

      begin

        if  sibNode<>tempNode then

          sibNode.Collapse(true);

      sibNode:=sibNode.getNextSibling;

      end;

      tree1.Selected.Collapse(true);           //强制打开当前结点

      tree1.Selected.Expand(false);

      if tree1.Selected.HasChildren=false then   //若当前结点无孩子,

      begin

        show_tree2(str); //说明已构成一个完整的类,调用show_tree2函数实现第二个树表//的内容显示,参数str为完整的类名

        hint.Caption:='    提示: 数据成功调入';

        Application.ProcessMessages;

  end;

 end;

  

参考文献

1 徐新华,IDE和Object Pascal 语言,人民邮电出版社,1998.12 

2 郑城荣,曾凡奎等,Delphi 运行时间库RTL和组件库VCL技术参考,人民邮电出版社,1999.1 

1 徐新华,GUI编程技术,人民邮电出版社,1998.12
非常感谢!!!!
在你的treeview控件的Onchange事件中:
  if youttv.Selected<>nil then
    youttv.Selected.SelectedIndex:=youttv.Selected.ImageIndex;
即可保证图标不变。
treeview中的点有stateindex是选中后的图标值,你一定没改,所以是默认值,而你父图标可能也是默认值,所以一样了,你只要在生成子node 时同时设置imageindex和stateindex就可以了
成功的社区在于拥抱变化——知乎创始人周源专访 优化UITableViewCell高度计算的那些事 国外iOS大牛:开发Apple Watch应用我犯过的错 云上Java System Profiling与Debugging——蚂蚁金服观察与实践 搜狗商业平台Java技术实践 Java在电信软件领域的技术实战 关于Java框架Vert.x的几点思考 Java在游戏服务器开发中的应用 Java框架研发思考 那些年,Java程序员用过的开发工具 Java内存模型的历史变迁 Java 8与Apache Ignite Java开发与技术挑战——关于技术的技术思考 专访唯品会架构师肖桦:做编码的架构师 越来越“简单”的Java 我的Java!越过山丘 专访沙梓社:做个“Think Different”的技术牛人 基于ES6,使用React、Webpack、Babel构建模块化JavaScript应用 财税街创始人石克清:创业须空杯心态+有效社交 自我知识管理:连贯性就是生产率 玩转Google I/O 2015:Android M、IoT、Glass 2.0、VR、ATAP ARC中Retain Cycle揭秘 失控与逆转!企业移动化2.0时代下如何求变? 玩转物联网之MQTT 专访都灵创客教育奚炎:被忽视的Maker教育 13岁iOS开发者:Swift开发Sprite Kit游戏实践 专访豌豆荚「自动装」开发团队:无需Root即可批量点击「下一步」 iOS项目的持续集成与管理 《近匠》谛听科技,探索智慧家庭的智能网关 【简讯】Python 3.5.0b1发布 《算法的乐趣》作者王晓华访谈:多看、多做、多想是秘诀 如何播放Flash? 我的IE不能自动填写域名了!!!第一个答对者20分! 一個很簡單的問題,在線等候,謝謝!! /usr/bin/top的原码在哪个路径下啊?小弟找了好久还是找不到急啊! 尊敬的流芳先生: 程序员考试中的一道很简单的c试题,有个问题 Sun Blade 2000 要多少钱? 活动目录中,遇到这个问题。 我的机器用程序向局域网内的另外一台机器发送一条信息,类似于发送控制台信息 [请教]会用客户端ftp软件客户端代理功能的进来帮帮忙 急求VCD的Specification! 在线紧急求助!!! 在MDI中如何更改子窗口标题? 请问有哪位好心的大哥能给我一个Bounds Checker V601_D.exe 的序列号? 100分求助如何在iPlanet中配置cgi-bin? 高分求助:请问如何确定某个窗口是否存在? 怎么样在vb中把一个excel表的数据拷贝到另一个excel中(包括行高,列宽,字体等) In Pro*c, 为什么我不能用#define UNAME_LEN 20 去定义常量. 高分 高分求《.NET开发的最佳实践与案例分析--北京讲座》示例源码及相关资料!!! 请教高手 那们有 AlphaBlend 函数的帮助中英文都行。 麻烦大家帮我看一下,代码错在那里。 详细说说rs.open sql,conn,Cursor Type,LockType 紧急求救!在线等待: 哪里可下载INTEL IPL库? 关于 我的GNOME的主Panel消失了,我该怎么办???? 一个C程序的问题求助! 请大家推荐一个支持EJB2.0 的免费的应用服务器 运行时建立数据库表 麻烦各位一下,这个错在哪了? 关于access关于自动增量的字段! 关于快捷菜单的问题。 世界上最大规模的大学生群架[真实](转载) win2000日文版与98SE怎么连接? IE6下注销用户的问题。 在线等待! 高分求助! 谁知道哪里有VB7的电子书?? php如何在长字符串中加<br>换行符,以达到强制换行目的?? 谁能讲一讲用evc访问如何访问pc上的数据库? win2k下的一个sql语句 紧急求救 高分求高分求“对话框打印”源码,大家帮我看看我的为什么不行? 视图中的表单公式是不是在IE下无效?为什么我试了一下不起作用? 下拉子数据dddw的问题 用一个窗口调用另一个窗口出现时LOAD事件为何没有做! 怎么写服务器控件的客户端事件阿? 请教透明窗体的实现 不好意思,提个智障问题,感谢帮助。 sql问题,如何用一条sql语句,同时删除两个表中的纪录 关于shell 随便一篇电影的观后感 截止到 5.27 日,选修课用的,2000字左右! 夜晚天空中的云层为什么会有红色的呢?夜间观察会发现天空中的云层,有的是白色或者灰色,但同时也有的云层是红色,这是为什么呢? 仿写句子:天空上的云,有的像羽毛,轻轻的飘在空中;有的像鱼鳞,一片片整齐的排列着.(注意修辞手法以 求一篇关于日本侵略中国的:影视评论\观后感求一篇关于日本侵略中国的:影视评论\观后感或如何看待日本侵华的事实与日本当今为何拒不认罪的现实或者是反思(选其中一种形式字数2000以 为什么傍晚天空是红色的 天上的街市 在哪里使用了联想? 天鹅的见解这篇短文的2~4段意思是什么? 哪一种体育运动最好? 晚上天空上的云为什么发亮在没有夕阳,天空中没有光线的情况下。是不是地上的灯光? 心墙 刘墉 阅读答案 用4个词语描写我一路上天游峰的感受 夜晚的天空为什么可以变成红色? 描写西双版纳 优秀作文300字 摘抄描写天游峰高的句子可可可 记金华的双龙洞课文中的好词佳句 天鹅的见解你对快乐有什么特殊的感受? 体育运动有多少种运动种类 皿加偏旁,缶加偏旁,戈加偏旁 游记作文500字 一共有多少种体育运动这个我还真不知道 知道的来说下 贝加偏旁,皿加偏旁,缶加偏旁,戈加偏旁. 天鹅的见解阅读答案,一匹骏马在湖边饮水;一条鲤鱼在湖里吹气泡;一只雄鹰在湖面上空盘旋.雄鹰一会儿直冲云霄,一会儿滑翔,不屑一顾地对骏马和鲤鱼说:“天空广阔无比,在天空自由自 描写天游峰的词语. 填部首组新字:身、口、工、火、寸、入、戈加同一个部首变为新字 快乐的见解 作文要400字,我悬赏就那么多了 英语翻译请各位英语高手帮忙下翻译一段阿甘的剧本 EXT.GREENBOW,ALABAMA Mrs.Gump and young Forrest walk across the street.Forrest walks stiffly next to his mother.阿甘 Now,when I was a baby,Momma named me after the great Civil Wa 关于天空的个性签名,悲伤点的最好天空是英文的 天游峰的扫路人 哪个句子生动的感受描写天游峰的高与险 求阿甘正传的英文剧本!知道的说下 我长大了300字 天空中为什么出现很长的云?很长很长?这是什么云? 为什么有时侯晚上的天空的云是红色的晚上我在阳台坐的时候发现天空的云是红的是为什么呢? 下暴雨前天空为什么是暗黑色 这云出现在日本的天空上?什麼时候可以出现呢.兄弟们,让我YY一次吧. 求普通高中英语教科书听力录音是人民教育出版社的 求选修6的课文和单词听力~ 两个人从操场的同一地点出发,相反跑步,一直两个人的速度分别是6米/秒和8米/秒,操场一周山是400米,求经过多长时间两个人独二次相遇? 模仿忘不了的笑声写作文,不写笑声,还可以写什么? 只有一个录音机,英语书,磁带,怎么练听力听力不算好,特别是听那些问句选答句的,以及长一点的阅读选项.脑子总反应不过来,刚想起这句话意思,下一段话就过去了英语书是学校发的,磁带学校 甲乙两个人在圆形操场跑步,已知甲的速度比乙快,如果两个人在同一地方同时出发,同向路,则经过3分20秒,可以第一次相遇,若反向跑,则经过40秒,也可以第一次相遇,已知甲跑的速度是每秒跑6米, 爱的消息刘墉阅读答案 六年级下册语文第六单元阅读材料第4课忘不了的笑声说说文章的主要内容 有多久没有抬头仰望苍穹? 为什么会有UFO 六年级《忘不了的笑声》中的人物的性格 天上的街市 第一段在运用比喻的同时,充分展开联想,这样写有什么好处 雪地上的脚印 刘墉 1.雪地上的脚印 的含义2.稳重父亲对离家出走的儿子抱怨着怎样的复杂感情3.为什么儿子离家后,父亲会想起电影 缇萦 中的一幕4.谈谈你对文章中加横线的句子的理解你放 以忘不了为话题写作文600字 为何黄昏时分的天空 成 红色?太阳也成红色?为何天不再 蓝 ?太阳不再 白亮?回 jinshitang6红光 是通过 什么方式到达 地面的。为什么波长长就没有被散射 掉?波长短的蓝光的穿透力不是 很 初二鲁迅的《藤野先生》 最后一节“每当夜间.深恶痛疾的的文字,”此句中的“良心发现”“正人君子”怎么理解?证据话的含义是什么? 《忘不了的笑声》 点评 太阳西下天空为什么是红色 为什么世上会有UFO 天游峰的诗句有 用卓加偏旁,组词新词( )追 下( ) 会有外星人吗? 登上天游峰所想到的诗句还有作者的感受 给”散”加一个偏旁组成新词给”散”加上一个偏旁,组成新词!谢谢了~ 求一篇电影《青春派》的观后感,急用求电影《青春派》的观后感 800字以上,观后感要求对成长和时代特征进行发散思考 《阿甘正传》阿甘的英文名叫什么? 拿字加偏旁组新词拿字加2个偏旁组2个新词
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘