ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

QtNodes 官方示例全解析:从数据流计算到自定义渲染的 11 个实战工程

QtNodes 官方示例全解析:从数据流计算到自定义渲染的 11 个实战工程 UI组件数据可视化【免费下载链接】nodeeditorQt Node Editor. Dataflow programming framework项目地址https://gitcode.com/gh_mirrors/no/nodeeditor点击查看免费下载本文以 QtNodesQt 节点图编辑器库数据流编程框架官方文档的 示例索引页 为骨架逐一对仓库examples/目录下的 11 个可运行示例进行剖析覆盖构建方式、每个示例解决的问题与关键技术点、无界面Headless计算模式以及运行命令。读完本文你将掌握 QtNodes 的两大使用范式——自定义图模型AbstractGraphModelBasicGraphicsScene与数据流模型DataFlowGraphModelDataFlowGraphicsScene并能直接挑选最合适的示例作为自己项目的起点。示例总览与构建方式官方文档明确指出所有示例都位于仓库根目录的examples/目录通过 CMake 选项-DBUILD_EXAMPLESON构建且该选项默认开启。这意味着只要按标准流程配置 QtNodes 项目示例二进制会被一并编译出来。从 examples/CMakeLists.txt 的源码可以看出示例通过 11 个add_subdirectory子目录组织add_subdirectory(simple_graph_model) add_subdirectory(vertical_layout) add_subdirectory(calculator) add_subdirectory(text) add_subdirectory(resizable_images) add_subdirectory(styles) add_subdirectory(connection_colors) add_subdirectory(dynamic_ports) add_subdirectory(lock_nodes_and_connections) add_subdirectory(node_validation) add_subdirectory(custom_painter)每个子目录对应一个独立可执行程序演示 QtNodes 的一项或一组核心能力。下表是官方文档给出的完整画廊一览示例目录核心演示内容examples/calculator/完整数据流应用数字源、运算符、显示节点内嵌控件、保存/加载、菜单集成examples/simple_graph_model/最小化自定义图模型继承AbstractGraphModel并使用BasicGraphicsSceneexamples/styles/自定义样式不同配色方案与视觉效果examples/connection_colors/基于数据类型的连接配色每种数据类型拥有独立颜色examples/vertical_layout/自上而下的节点布局端口位于上下边缘examples/dynamic_ports/运行时增删端口演示两阶段端口修改 APIexamples/resizable_images/内嵌图像控件的节点可拖拽调整大小examples/lock_nodes_and_connections/锁定节点移动与连接拖离examples/node_validation/NodeValidationState与NodeProcessingStatus错误/警告状态与处理指示器examples/custom_painter/自定义节点与连接绘制渐变与箭头examples/text/文本数据在节点间传递适合作为入门起点Calculator完整的端到端数据流应用examples/calculator/是功能最完整的示例展示了数据流应用的完整形态。其文件结构为NumberSourceDataModel数字源、NumberDisplayDataModel结果显示、AdditionModel、SubtractionModel、MultiplicationModel、DivisionModel四则运算与LongProcessingRandomNumber模拟长耗时处理外加MathOperationDataModel运算节点的公共基类与DecimalData数据载体。注册表与菜单集成参考 examples/calculator/main.cpp所有节点模型通过一个NodeDelegateModelRegistry按分类注册static std::shared_ptrNodeDelegateModelRegistry registerDataModels() { auto ret std::make_sharedNodeDelegateModelRegistry(); ret-registerModelNumberSourceDataModel(Sources); ret-registerModelNumberDisplayDataModel(Displays); ret-registerModelAdditionModel(Operators); // ... return ret; }注册时传入的字符串如Sources、Operators是菜单分类名注册后的模型会自动成为场景右键菜单的创建条目connection_colors示例的源码注释也印证了这一点。该示例还演示了把 QtNodes 场景嵌入传统 Qt Widgets 应用的做法用QMenuBarQVBoxLayout构建主窗口在 File 菜单挂接「Save Scene」与「Load Scene」动作并直接调用场景的保存/加载能力QObject::connect(saveAction, QAction::triggered, scene, [scene, mainWidget]() { if (scene-save()) mainWidget.setWindowModified(false); }); QObject::connect(loadAction, QAction::triggered, scene, DataFlowGraphicsScene::load); QObject::connect(scene, DataFlowGraphicsScene::sceneLoaded, view, GraphicsView::centerScene); QObject::connect(scene, DataFlowGraphicsScene::modified, mainWidget, [mainWidget]() { mainWidget.setWindowModified(true); });这里体现了 QtNodes 与 Qt 信号槽机制的深度集成sceneLoaded加载完成后自动居中视图、modified图被修改时同步窗口的未保存标记配合窗口标题中的[*]占位符。当scene-groupingEnabled()为真时还会追加「Load Group...」菜单项说明场景内置了分组文件的加载入口。数据流核心链路calculator采用 QtNodes 的数据流范式DataFlowGraphModel负责管理节点并自动路由数据DataFlowGraphicsScene负责可视化。配合 数据流指南 可知其核心链路是源节点通过emit dataUpdated(0)发出信号 →DataFlowGraphModel回调源节点的outData()取数据 → 再调用下游节点的setInData()推送数据 → 下游节点计算后再次emit dataUpdated(0)继续传播。运算节点在输入齐全时计算结果并通过emit dataUpdated(0)通知显示节点输入缺失时清空结果使输出失效——这套输入齐全才计算、缺失即失效的规则在 MathOperationDataModel.cpp 中均有对应实现。Simple Graph Model最小化自定义图模型examples/simple_graph_model/演示了 QtNodes 的另一种范式不借助数据流直接继承AbstractGraphModel自己管理全部图数据并用BasicGraphicsScene渲染。这是编写可视化、自定义图逻辑如状态机、Shader 编辑器的推荐起点。参考 examples/simple_graph_model/main.cpp最小启动代码仅需SimpleGraphModel graphModel; // 程序化建图两个节点 一条连接 NodeId id1 graphModel.addNode(); graphModel.setNodeData(id1, NodeRole::Position, QPointF(0, 0)); NodeId id2 graphModel.addNode(); graphModel.setNodeData(id2, NodeRole::Position, QPointF(300, 300)); graphModel.addConnection(ConnectionId{id1, 0, id2, 0}); auto scene new BasicGraphicsScene(graphModel); GraphicsView view(scene); view.show();addNode()、setNodeData()、addConnection()均是对模型层的直接操作视图会通过模型发出的信号自动同步。该示例还演示了如何通过QAction 右键菜单在鼠标位置创建新节点view.setContextMenuPolicy(Qt::ActionsContextMenu); QAction createNodeAction(QStringLiteral(Create Node), view); QObject::connect(createNodeAction, QAction::triggered, []() { QPointF posView view.mapToScene(view.mapFromGlobal(QCursor::pos())); NodeId const newId graphModel.addNode(); graphModel.setNodeData(newId, NodeRole::Position, posView); });关于自定义图模型需要实现的纯虚方法newNodeId、nodeData、connectionPossible、addNode、addConnection等与必须发出的信号nodeCreated、nodeDeleted、connectionCreated等可参见 图模型指南 中的完整清单与示例实现。一个关键警告是忘记发出信号会导致视图与模型失步。Styles 与 Connection Colors定制视觉外观两个示例分别从整体换肤和按数据类型着色两个角度演示了 样式指南 中的能力。Styles三种样式对象的 JSON 驱动换肤QtNodes 的样式体系由StyleCollection统一管理内部以 JSON 存储分为三层GraphicsViewStyle—— 画布背景与网格BackgroundColor、FineGridColor、CoarseGridColorNodeStyle—— 节点颜色、边框、字体NormalBoundaryColor、GradientColor0-3渐变、ShadowEnabled、ErrorColor、WarningColor等ConnectionStyle—— 连接线与颜色ConstructionColor、NormalColor、SelectedColor、HoveredColor、LineWidth、PointDiameter等styles示例通过ConnectionStyle::setConnectionStyle(...)全局应用样式字符串calculator的main.cpp中同样有一段完整的连接样式 JSONConstructionColor: gray、SelectedHaloColor: deepskyblue、LineWidth: 3.0、UseDataDefinedColors: true可作为真实可用的样式模板。样式也支持按节点覆盖NodeRole::Style与从外部 JSON 文件加载NodeStyle::setNodeStyle/ConnectionStyle::setConnectionStyle/GraphicsViewStyle::setGraphicsViewStyle。Connection Colors数据类型驱动连接配色connection_colors示例把样式系统的「数据定义颜色」特性单独抽出来演示。实现要点是在全局样式中开启UseDataDefinedColors: true随后在自定义数据类型NodeDataType上为每种类型指定专属颜色连接线即自动按所传输的数据类型着色——每种数据类型一条专属色视觉上可以一眼区分不同数据在流图中的走向。该示例的 main.cpp 展示了注册单个模型并开启该样式的完整过程数据定义色的具体写法可参考 样式指南 中NodeDataType携带QColor参数的示例。Vertical Layout自上而下的垂直布局vertical_layout示例演示了 QtNodes 的垂直布局能力适合瀑布式、自上而下的图结构。其原理在 可视化指南 中说明QtNodes 内置两种节点几何实现——默认的DefaultHorizontalNodeGeometry端口在左右两侧与DefaultVerticalNodeGeometry端口在上下边缘垂直布局只需scene.setOrientation(Qt::Vertical);启用后节点端口位于顶部和底部连接线沿垂直方向流动。该示例同样基于SimpleGraphModel自建模型可作为自定义模型 垂直布局组合的参考模板。Dynamic Ports两阶段端口修改 APIdynamic_ports示例解决节点端口数量可变的需求如「N 个数相加」「数组合并」这类可变输入节点。配套的PortAddRemoveWidget为节点提供「添加端口 / 删除端口」的交互控件。官方文档 高级主题指南 强调修改端口必须使用两阶段 API否则会破坏连接状态修改前调用portsAboutToBeInserted(...)或portsAboutToBeDeleted(...)让库缓存/移除受影响的连接修改内部数据如端口计数调用portsInserted()或portsDeleted()完成操作库自动恢复被移动位置的连接。在NodeDelegateModel中对应的是发出信号void MyDelegate::addPort() { emit portsAboutToBeInserted(PortType::In, newIndex, newIndex); _inputCount; emit portsInserted(); }这是一条值得写进代码注释的警告绕过portsAboutTo.../ports...调用直接改端口会导致连接状态损坏。Resizable Images可拖拽缩放的嵌入式图像节点resizable_images示例演示节点内嵌图像控件ImageLoaderModel负责加载图像、ImageShowModel负责展示数据载体为PixmapData且节点尺寸可由用户拖拽调整。可调整尺寸的能力来自 高级主题指南 中的NodeFlag::Resizable标志图模型在nodeFlags()中返回该标志即允许用户缩放节点模型侧还需在setNodeData()中处理NodeRole::Size保存新尺寸并发出nodeUpdated(nodeId)通知场景重绘。这为「嵌入式 Widget 内容随节点尺寸变化」的应用如图像预览、富文本编辑提供了标准做法。Lock Nodes Connections锁定节点与连接lock_nodes_and_connections示例演示如何禁止节点被移动、以及禁止连接被拖离。核心是 高级主题指南 中的两组 API锁定节点图模型在nodeFlags()中为特定节点附加NodeFlag::Locked运行时锁定则修改内部集合后emit nodeFlagsUpdated(nodeId)通知场景刷新void MyModel::lockNode(NodeId nodeId) { _lockedNodes.insert(nodeId); emit nodeFlagsUpdated(nodeId); // Tell scene to update }禁止连接脱离重写detachPossible(ConnectionId)返回false即禁止用户把该连接从节点上拖走例如保护输出类节点不被误操作bool MyModel::detachPossible(ConnectionId conn) const override { if (isOutputNode(conn.outNodeId)) { return false; } return true; }该示例将两类锁定逻辑封装在DataFlowModel与DelegateNodeModel中可作为「只读展示 / 演示模式 / 受保护节点」场景的实现参考。Node Validation校验状态与处理状态指示器node_validation示例ValidatedModel、TextData、TextSourceModel、TextDisplayModel演示了 QtNodes 的两类状态指示机制详见 数据流指南NodeValidationState配置校验在setInData()中根据输入设置节点的校验状态状态会以节点角落的彩色图标呈现_stateMessage则作为悬停提示tooltip显示Valid无图标—— 配置正确Warning橙色图标—— 存在隐患但可能仍可处理Error红色图标—— 配置无效无法处理if (!data) { NodeValidationState state; state._state NodeValidationState::State::Warning; state._stateMessage Missing input data; // 悬停时显示 setValidationState(state); return; }NodeProcessingStatus处理状态表示计算生命周期取值包括NoStatus默认、Processing计算中转圈图标、Updated成功完成、Pending等待输入、Empty无数据、Failed失败、Partial部分完成。典型用法是在异步计算前后切换状态setNodeProcessingStatus(NodeProcessingStatus::Processing); // 异步计算完成后 setNodeProcessingStatus(NodeProcessingStatus::Updated); emit dataUpdated(0);Custom Painter替换默认渲染管线custom_painter示例CustomNodePainter、CustomConnectionPainter、SimpleGraphModel演示如何完全替换节点的默认外观绘制渐变背景与箭头连接。其原理在 可视化指南 中给出自定义节点绘制继承AbstractNodePainter重写paint(QPainter*, NodeGraphicsObject)通过nodeScene()-nodeGeometry()与graphModel()获取几何与模型数据自行绘制圆角矩形、标题等然后通过scene.setNodePainter(std::make_uniqueMyNodePainter())注入场景。自定义连接绘制继承AbstractConnectionPainter重写paint()用endPoint(PortType::Out)/endPoint(PortType::In)获取两端坐标绘制直线与箭头和getPainterStroke()返回命中测试用的加粗路径。自定义节点几何继承AbstractNodeGeometry重写boundingRect()、portPosition()、captionPosition()、widgetPosition()等布局方法控制节点排版。QtNodes 还有对应的自动化测试覆盖该能力例如 TestCustomPainters.cpp验证自定义绘制器在场景中的集成行为可作为参考。Text最简单的数据流入门text示例TextData、TextSourceDataModel、TextDisplayDataModel演示字符串数据在节点间的传递官方文档明确称其为Good starting point最佳入门起点。相比calculator它只包含文本源 → 文本显示的最简链路非常适合第一次阅读数据流代码时使用一个NodeDelegateModel子类实现caption()、nPorts()、dataType()、setInData()、outData()、embeddedWidget()这几个必需方法即可跑通数据载体TextData继承QtNodes::NodeData并通过type()返回唯一类型标识。Headless 无界面模式不依赖 GUI 运行图计算官方文档专门用一节介绍Headless 无界面模式examples/calculator/headless_main.cpp演示了完全脱离 GUI 运行图计算的方式。这在自动化测试、批处理、服务端计算等场景中非常实用。参考 headless_main.cpp 的完整流程// 1. 创建注册表并构造模型不挂任何场景/视图 std::shared_ptrNodeDelegateModelRegistry registry registerDataModels(); DataFlowGraphModel dataFlowGraphModel(registry); // 2. 从 JSON 加载已保存的图此处是内嵌的 adding numbers 场景 QJsonDocument sceneJson QJsonDocument::fromJson(addingNumbersScene.toUtf8()); dataFlowGraphModel.load(sceneJson.object()); // 3. 通过 NodeId 取回委托模型编程式修改输入 NodeId const nodeSource 0; dataFlowGraphModel.delegateModelNumberSourceDataModel(nodeSource)-setNumber(33.3); // 4. 读取下游计算结果数据流已自动传播 NodeId const nodeResult 2; qInfo() Result: dataFlowGraphModel.delegateModelNumberDisplayDataModel(nodeResult)-number();文档中的代码块使用model.load(loadJsonFromFile(saved_graph.json))说明可以从文件加载headless 示例实际用的是内嵌 JSON 字符串 QJsonDocument::fromJson。delegateModelT()是数据流模型的关键 API它把NodeId映射回对应的NodeDelegateModel实例从而允许以类型安全的方式调用节点专属方法如setNumber。此外文档还提示另一种建图方式用DataFlowGraphModel::addNode与addConnection自行构建图再用返回的NodeId获取委托模型——无需任何场景文件。图 JSON 格式参考headless 示例内嵌的addingNumbersScene展示了 QtNodes 图的 JSON 结构包含nodes含id、internal-data、position与connections含inPortIndex、intNodeId、outNodeId、outPortIndex两大数组。这个 JSON 正是由 GUI 版calculator示例的scene-save()保存而来与 序列化指南 描述的文件格式一致可作为手写测试图或离线生成场景文件的模板。运行示例官方文档给出的运行方式是构建完成后从构建目录执行对应二进制。假设 CMake 输出在build/# From build directory ./bin/calculator ./bin/simple_graph_model ./bin/styles # ... etc每个示例都是独立可执行程序分别演示特定功能。不同示例的启动体验可参考官方文档描述calculator启动后即可通过 File 菜单保存/加载场景simple_graph_model启动时预置了两个相连的节点并支持右键创建新节点connection_colors、styles启动即呈现定制配色dynamic_ports通过节点上的按钮增删端口resizable_images可拖拽调整节点大小lock_nodes_and_connections展示锁定效果node_validation展示校验与处理状态图标custom_painter展示渐变节点与箭头连接。如何选择合适的示例作为项目起点结合官方文档对每个示例的定位可以给出如下选型建议首次接触 QtNodes从text开始理解数据流最小闭环再进阶到calculator掌握注册表、菜单集成、保存/加载与内嵌控件做可视化/自定义图逻辑无数据传播需求以simple_graph_model为模板配合 图模型指南 补全纯虚方法与信号做视觉编程/计算管线以calculator为骨架结合node_validation状态指示与connection_colors类型着色增强交互体验需要服务端/测试侧计算直接复用calculator/headless_main.cpp的无界面模式配合DataFlowGraphModel::addNode/addConnection编程式建图追求界面定制styles全局换肤、custom_painter替换渲染管线、vertical_layout垂直流向、dynamic_ports可变端口分别对应不同定制维度。仓库的测试目录如 TestDataFlow.cpp、TestNodeValidation.cpp、TestCustomPainters.cpp为上述核心能力提供了可编译、可回归的验证参考。官方文档中每个示例也对应了深入讲解章节数据流见 数据流指南自定义模型见 图模型指南换肤见 样式指南渲染与布局见 可视化指南动态端口、锁定等高级能力见 高级主题指南。赞分享UI组件数据可视化【免费下载链接】nodeeditorQt Node Editor. Dataflow programming framework项目地址https://gitcode.com/gh_mirrors/no/nodeeditor点击查看免费下载相关推荐react-sketchapp 官方示例全解析从 Basic Setup 到 GraphQL、跨端渲染与 TypeScript 实战react sketchapp 官方示例全解析从 Basic Setup 到 GraphQL、跨端渲染与 TypeScript 实战 react sketch开发工具前端egui 与 eframe 官方示例仓库指南从 Hello World 到自定义渲染的完整实践路线egui 与 eframe 官方示例仓库指南从 Hello World 到自定义渲染的完整实践路线 本指南围绕 egui 仓库中的 examples httpUI组件前端桌面应用Astro 集成 Preact 实战从官方示例到 astrojs/preact 渲染器源码解析Astro 集成 Preact 实战从官方示例到 astrojs/preact 渲染器源码解析 本文以 Astro 仓库中的官方示例 examples/fr前端Web框架SSR前端构建上一篇如何用DyberPet打造你的专属AI桌面伙伴5步实现个性化虚拟助手下一篇ComfyUI-BrushNet终极指南专业图像修复与内容生成完整解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表