zoukankan      html  css  js  c++  java
  • 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) 连接点处理
    代码
    /// <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
    <stringstring> keyPair = HitBNode(currentPair, currentNode, otherBNode);
                        
    if (keyPair.Key != string.Empty)
                        {
                            currentNode.AddAdjNode(keyPair.Key, keyPair.Value);
                        }

                    }
                }

            }

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

    代码
    /// <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);
                }
            }
     
     

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

  • 相关阅读:
    1006 Sign In and Sign Out
    1005 Spell It Right
    1004 Counting Leaves
    1003 Emergency
    PAT甲级练习题1001、1002
    翻转字符串.
    JavaScript实现弹幕效果
    SSI技术
    c#事务处理(sqlTransaction)
    Fiddler查看接口响应时间
  • 原文地址:https://www.cnblogs.com/hbb0b0/p/1929018.html
Copyright © 2011-2022 走看看