Winform自定义控件之二叉树控件(2)

1. 二叉树控件

(1) 二叉树节点控件一个连接节点只能引出一条连接线

(2) 二叉树节点控件可以自由拖动并且自动绘制连接线

废话不说了实现效果如下:

2. 实现效果如下:

clip_image002

图-1添加节点

clip_image004

图-2 插入节点

clip_image006

图-3 连接节点

clip_image008

图-4 拖动节点调整节点位置

3. 类关系图

clip_image010

4. 实现思路

连接矩形:就是指连接节点上的小方块。

连接矩形名称

枚举对应值

TopRectangle

下左

BottomLeftRectangle

下右

BottomRightRectangle

BNode节点类中存储与它连接的各节点字符串,格式如下:

<当前节点名称-连接矩形类型名称,连接节点-连接矩形类型名称>

当鼠标点击连接矩形是开始记录当前连接矩形,当鼠标释放时记录鼠标释放位置。

鼠标释放时引发连接事件,在外部连接事件中判断鼠标的释放位置是否在进入另一节点的连接矩形中。如果进入了另一节点的连接矩形,就在当前节点中记录当前节点的字符串形式的连接点信息。然后调用绘图方法枚举每个二叉树节点并且根据字符串形式的连接点信息连接每个二叉树节点。

为什么使用字符串格式的连接点信息?

因为字符串格式的存储的只是相对连接信息,当节点移动时更容易计算节点到容器的客户端坐标。如果存储是节点到容器的客户端Point结构的连接点信息,节点移动时需要大量的坐标转化。

5. 重要的算法
(1) 连接点处理

 

ExpandedBlockStart.gif 代码
///   <summary>
        
///  节点的连接点坐标处理
        
///   </summary>
         private   void  AdjNodePointProcess(BNode currentNode)
        {
            List
< BNode >  allList  =   this .Controls.OfType < BNode > ().ToList();

            List
< BNode >  otherList  =  allList.Where(p  =>  p.Name  !=  currentNode.Name).ToList();


            
for  ( int  j  =   0 ; j  <  currentNode.EndPointList.Count; j ++ )
            {

                KeyValuePair
< string , Point >  currentPair  =  currentNode.EndPointList.ToArray()[j];

                
foreach  (var otherBNode  in  otherList)
                {
                    KeyValuePair
< string string >  keyPair  =  HitBNode(currentPair, currentNode, otherBNode);
                    
if  (keyPair.Key  !=   string .Empty)
                    {
                        currentNode.AddAdjNode(keyPair.Key, keyPair.Value);
                    }

                }
            }

        }

 

 

(2) 连接矩形只能有一条连接线限制

 

ExpandedBlockStart.gif 代码
///   <summary>
        
///  添加连接节点
        
///   </summary>
        
///   <param name="key"></param>
        
///   <param name="value"></param>
         public   void  AddAdjNode( string  key, string  value)
        {
            
// 允许a-->b修改为a---->c
             if  (adjNodes.ContainsKey(key))
            {
                adjNodes.Remove(key);
                Debug.WriteLine(
" add line " );
            }

            
// 找出当前节点的父容器
            Control container  =   this .Parent;

            List
< BNode >  list  =  container.Controls.OfType < BNode > ().ToList();
            
// (1)防止集合已有了
            
// a节点 有了 a-->b,b节点有 b-->a
            
// (2)防止集合已有了(同一节点只能有一条连接线)
            
// bNode3|BottomLeftRectangle-bNode4|TopRectangle                                
            
// bNode1|BottomLeftRectangle-bNode4|TopRectangle                                
             if  (
                
! list.Exists(
                
delegate (BNode b) { 
                    
if (b.adjNodes.Count(p => p.Value == key  &&  p.Key == value) > 0 )
                    {
                        
return   true  ;
                    }
                    
return   false ;
                
                }
                )

                
&&
                
! list.Exists(
                
delegate (BNode b) { 
                    
if (b.adjNodes.Count(p => p.Value == value ) > 0   ||  b.adjNodes.Count(p => p.Key == value) > 0
                        
||
                        b.adjNodes.Count(p
=> p.Value  == key  ) > 0   ||  b.adjNodes.Count(p => p.Key == key ) > 0
                        )
                    {
                        
return   true  ;
                    }
                    
return   false ;
                }
                )
                )
            {
                adjNodes.Add(key, value);
            }
        }
 
 

 自定义二叉树示例程序下载

 

 

 

转载于:https://www.cnblogs.com/hbb0b0/archive/2011/01/06/1929018.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值