我做的是一个关于贝叶斯网络的项目,用到了QtNodes,基于我目前做的,讲解一下如何改造QtNodes用到自己项目中
一、QtNodes详细描述
1. 什么是QtNodes?
QtNodes是一个基于Qt框架的开源库,用于创建节点式图形界面。它允许开发者轻松构建可视化的应用程序,如数据流图、流程图、视觉编程工具等。通过QtNodes,用户可以通过拖拽和连接不同的节点来实现复杂的逻辑和数据处理,极大地简化了复杂系统的可视化和交互设计。
2. 主要特点
- 模块化设计:QtNodes采用模块化设计,开发者可以根据需要扩展或定制节点的功能。
- 高度可定制:提供丰富的API接口,允许开发者自定义节点的外观、行为以及数据处理逻辑。
- 跨平台支持:基于Qt框架,QtNodes支持多种操作系统,包括Windows、macOS和Linux。
- 实时交互:支持实时的节点连接和数据传输,适用于需要即时反馈的应用场景。
- 开源社区支持:活跃的开源社区提供了丰富的示例和文档,帮助开发者快速上手。
3. 典型应用场景
- 数据处理工具:如数据可视化、ETL(提取、转换、加载)工具等。
- 视觉编程环境:如图形化的编程工具,适用于教育和快速原型开发。
- 游戏开发:用于构建游戏中的事件系统、行为树等。
- 图像和音频处理:构建复杂的图像或音频处理流水线。
4. 基本架构
QtNodes通常由以下几个主要组件构成:
- Node:基本的节点单元,包含输入和输出端口,用于连接和传输数据。
- Connection:节点之间的连接,表示数据或信号的流动。
- Graph:节点和连接的集合,代表整个图形结构。
- Editor:提供用户交互界面,允许用户添加、删除、连接节点。
QtNodes库来源于:GitHub - paceholder/nodeeditor: Qt Node Editor. Dataflow programming framework
二.深入浅出QtNodes:构建你的第一个节点式应用
1.创建视图和场景,把场景加入视图中,把图形结构加入场景中。视图:QGraphicsView 场景:QGraphicsScene 图形结构:QtNodes::AbstractGraphModel
m_nodeProperty_widget = new NodePropertyWidget;
m_scene = new NodeGraphicsScene(graphModel);
view.setScene(m_scene);
ui->gridLayout->addWidget(&view);
2.添加节点,设置节点显示位置,添加节点间连接关系
NodeId id1 = graphModel.addNode();
graphModel.setNodeData(id1, NodeRole::Position, QPointF(100, 0));
NodeId id2 = graphModel.addNode();
graphModel.setNodeData(id2, NodeRole::Position, QPointF(100, 100));
NodeId id3 = graphModel.addNode();
graphModel.setNodeData(id3, NodeRole::Position, QPointF(0, 200));
NodeId id4 = graphModel.addNode();
graphModel.setNodeData(id4, NodeRole::Position, QPointF(200, 200));
graphModel.addConnection(ConnectionId{id1, 0, id2, 0});
graphModel.addConnection(ConnectionId{id2, 0, id3, 0});
graphModel.addConnection(ConnectionId{id2, 0, id4, 0});
这样节点就可以显示出来了,我这个节点用了自定义的widget,后面再说这部分如何实现。
调用场景的方法setOrientation(Qt::Vertical);可以设置整体垂直或者水平。
三,自定义节点样式、扩展功能
鉴于我目前的项目,改造的内容来展示
1.每个存放自定义数据类型,在QtNodes::AbstractGraphModel子类中
//std::unordered_set<NodeId> _nodeIds;
mutable std::map<NodeId,NodeInfo> _nodeIds;
注意:节点会有复制、粘贴功能,用自定义类型后,自定义类型中的信息可是也是需要拷贝的。
在下面两个函数中实现即可!
在这个函数中,把你需要拷贝节点的数据序列化到返回的json里。
在下方函数中,把序列化的数据反序列化出来。
2.默认只支持线条,使支持箭头
在QtNodes::AbstractConnectionPainter的子类中paint函数中实现
可以控制线段的单箭头和双箭头,我这项目中只有被指向的节点显示箭头,所以下面部分我注释了。
3.节点上显示自定义widget
在节点类中加入以下代码,这样节点上就可以显示自定义widget了,这样显示的内容和布局我们就能很好的控制了。
4.节点支持自己连接自己
在QtNodes::NodeConnectionInteraction类中,注释掉这个判断即可。
还有一些就不全部介绍了,比如节点双击事件、节点和鼠标右键菜单自定义、节点全选、通过鼠标拉取来选择节点、节点连接只允许一端连接一端等等。
5.节点的连线端点,平均分配
在DefaultConnectionPainter::paint函数中,cubicPath函数中获取的连线路径
进入cubicPath函数中,in,out就是原来的两个端点,可以根据原in和out点,再根据与此节点连接的节点数量和坐标重新分配x坐标就好了,inPointPos和outPointPos就是我重新分配x坐标的函数。
这时候会出现上述这种情况,节点往边上移动一些,线端点就显示不全了。
ConnectionGraphicsObject::paint函数里的这行代码记得注释掉,他会限制绘制区域。
这时候就好了