项目简介
STNodeEditor 是一个轻量且功能强大的节点编辑器,基于 Windows Forms 开发。它提供了一套完整的可视化编程框架,允许开发者通过拖拽连接节点的方式来构建数据处理流程。该项目受到 Blender、GNURadio 和 Davinci Resolve 等专业节点编辑软件的启发,旨在为 .NET 开发者提供一个灵活、可扩展的节点式编程解决方案。

算法原理
核心架构设计
STNodeEditor 采用分层架构设计,主要包含以下核心组件:
- STNode(节点基类):所有自定义节点的基类,提供节点的基本属性(位置、大小、标题、颜色等)和生命周期管理方法(OnCreate、OnDraw、OnSaveNode 等)。
- STNodeEditor(节点编辑器):主控件,负责管理所有节点、连线、画布缩放/移动、事件处理等。
- STNodeOption(节点选项):表示节点的输入/输出端口,支持单连接(圆形)和多连接(方形)模式,自动进行类型兼容性检查。
- STNodeHub(节点集线器):内置特殊节点,用于分线、合并线路,支持动态添加/删除连接点。
- STNodePropertyGrid(属性网格):与节点属性绑定,支持自动识别和显示节点的可配置属性。
- STNodeTreeView(节点树视图):提供节点分类浏览和拖拽功能,支持按路径组织节点。

关键算法实现
1. 连线算法
- 类型兼容性检查:在连接两个节点时,自动检测数据类型是否兼容,防止不匹配的数据流。
- 环路检测:通过深度优先搜索(DFS)算法检测是否存在环形连接,避免无限循环。
- 重复连接检测:检查是否已存在相同源-目标的连接,防止重复连线。
- 曲线绘制:使用贝塞尔曲线算法绘制连线,支持曲度调节(Curvature 属性)。
2. 布局与渲染算法
- 自动布局计算:节点自动计算最佳尺寸(AutoSize),根据标题长度、选项数量和文本宽度动态调整大小。
- 磁铁吸附算法:移动节点时,自动吸附到其他节点的边界或网格线上,提高布局精度。
- 双缓冲渲染:使用双缓冲技术减少闪烁,提升绘制性能。
- 区域裁剪优化:只重绘发生变化的区域,提高渲染效率。
3. 事件处理机制
- 事件冒泡系统:鼠标事件(点击、悬停、拖拽)在节点层次中正确传递和处理。
- 状态管理:维护节点的选中、活动、悬停等状态,并触发相应事件。
- 异步操作:支持异步加载/保存画布,避免界面阻塞。
4. 数据持久化
- 二进制序列化:使用自定义二进制格式保存节点状态,包括位置、大小、连接关系、属性值等。
- 类型安全存储:为每个属性类型提供专门的序列化/反序列化处理器,确保数据完整性。
- 版本兼容性:支持向后兼容的文件格式,新版本可以打开旧版本保存的文件。
环境要求
开发环境
- 操作系统:Windows 7 及以上版本(推荐 Windows 10/11)
- .NET Framework:.NET Framework 4.6.1 或更高版本
- 开发工具:Visual Studio 2017 或更高版本(推荐 VS 2019/2022)
运行环境
- 客户端:Windows 操作系统
- .NET Framework:.NET Framework 4.6.1 运行时
- 硬件要求:
- CPU:Intel Core i3 或同等性能处理器
- 内存:2GB RAM(推荐 4GB)
- 显卡:支持 DirectX 9 的显卡(用于硬件加速渲染)
安装步骤
方法一:从源码编译安装
-
克隆项目:
git clone https://github.com/DebugST/STNodeEditor.git cd STNodeEditor -
打开解决方案:
- 使用 Visual Studio 打开
WinNodeEditorTest.sln解决方案文件 - 或者直接双击
WinNodeEditorTest.sln文件
- 使用 Visual Studio 打开
-
构建项目:
- 在 Visual Studio 中选择
生成→重新生成解决方案 - 确保构建成功,没有错误
- 在 Visual Studio 中选择
-
获取编译结果:
- 编译后的程序位于
WinNodeEditorDemo\bin\Debug\目录下 - 主要文件:
WinNodeEditorDemo.exe和ST.Library.UI.dll
- 编译后的程序位于
方法二:直接运行预编译版本
-
下载预编译包:
- 访问 GitHub Releases 页面下载最新版本
- 或者直接使用项目根目录下的
WinNodeEditorDemo.exe(如果已存在)
-
运行程序:
- 双击
WinNodeEditorDemo.exe即可启动
- 双击
运行步骤
启动程序
- 双击
WinNodeEditorDemo.exe启动应用程序 - 程序启动后会显示主界面,包含节点编辑器、节点树视图和属性网格
基本操作
创建节点
- 在节点树视图中找到需要的节点类型
- 将节点拖拽到编辑器画布中
- 或者通过代码方式添加:
stNodeEditor1.Nodes.Add(new MyNode());
连接节点
- 点击源节点的输出端口并拖拽到目标节点的输入端口
- 系统会自动检查类型兼容性和环路问题
- 支持 Ctrl+拖拽进行快速复制节点
编辑节点
- 右键点击节点标题打开上下文菜单
- 在属性网格中修改节点属性
- 使用鼠标滚轮缩放画布(Ctrl+滚轮)
- 中键拖拽移动画布
保存和加载
- 保存画布:点击工具栏的保存按钮或选择
文件→保存,保存为.stn格式文件 - 加载画布:点击工具栏的打开按钮或选择
文件→打开,加载之前保存的.stn文件
高级功能
自定义节点开发
- 创建继承自
STNode的类 - 在
OnCreate()方法中添加输入/输出选项 - 重写
OnDrawBody()方法自定义节点外观 - 重写
OnSaveNode()和OnLoadNode()方法实现数据持久化 - 使用
STNodePropertyAttribute标记属性,使其在属性网格中显示
节点属性配置
- 在节点类中使用
[STNodePropertyAttribute]特性标记需要在属性网格中显示的属性 - 支持基本类型(int、float、double、bool、string、enum)及其数组
- 可以自定义属性描述器(STNodePropertyDescriptor)支持复杂类型
注意事项
使用注意事项
- 节点命名规范:节点标题应简洁明了,避免使用特殊字符
- 类型匹配:连接节点时确保数据类型兼容,否则连接会被拒绝
- 环路避免:避免创建可能导致无限循环的节点连接
- 性能优化:大量节点时建议关闭网格显示(ShowGrid = false)以提高性能
- 内存管理:及时释放不再使用的节点,避免内存泄漏
开发注意事项
- 构造函数要求:自定义节点必须提供空参数构造函数,否则无法通过反射创建
- 线程安全:所有 UI 操作必须在主线程中执行,使用
Invoke()或BeginInvoke()处理跨线程调用 - 资源释放:重写
Dispose()方法释放 GDI+ 资源(如 Image、Pen、Brush 等) - 异常处理:在
OnSaveNode()和OnLoadNode()中添加适当的异常处理,避免数据损坏
常见问题解决
连接失败
- 检查数据类型是否兼容
- 检查是否已存在相同连接
- 检查是否形成环路
- 查看状态栏提示信息
渲染异常
- 确认 .NET Framework 版本是否正确
- 尝试禁用硬件加速:
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false); - 检查自定义绘制代码是否有异常
性能问题
- 减少节点数量或简化节点外观
- 关闭不必要的视觉效果(网格、边框、磁铁效果)
- 使用
CanvasScale控制缩放级别
文件夹结构介绍
STNodeEditor/
├── .gitignore # Git 忽略文件配置
├── LICENSE # MIT 开源许可证
├── README.md # 项目原始 README 文件
├── README2.md # 本项目文档(当前文件)
├── WinNodeEditorTest.sln # Visual Studio 解决方案文件
├── WinNodeEditorTest.suo # Visual Studio 用户选项文件
├── docs/ # 项目文档
│ ├── css/ # CSS 样式文件
│ ├── images/ # 文档图片资源
│ ├── js/ # JavaScript 脚本
│ ├── api.html # API 文档
│ ├── doc_cn.html # 中文文档入口
│ ├── doc_en.html # 英文文档入口
│ ├── index.html # 文档首页
│ ├── tutorials_cn.html # 中文教程文档
│ └── tutorials_en.html # 英文教程文档
├── ST.Library.UI/ # 核心库项目
│ ├── NodeEditor/ # 节点编辑器核心代码
│ │ ├── FrmNodePreviewPanel.cs # 节点预览面板
│ │ ├── FrmSTNodePropertyInput.cs # 节点属性输入窗体
│ │ ├── FrmSTNodePropertySelect.cs # 节点属性选择窗体
│ │ ├── STNode.cs # 节点基类
│ │ ├── STNodeAttribute.cs # 节点特性类
│ │ ├── STNodeCollection.cs # 节点集合类
│ │ ├── STNodeControl.cs # 节点控件基类
│ │ ├── STNodeControlCollection.cs # 节点控件集合类
│ │ ├── STNodeEditor.cs # 节点编辑器主控件
│ │ ├── STNodeEditorDataType.cs # 节点编辑器数据类型
│ │ ├── STNodeEditorPannel.cs # 节点编辑器面板
│ │ ├── STNodeHub.cs # 节点集线器
│ │ ├── STNodeOption.cs # 节点选项类
│ │ ├── STNodeOptionCollection.cs # 节点选项集合类
│ │ ├── STNodePropertyAttribute.cs # 节点属性特性
│ │ ├── STNodePropertyGrid.cs # 节点属性网格
│ │ └── STNodeTreeView.cs # 节点树视图
│ ├── Properties/ # 项目属性
│ │ └── AssemblyInfo.cs # 程序集信息
│ ├── bin/Debug/ # 编译输出目录
│ │ ├── ST.Library.UI.dll # 核心库 DLL
│ │ └── ST.Library.UI.pdb # 调试符号文件
│ └── ST.Library.UI.csproj # 核心库项目文件
└── WinNodeEditorDemo/ # 示例演示项目
├── Blender/ # Blender 相关节点
│ ├── BlenderMixColorNode.cs # Blender 混合颜色节点
│ ├── FrmEnumSelect.cs # 枚举选择窗体
│ ├── STNodeCheckBox.cs # 复选框节点控件
│ ├── STNodeColorButton.cs # 颜色按钮节点控件
│ ├── STNodeProgress.cs # 进度条节点控件
│ └── STNodeSelectBox.cs # 选择框节点控件
├── ImageNode/ # 图像处理节点
│ ├── ImageBaseNode.cs # 图像基础节点
│ ├── ImageChannelNode.cs # 图像通道节点
│ └── ImageInputNode.cs # 图像输入节点
├── NumberNode/ # 数值处理节点
│ ├── NumberAddNode.cs # 数值加法节点
│ ├── NumberInputNode.cs # 数值输入节点
│ └── NumberNode.cs # 数值基础节点
├── Properties/ # 项目属性
│ ├── AssemblyInfo.cs # 程序集信息
│ ├── Resources.Designer.cs # 资源设计器
│ ├── Resources.resx # 资源文件
│ ├── Settings.Designer.cs # 设置设计器
│ └── Settings.settings # 应用设置
├── bin/Debug/ # 编译输出目录
│ ├── ST.Library.UI.dll # 核心库引用
│ ├── WinNodeEditorDemo.exe # 主程序
│ └── WinNodeEditorDemo.pdb # 调试符号文件
├── AttrTestNode.cs # 属性测试节点
├── CalcNode.cs # 计算节点
├── EmptyOptionTestNode.cs # 空选项测试节点
├── Form1.Designer.cs # 主窗体设计器
├── Form1.cs # 主窗体逻辑
├── Form1.resx # 主窗体资源
├── Program.cs # 程序入口
├── STNodeHub.cs # 节点集线器(示例)
├── ToolStripRendererEx.cs # 工具栏渲染器
└── WinNodeEditorDemo.csproj # 示例项目文件
源码地址:https://download.csdn.net/download/FL1623863129/90010624
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/FL1623863129/article/details/162761575



