开源节点框架STNodeEditor使用
节点,一般都为树形Tree结构,如TreeNode,XmlNode。
树形结构有其关键属性Parent【父节点】,Children【子节点】
LinkedListNode为链表线性结构,有其关键属性Next【下一个】,Previous【上一个】,
可以用其进行工作流workFlow设计
右键 项目 STNodeDemo,管理NuGet程序包
输入关键字STNodeEditor
安装完成后
我们可以查看工具箱
开源的 .NET 轻量级且功能强大的节点编辑器STNodeEditor
STNodeEditor 是一个轻量且功能强大的节点编辑器 使用方式非常简洁 提供了丰富的属性以及事件可以非常方便的完成节点之间数据的交互及通知 大量的虚函数可供开发者重写具有很高的自由性。
当有很多应用程序(模块) 它们之间需要相互调用传递数据来完成一整套流程的工作 开发单一功能的应用程序(模块)相对比较容易 而实现一整套很多功能相互调用的应用程序相对比较繁琐 此套框架开发者只需要定义好传递的数据类型 然后分别实现单一节点功能 至于执行流程交给框架和用户布线即可。
项目地址
https://github.com/DebugST/STNodeEditor
STNodeEditor是基于WinForm的一套框架 使用GDI+开发 不包含任何额外依赖 整个调用库仅100+kb
项目主页:https://debugst.github.io/STNodeEditor/
教程文档:https://debugst.github.io/STNodeEditor/doc_cn.html
NuGet:https://www.nuget.org/packages/ST.Library.UI/
GitHub:https://github.com/DebugST/STNodeEditor
由上图可见 STNodeEditor 包含3部分 TreeView PropertyGrid NodeEditor 这三部分组成了一套完整的可使用框架
TreeView
开发这可以把执行功能编码到一个节点中 而TreeView则负责展示以及检索节点 在TreeView中的节点可直接拖拽添加到NodeEditor中
PropertyGrid
类似与WinForm开发使用的属性窗口 作为一个节点 它也是可以有属性的 而作者在编辑器进行设计的过程中也把一个节点视作一个Form让开发者几乎没有什么学习成本直接上手一个节点的开发
NodeEditor
NodeEditor是用户组合自己执行流程的地方 使得功能模块执行流程可视化
因ST.Library.UI.NodeEditor.STNode 是一个抽象类,因此我们需要新建一个子类SnakeNode
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ST.Library.UI.NodeEditor;namespace STNodeDemo
{public class SnakeNode : ST.Library.UI.NodeEditor.STNode{public SnakeNode(string title) {this.Title = title;this.TitleColor = Color.FromArgb(200, Color.Goldenrod);}/// <summary>/// 输出节点集合/// </summary>public List<STNodeOption> OutputOptionCollection = new List<STNodeOption>();STNodeOption outputTest;protected override void OnCreate(){base.OnCreate();this.Title = "SnakeNode";//输入项集合int index = this.InputOptions.Add(new STNodeOption("Input1", typeof(string), false));STNodeOption nodeIn2 = this.InputOptions.Add("Input2", typeof(int), false);STNodeOption nodeIn3 = this.InputOptions.Add("Input3", typeof(float), false);//输出项集合STNodeOption nodeOut = this.OutputOptions.Add("Output1", typeof(string), false);outputTest = this.OutputOptions.Add("OutputTime", typeof(DateTime), false);OutputOptionCollection.Add(nodeOut);OutputOptionCollection.Add(outputTest);//STNodeOption[] ss = this.GetOutputOptions();}//当所有者发生改变(即:在NodeEditor中被添加或移除)//应当像容器提交自己拥有数据类型的连接点 所期望显示的颜色//颜色主要用于区分不同的数据类型protected override void OnOwnerChanged(){base.OnOwnerChanged();if (this.Owner == null) return;this.Owner.SetTypeColor(typeof(string), Color.Yellow);//当前容器中已有的颜色会被替换this.Owner.SetTypeColor(typeof(int), Color.DodgerBlue, true);this.Owner.SetTypeColor(typeof(float), Color.Pink, true);this.Owner.SetTypeColor(typeof(DateTime), Color.Green, true);//下面的代码将忽略容器中已有的颜色//this.SetOptionDotColor(op, Color.Red); //无需在OnOwnerChanged()中设置Task.Factory.StartNew(() => {for (int i = 0; i < 50; i++){System.Threading.Thread.Sleep(1000);//STNodeOption.TransferData(object)会自动设置STNodeOption.Data//然后自动向所有连接的选项进行数据传递outputTest.TransferData(DateTime.Now);}});}}
}
新建测试接收节点类ViperNode
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ST.Library.UI.NodeEditor;namespace STNodeDemo
{public class ViperNode : ST.Library.UI.NodeEditor.STNode{public ViperNode(string title) {this.Title = title;this.TitleColor = Color.FromArgb(200, Color.Goldenrod);}/// <summary>/// 输入节点集合/// </summary>public List<STNodeOption> InputOptionCollection = new List<STNodeOption>();STNodeOption inputTest;protected override void OnCreate(){base.OnCreate();this.Title = "ViperNode";//输入项集合inputTest = this.InputOptions.Add("ViperTime", typeof(DateTime), false);inputTest.DataTransfer += new STNodeOptionEventHandler(InputTest_DataTransfer);InputOptionCollection.Add(inputTest);}private void InputTest_DataTransfer(object sender, STNodeOptionEventArgs e){//当连接的建立与断开都会触发此事件 所以需要判断连接状态if (e.Status != ConnectionStatus.Connected || e.TargetOption.Data == null){//当 STNode.AutoSize=true 并不建议使用STNode.SetOptionText//因为当文本发生改变时候会重新计算布局 正确的做法是自定义一个如Lable控件//作为时间的显示 当然这里为了演示方式采用此方案this.SetOptionText(inputTest, "--");}else{this.SetOptionText(inputTest, Convert.ToDateTime(e.TargetOption.Data).ToString("yyyy-MM-dd HH:mm:ss.fff"));}}}
}
新建测试窗体FormSTNode,设计如下
FormSTNode.Designer.cs设计器代码如下:
namespace STNodeDemo
{partial class FormSTNode{/// <summary>/// 必需的设计器变量。/// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// 清理所有正在使用的资源。/// </summary>/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows 窗体设计器生成的代码/// <summary>/// 设计器支持所需的方法 - 不要修改/// 使用代码编辑器修改此方法的内容。/// </summary>private void InitializeComponent(){this.stNodeEditor1 = new ST.Library.UI.NodeEditor.STNodeEditor();this.btnConnectLine = new System.Windows.Forms.Button();this.SuspendLayout();// // stNodeEditor1// this.stNodeEditor1.AllowDrop = true;this.stNodeEditor1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(34)))), ((int)(((byte)(34)))), ((int)(((byte)(34)))));this.stNodeEditor1.Curvature = 0.3F;this.stNodeEditor1.Location = new System.Drawing.Point(12, 67);this.stNodeEditor1.LocationBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(120)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));this.stNodeEditor1.MarkBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(180)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));this.stNodeEditor1.MarkForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(180)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));this.stNodeEditor1.MinimumSize = new System.Drawing.Size(100, 100);this.stNodeEditor1.Name = "stNodeEditor1";this.stNodeEditor1.Size = new System.Drawing.Size(1160, 475);this.stNodeEditor1.TabIndex = 0;this.stNodeEditor1.Text = "stNodeEditor1";// // btnConnectLine// this.btnConnectLine.Font = new System.Drawing.Font("宋体", 16F);this.btnConnectLine.Location = new System.Drawing.Point(52, 12);this.btnConnectLine.Name = "btnConnectLine";this.btnConnectLine.Size = new System.Drawing.Size(169, 33);this.btnConnectLine.TabIndex = 1;this.btnConnectLine.Text = "连线-显示时间";this.btnConnectLine.UseVisualStyleBackColor = true;this.btnConnectLine.Click += new System.EventHandler(this.btnConnectLine_Click);// // FormSTNode// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(1200, 554);this.Controls.Add(this.btnConnectLine);this.Controls.Add(this.stNodeEditor1);this.Name = "FormSTNode";this.Text = "STNodeEditor开源框架,输入输出";this.Load += new System.EventHandler(this.FormSTNode_Load);this.ResumeLayout(false);}#endregionprivate ST.Library.UI.NodeEditor.STNodeEditor stNodeEditor1;private System.Windows.Forms.Button btnConnectLine;}
}
窗体FormSTNode.cs测试代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;using ST.Library.UI.NodeEditor;namespace STNodeDemo
{public partial class FormSTNode : Form{public FormSTNode(){InitializeComponent();//参考地址 https://blog.csdn.net/crystal_lz/article/details/117131080/*single-connection
单连接模式 在单连接模式下一个连接点同时 只能被一个 同数据类型点的连接
multi-connection
多连接模式 在多连接模式下一个连接点同时 可以被多个 同数据类型点连接数据交互:STNodeOption可以通过绑定DataTransfer事件获取到传入该选项的所有数据
STNodeOption可以通过TransferData(object obj)向该选项上所有连接的选项进行数据投递*/}private void FormSTNode_Load(object sender, EventArgs e){SnakeNode stNode = new SnakeNode("STNode的标题");stNode.Location = new Point(10, 10);stNodeEditor1.Nodes.Add(stNode);ViperNode destNode = new ViperNode("显示时间");destNode.Location = new Point(400, 10);stNodeEditor1.Nodes.Add(destNode);}/// <summary>/// 获取指定的输出节点选项/// </summary>/// <param name="node"></param>/// <param name="strText"></param>/// <returns></returns>private STNodeOption GetOutNodeOption(SnakeNode node, string strText) {STNodeOption outNodeOption = node.OutputOptionCollection.FirstOrDefault(option => option.Text == strText);return outNodeOption;}/// <summary>/// 获取指定的输入节点选项/// </summary>/// <param name="node"></param>/// <param name="strText"></param>/// <returns></returns>private STNodeOption GetInNodeOption(ViperNode node, string strText){STNodeOption inNodeOption = node.InputOptionCollection.FirstOrDefault(option => option.Text == strText);return inNodeOption;}private void btnConnectLine_Click(object sender, EventArgs e){STNodeOption outNodeOption = GetOutNodeOption((SnakeNode)stNodeEditor1.Nodes[0], "OutputTime");STNodeOption inNodeOption = GetInNodeOption((ViperNode)stNodeEditor1.Nodes[1], "ViperTime");ConnectionStatus connectionStatus = outNodeOption.ConnectOption(inNodeOption);MessageBox.Show($"输出节点 连接 输入节点 的状态结果【{connectionStatus}】", "提示");}}
}
测试运行如图:
相关文章:

开源节点框架STNodeEditor使用
节点,一般都为树形Tree结构,如TreeNode,XmlNode。 树形结构有其关键属性Parent【父节点】,Children【子节点】 LinkedListNode为链表线性结构,有其关键属性Next【下一个】,Previous【上一个】,…...
算法每日一题: Nim游戏 | 找规律
哈哈,大家好,我是星恒,今天的每日一题真开心,连做了3天牢,终于ak了一道,太不容易了 这道题其实就是找规律,刚开始我还以为是动归,但是列举了不少例子之后,发现有自己直接…...

分类预测 | Matlab实现GAF-PCNN-MATT格拉姆角场和双通道PCNN融合多头注意力机制的分类预测/故障识别
分类预测 | Matlab实现GAF-PCNN-MATT格拉姆角场和双通道PCNN融合多头注意力机制的分类预测/故障识别 目录 分类预测 | Matlab实现GAF-PCNN-MATT格拉姆角场和双通道PCNN融合多头注意力机制的分类预测/故障识别分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现G…...
Dockerfile保留字
目录 一、Dockerfile保留字是什么? 二、Docker构建流程 1. 从基础镜像运行容器 2. 执行指令并修改容器 3. 提交新的镜像层 4. 基于新镜像运行新容器 5. 执行下一条指令 6. 循环执行指令 7. 所有指令执行完成 三、保留字 1. FROM 使用基础镜像作为起点 2.…...
Linux的7个运行级别
目录 1、有那7个运行级别? 2、那么如何查看运行级别呢? 3、那么我想临时切换运行级别? 4、那么我想修改配置文件中的运行级别呢? 1、有那7个运行级别? 0:停机状态。系统默认运行级别不能设置为0,否则系统不能正常启动&a…...
Linux期末总复习( 详解 )
文章目录 一、选择题二、填空题三、简答题四、操作题 一、选择题 1.在创建Linux分区时,一定要创建( D )两个分区 A. FAT/NTFS B. FAT/SWAP C. NTFS/SWAP D.SWAP/根分区 2.在Red Hat Linux 9 中,系统默认的…...

【Linux系统化学习】进程等待
目录 进程等待 进程等待的必要性 进程等待的方法 wait方法 等待一个进程(阻塞等待) waitpid方法 任意等待多个进程(阻塞等待) 父进程获取子进程的退出信息 非阻塞轮询等待 进程等待 进程等待的必要性 之前讲过,子进程退…...

前端学习笔记 | HTML5+CSS3静态网页制作的技巧(持续更新)
注:本文的css样式均使用less写法 1、字体居中 (1)先text-align:center;行内元素水平居中 (2)再line-heigh:(盒子高度);行内元素垂直居中 text-align: center;line-height: ( 30 / vw ); 2、盒子居中 情景1&#…...

docker安装-centos
Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10 卸载旧版本Docker sudo yum remove docker \ docker-common \ docker-selinux \ docker-engine使用yum安装 yum 更新到最新版本: sudo yum update执行以下命令安装依赖包: sudo yum…...

Redis入门指南
文章目录 Redis概述Redis基本数据类型Redis与MySQL的区别以及使用场景如何保持双写一致性(缓存一致性)1. 延迟双删2. 分布式锁(强一致性时使用)3. 中间件 Redis持久化机制RDB(redis database)AOF࿰…...
K8s之configMap
1. 概述 1.1 什么是configMap 1.1 什么是configMap configMap是Kubernetes中的一种资源对象,用于存储配置数据。它可以包含键值对,也可以包含来自文件的配置数据。configMap的作用是将配置数据与应用程序的容器分离,使得配置可以在不重…...

提高 NFS Azure 文件共享性能
本文内容 适用于增加预读大小以提高读取吞吐量Nconnect另请参阅 本文介绍如何提高 NFS Azure 文件共享的性能。 适用于 展开表 文件共享类型SMBNFS标准文件共享 (GPv2)、LRS/ZRS 标准文件共享 (GPv2)、GRS/GZRS 高级文件共享 (FileStorage)、LRS/ZRS 增加预读大…...
【Django-ninja】使用schema
在Django Ninja中,"schema"主要是指帮助描述和规范你的API的工具,以便系统能够自动生成文档并提供验证。通俗地说,它有两个主要作用: API文档生成器: Schema 让 Django Ninja 能够自动生成互动式的API文档。…...

【TCP/IP】用户访问一个购物网站时TCP/IP五层参考模型中每一层的功能
当用户访问一个购物网站时,网络上的每一层都会涉及不同的协议,具体网络模型如下图所示。 以下是每个网络层及其相关的协议示例: 物理层:负责将比特流传输到物理媒介上,例如电缆或无线信号。所以在物理层,可…...
Unity 开发注意事项
1. 空Unity消息 Unity消息被运行时事件调用,即使消息体为空也会被调用。因此,删除空消息避免不必要的处理。 例如: using UnityEngine;class Camera : MonoBehaviour {private void FixedUpdate(){}private void Foo(){} } 应该删除未使用…...
[Unity Sentis] Unity Sentis 详细步骤工作流程
文章目录 1. 导入模型文件支持的模型创建运行时模型导入错误 2. 为模型创建输入将数组转换为张量创建多个输入进行操作 3. 创建一个引擎来运行模型创建一个Worker后端类型 4. 运行模型5. 获取模型的输出获取张量输出多个输出打印输出 1. 导入模型文件 要导入 ONNX 模型文件&am…...

力扣144 二叉树的前序遍历 Java版本
文章目录 题目描述递归方法代码 非递归方法代码 题目描述 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 示例 1: 输入:root [1,null,2,3] 输出:[1,2,3] 示例 2: 输入:root [] 输出…...

《Vue3 基础知识》 使用 GoGoCod 升级到Vue3+ElementPlus 适配处理
此篇为 《Vue2ElementUI 自动转 Vue3ElementPlus(GoGoCode)》 的扩展! Vue3 适配 Vue3 不兼容适配 Vue 3 迁移指南 在此,本章只讲述项目或组件库中遇到的问题; Vue3 移除 o n , on, on&#…...

c#string方法对比
字符串的截取匹配操作在开发中非常常见,比如下面这个示例:我要匹配查找出来字符串数组中以“abc”开头的字符串并打印,我下面分别用了两种方式实现,代码如下: using System; namespace ConsoleApp23{ class Progra…...

Electron实战(一):环境搭建/Hello World/打包exe
文章目录 Electron安装Node.jsNodeJs推荐配置开始Electron项目创建index.js文件创建src目录运行打包生成exe生成安装包踩坑 下一篇Electron实战(二):将Node.js和UI能力(app/BrowserWindow/dialog)等注入html Electron Electron是一个使用JavaScript, HT…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...

Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...