|
1 | | -# DotNet_WinForm_NodeEditor |
2 | | -一款基于.Net WinForm的节点编辑器 纯GDI+绘制 |
| 1 | +## STNodeEditor |
| 2 | + |
| 3 | +`STNodeEditor` 是一个很不错的节点编辑器 使用方式非常简洁 提供了丰富的属性以及事件 可以非常方便的完成节点之间数据的交互及通知 大量的重载函数供开发者使用具有很高的自由性 |
| 4 | + |
| 5 | +编译环境: `VS 2010 (.Net 3.5)` |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +此控件采用 [`MIT`](https://opensource.org/licenses/mit-license.php) 开源协议开源 使开发者能够拥有更大的自由度更少的限制 |
| 10 | + |
| 11 | +`STNodeEditor` 拥有非常方便的UI自定义能力 提供的 `STNodeControl` 基类 可以让开发者能够像自定义 `WinForm` 控件一样去定义 节点需要的控件 |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +## 简要说明 |
| 16 | +* 画布 |
| 17 | + * 移动 `鼠标中键` 拖动 Mac用户可二指拖动 `触控板` |
| 18 | + * 缩放 按下 `Control` + `鼠标滚轮` |
| 19 | + * 画布中的节点内容以及连线关系可通过 `STNodeEditor.Load/SaveCanvas()` 加载或者保存 |
| 20 | +* 删除连线 |
| 21 | + * 悬停到连线上 `鼠标右键` |
| 22 | +* 移动节点 |
| 23 | + * `鼠标左键` 拖动 `节点标题` |
| 24 | + * 之所以是拖动标题而不是节点任意位置 是因为作者的设计思路是将节点视为一个 `窗体` 窗体的客户区域留给开发者自定义 |
| 25 | +* STNode |
| 26 | + * 如同 `System.Windows.Forms.TreeView` 一样 所有的节点都保存在 `STNodeEditor.Nodes` 中 其数据类型为 `STNode` |
| 27 | + * `STNode` 为抽象类被 `abstract` 修饰 需要开发者自己继承向节点中添加选项 |
| 28 | + * `STNode` 有三个重要属性 `InputOptions` `OutputOptions` `Controls` |
| 29 | + |
| 30 | +## 示例 |
| 31 | +```cs |
| 32 | +public class DemoNode : STNode |
| 33 | +{ |
| 34 | + protected override void OnCreate() { |
| 35 | + //在创建节点时候向其添加需要的选项 |
| 36 | + base.OnCreate(); |
| 37 | + this.InputOptions.Add(new STNodeOption("Input", typeof(string), false)); |
| 38 | + this.InputOptions.Add(new STNodeOption("SingleNode", typeof(System.Drawing.Image), true)); |
| 39 | + this.InputOptions.Add(new STNodeOption("SingleNode", typeof(object), true)); |
| 40 | + |
| 41 | + this.OutputOptions.Add(new STNodeOption("output", typeof(string), false)); |
| 42 | + this.OutputOptions.Add(new STNodeOption("Single", typeof(System.Drawing.Icon), true)); |
| 43 | + this.OutputOptions.Add(new STNodeOption("Single", typeof(object), true)); |
| 44 | + |
| 45 | + this.Title = "Demo_Node"; |
| 46 | + } |
| 47 | +} |
| 48 | +//stNodeEditor1.SetTypeColor(type, color);此方法会自动替换已存在值 |
| 49 | +stNodeEditor1.TypeColor.Add(typeof(string), Color.Yellow); |
| 50 | +stNodeEditor1.TypeColor.Add(typeof(Image), Color.Red); |
| 51 | +stNodeEditor1.Nodes.Add(new DemoNode()); |
| 52 | +``` |
| 53 | +上述代码的 `DemoNode` 被添加到节点编辑器中的效果为 |
| 54 | + |
| 55 | + |
| 56 | + |
| 57 | +由此可见 开发者要自定义一个节点相当便捷 当然上述代码并没有包含事件处理 上述代码仅仅是在演示 `STNodeOption` 的效果 下列代码则是一个包含了计算两个整数和的功能 |
| 58 | +```cs |
| 59 | +public class NodeNumberAdd : STNode |
| 60 | +{ |
| 61 | + private STNodeOption m_in_num1; |
| 62 | + private STNodeOption m_in_num2; |
| 63 | + private STNodeOption m_out_num; |
| 64 | + private int m_nNum1, m_nNum2; |
| 65 | + |
| 66 | + protected override void OnCreate() { |
| 67 | + base.OnCreate(); |
| 68 | + this.Title = "NumberAdd"; |
| 69 | + m_in_num1 = new STNodeOption("num1", typeof(int), true);//只能有一个连线 |
| 70 | + m_in_num2 = new STNodeOption("num2", typeof(int), true);//只能有一个连线 |
| 71 | + m_out_num = new STNodeOption("result", typeof(int), false);//可以多个连线 |
| 72 | + this.InputOptions.Add(m_in_num1); |
| 73 | + this.InputOptions.Add(m_in_num2); |
| 74 | + this.OutputOptions.Add(m_out_num); |
| 75 | + m_in_num1.DataTransfer += new STNodeOptionEventHandler(m_in_num_DataTransfer); |
| 76 | + m_in_num2.DataTransfer += new STNodeOptionEventHandler(m_in_num_DataTransfer); |
| 77 | + } |
| 78 | + //当有数据传入时 |
| 79 | + void m_in_num_DataTransfer(object sender, STNodeOptionEventArgs e) { |
| 80 | + //判断连线是否是连接状态(建立连线 断开连线 都会触发该事件) |
| 81 | + if (e.Status == ConnectionStatus.Connected) { |
| 82 | + if (sender == m_in_num1) |
| 83 | + m_nNum1 = (int)e.TargetOption.Data;//TargetOption为触发此事件的Option |
| 84 | + else |
| 85 | + m_nNum2 = (int)e.TargetOption.Data; |
| 86 | + } else { |
| 87 | + if (sender == m_in_num1) m_nNum1 = 0; else m_nNum2 = 0; |
| 88 | + } |
| 89 | + //向输出选项上的所有连线传输数据 输出选项上的所有连线都会触发 DataTransfer 事件 |
| 90 | + m_out_num.TransferData(m_nNum1 + m_nNum2); //m_out_num.Data 将被自动设置 |
| 91 | + } |
| 92 | + |
| 93 | + protected override void OnOwnerChanged() { |
| 94 | + //通常刚被添加到节点编辑器时触发 如是以插件方式提供的节点 应当向编辑器提交数据类型颜色 |
| 95 | + base.OnOwnerChanged(); |
| 96 | + if (this.Owner == null) return; //或者通过m_in_num1.DotColor = Color.Red;进行设置 |
| 97 | + this.Owner.SetTypeColor(typeof(int),Color.Red); |
| 98 | + } |
| 99 | +} |
| 100 | +``` |
| 101 | +效果为 |
| 102 | + |
| 103 | + |
| 104 | + |
| 105 | +更多细节请参考文档 |
| 106 | + |
| 107 | +项目主页: [DebugST.github.io/DotNet_WinForm_NodeEditor](https://DebugST.github.io/DotNet_WinForm_NodeEditor) |
| 108 | + |
| 109 | +开发文档: [DebugST.github.io/DotNet_WinForm_NodeEditor/doc.html](https://DebugST.github.io/DotNet_WinForm_NodeEditor/doc.html) |
| 110 | + |
| 111 | +## 关于作者 |
| 112 | +* Github: [DebugST](https://DebugST.github.io) |
| 113 | +* Blog: [Crystal_lz](http://st233.com) |
| 114 | +* Mail: (2212233137@qq.com) |
0 commit comments