开源节点框架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}】", "提示");}}
}

测试运行如图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/667857.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1978-2022年人民币汇率(年平均价)数据

1978-2022年人民币汇率&#xff08;年平均价&#xff09;数据 1、时间&#xff1a;1978-2022年&#xff0c;其中人民币对欧元汇率时间为2002-2022年 2、指标&#xff1a;人民币对美元汇率(美元100)(元)、人民币对日元汇率(日元100)(元)、人民币对港元汇率(港元100)(元)、人民…

华为突然官宣:新版鸿蒙系统,正式发布

华为&#xff0c;一家始终引领科技创新潮流的全球性企业&#xff0c;近日再次引发行业震动——全新HarmonyOS NEXT&#xff0c;被誉为“纯血版鸿蒙”的操作系统正式官宣。这是华为在操作系统领域迈出的坚实且具有突破性的一步&#xff0c;标志着华为正逐步摆脱对安卓生态系统的…

3D力导向树插件-3d-force-graph学习002

一、实现效果&#xff1a;节点文字同时展示 节点显示不同颜色节点盒label文字并存节点上添加点击事件 二、利用插件&#xff1a;CSS2DRenderer 提示&#xff1a;以下引入文件均可在安装完3d-force-graph的安装包里找到 三、关键代码 提示&#xff1a;模拟数据可按如下格式填…

Node.js 包管理工具

一、概念介绍 1.1 包是什么 『包』英文单词是 package &#xff0c;代表了一组特定功能的源码集合 1.2 包管理工具 管理『包』的应用软件&#xff0c;可以对「包」进行 下载安装 &#xff0c; 更新 &#xff0c; 删除 &#xff0c; 上传 等操作。 借助包管理工具&#xff0…

视频美颜SDK开发指南:从入门到精通的技术实践

美颜SDK是一种强大的工具&#xff0c;它不仅仅可以让用户在实时视频中获得光滑的肌肤和自然的妆容&#xff0c;从简单的滤镜到复杂的人脸识别&#xff0c;美颜SDK涵盖了广泛的技术领域。 一、美颜SDK的基本原理 美颜SDK包括图像处理、人脸检测和识别、滤镜应用等方面。掌握这些…

uniapp中使用EelementPlus

uniapp的强大是非常震撼的&#xff0c;一套代码可以编写到十几个平台。这个可以在官网上进行查询uni-app官网。主要还是开发小型的软件系统&#xff0c;使用起来非常的方便、快捷、高效。 uniapp中有很多自带的UI&#xff0c;在创建项目的时候&#xff0c;就可以自由选择。而E…

Unity类银河恶魔城学习记录1-11 PlayerPrimaryAttack P38

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Player.cs using System.Collections; using System.Collections.Generic…

苹果公司宣布,为Apple Vision Pro打造了超过600款新应用

深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领域的领跑者。点击订阅&#xff0c;与未来同行&#xff01; 订阅&#xff1a;https://rengongzhineng.io/ 。 2月…

JavaWeb之HTML-CSS --黑马笔记

什么是HTML ? 标记语言&#xff1a;由标签构成的语言。 注意&#xff1a;HTML标签都是预定义好的&#xff0c;HTML代码直接在浏览器中运行&#xff0c;HTML标签由浏览器解析。 什么是CSS ? 开发工具 VS Code --安装文档和安装包都在网盘中 链接&#xff1a;https://p…

git整合分支的两种方法——合并(Merge)、变基(Rebase)

问题描述&#xff1a; 初次向git上传本地代码或者更新代码时&#xff0c;总是会遇到以下两个选项。有时候&#xff0c;只是想更新一下代码&#xff0c;没想到&#xff0c;直接更新了最新的代码&#xff0c;但是自己本地的代码并没有和git上的代码融合&#xff0c;反而被覆盖了…

机器学习系列——(六)数据降维

引言 在机器学习领域&#xff0c;数据降维是一种常用的技术&#xff0c;旨在减少数据集的维度&#xff0c;同时保留尽可能多的有用信息。数据降维可以帮助我们解决高维数据带来的问题&#xff0c;提高模型的效率和准确性。本文将详细介绍机器学习中的数据降维方法和技术&#…

浅谈——开源软件的影响力

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 ✨特色专栏&#xff1a…

数据结构与算法:图论(邻接表板子+BFS宽搜、DFS深搜+拓扑排序板子+最小生成树MST的Prim算法、Kruskal算法、Dijkstra算法)

前言 图的难点主要在于图的表达形式非常多&#xff0c;即数据结构实现的形式很多。算法本身不是很难理解。所以建议精通一种数据结构后遇到相关题写个转换数据结构的接口&#xff0c;再套自己的板子。 邻接表板子&#xff08;图的定义和生成&#xff09; public class Graph…

Java I/O 流

内容体系图 文件基础 说明&#xff1a;输入输出是针对内存来说的 常用的文件操作

zabbix监控mariadb数据库

zabbix监控mariadb数据库 1.创建监控用户及授权 [rootchang ~]# mysql -uroot -p123qqq.A MariaDB [(none)]> CREATE USER monitor% IDENTIFIED BY 123qqq.A; MariaDB [(none)]> GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO monitor%; Maria…

Coil:Android上基于Kotlin协程的超级图片加载库

Coil&#xff1a;Android上基于Kotlin协程的超级图片加载库 1. coil简介 在当今移动应用程序的世界中&#xff0c;图片加载是一个不可或缺的功能。为了让应用程序能够高效地加载和显示图片&#xff0c;开发人员需要依赖于强大的图片加载库。而今天&#xff0c;我将向大家介绍…

爱上算法:每日算法(24-2月4号)

&#x1f31f;坚持每日刷算法&#xff0c;&#x1f603;将其变为习惯&#x1f91b;让我们一起坚持吧&#x1f4aa; 文章目录 [232. 用栈实现队列](https://leetcode.cn/problems/implement-queue-using-stacks/)思路CodeJavaC 复杂度 [225. 用队列实现栈](https://leetcode.cn/…

使用java -jar命令运行jar包提示“错误:找不到或无法加载主类“的问题分析

用maven把普通java项目打包成可运行的jar后&#xff0c;打开cmd用java -jar运行此jar包时报错&#xff1a; 用idea运行该项目则没有问题 。 其实原因很简单&#xff0c;我们忽略了2个细节。 java指令默认在寻找class文件的地址是通过CLASSPATH环境变量中指定的目录中寻找的。我…

Seata介绍

Seata 是一款开源的分布式事务解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 Seata 中有三⼤模块&#xff0c;分别是 TM、RM 和 TC。其中 TM 和 RM 是作为 Seata 的客户端与业务系统集成在⼀起&#xff0c;TC 作为 Seata 的服务端独⽴部署…

浅谈QT的几种线程的使用和区别。

简介&#xff1a; 线程是操作系统中的基本执行单元&#xff0c;是一个独立的执行路径。每个线程都有自己的栈空间&#xff0c;用于存储本地变量和函数调用的上下文。多个线程可以在同一进程中并发执行&#xff0c;从而实现并发处理&#xff0c;提高程序的性能和响应能力。 与进…