乐于分享
好东西不私藏

基于.Net WinForm的节点编辑器纯GDI+绘制支持拖拽绘制节点

基于.Net WinForm的节点编辑器纯GDI+绘制支持拖拽绘制节点

基于.Net WinForm的节点编辑器纯GDI+绘制支持拖拽绘制节点

项目简介

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

在这里插入图片描述

算法原理

核心架构设计

STNodeEditor 采用分层架构设计,主要包含以下核心组件:

  1. 1. STNode(节点基类) :所有自定义节点的基类,提供节点的基本属性(位置、大小、标题、颜色等)和生命周期管理方法(OnCreate、OnDraw、OnSaveNode 等)。
  2. 2. STNodeEditor(节点编辑器) :主控件,负责管理所有节点、连线、画布缩放/移动、事件处理等。
  3. 3. STNodeOption(节点选项) :表示节点的输入/输出端口,支持单连接(圆形)和多连接(方形)模式,自动进行类型兼容性检查。
  4. 4. STNodeHub(节点集线器) :内置特殊节点,用于分线、合并线路,支持动态添加/删除连接点。
  5. 5. STNodePropertyGrid(属性网格) :与节点属性绑定,支持自动识别和显示节点的可配置属性。
  6. 6. 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 的显卡(用于硬件加速渲染)

安装步骤

方法一:从源码编译安装

  1. 1. 克隆项目 :

    git clone https://github.com/DebugST/STNodeEditor.git
    cd STNodeEditor
  2. 2. 打开解决方案 :
    • • 使用 Visual Studio 打开 WinNodeEditorTest.sln 解决方案文件
    • • 或者直接双击 WinNodeEditorTest.sln 文件
  3. 3. 构建项目 :
    • • 在 Visual Studio 中选择 生成 → 重新生成解决方案
    • • 确保构建成功,没有错误
  4. 4. 获取编译结果 :
    • • 编译后的程序位于 WinNodeEditorDemo\bin\Debug\ 目录下
    • • 主要文件: WinNodeEditorDemo.exe 和 ST.Library.UI.dll

方法二:直接运行预编译版本

  1. 1. 下载预编译包 :
    • • 访问 GitHub Releases 页面下载最新版本
    • • 或者直接使用项目根目录下的 WinNodeEditorDemo.exe (如果已存在)
  2. 2. 运行程序 :
    • • 双击 WinNodeEditorDemo.exe 即可启动

运行步骤

启动程序

  1. 1. 双击 WinNodeEditorDemo.exe 启动应用程序
  2. 2. 程序启动后会显示主界面,包含节点编辑器、节点树视图和属性网格

基本操作

创建节点
  • • 在节点树视图中找到需要的节点类型
  • • 将节点拖拽到编辑器画布中
  • • 或者通过代码方式添加: stNodeEditor1.Nodes.Add(new MyNode());
连接节点
  • • 点击源节点的输出端口并拖拽到目标节点的输入端口
  • • 系统会自动检查类型兼容性和环路问题
  • • 支持 Ctrl+拖拽进行快速复制节点
编辑节点
  • • 右键点击节点标题打开上下文菜单
  • • 在属性网格中修改节点属性
  • • 使用鼠标滚轮缩放画布(Ctrl+滚轮)
  • • 中键拖拽移动画布
保存和加载
  • • 保存画布 :点击工具栏的保存按钮或选择 文件 → 保存 ,保存为 .stn 格式文件
  • • 加载画布 :点击工具栏的打开按钮或选择 文件 → 打开 ,加载之前保存的 .stn 文件

高级功能

自定义节点开发
  1. 1. 创建继承自 STNode 的类
  2. 2. 在 OnCreate() 方法中添加输入/输出选项
  3. 3. 重写 OnDrawBody() 方法自定义节点外观
  4. 4. 重写 OnSaveNode() 和 OnLoadNode() 方法实现数据持久化
  5. 5. 使用 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://mbd.pub/o/bread/YZaUk5hwZg==