简介

qtpynodeeditor 是一个用于在 Python 中创建可视化节点编辑器的第三方库。它基于 Qt 的 PyQt 或 PySide 绑定构建,提供了完整的框架来创建类似可视化编程工具(如 Blender 的节点编辑器或虚幻引擎的蓝图)的应用程序。

为了帮你快速了解,我将它的核心特性总结如下表:

特性 说明
核心架构 采用模型-视图分离的设计模式,将数据逻辑与图形界面解耦,便于维护和扩展。
核心组件 包含节点端口连接线。节点是实现具体功能的单元,端口是输入输出接口,连接线定义数据流。
核心功能 支持节点的增删、移动、连接编辑;内置撤销/重做栈;支持将整个节点图序列化保存到文件或从文件加载。
样式系统 支持通过 JSON 灵活定义节点、连接线和画布的背景样式,可以实现动态主题切换。
数据流 支持在节点之间定义类型安全的数据传递。库会处理连接的创建、断开以及数据更新的传播逻辑。

🛠️ 主要应用场景

这个库非常适合开发需要可视化编排流程的应用,常见的用途包括:

  • 数据处理与科学计算:构建可视化数据分析管道。
  • 图形与渲染管线:编辑材质、特效或复合渲染流程。
  • 游戏开发:创建角色的行为树、对话树或游戏逻辑。
  • 自动化与脚本编排:通过拖拽方式组合复杂的自动化任务。

💡 选择与替代方案

除了 qtpynodeeditor,Python 生态中还有其他一些节点编辑器库,各有侧重:

  • NodeGraphQt:功能丰富,界面现代,在数字内容创作(DCC)工具领域较流行。
  • Ryven:专注于易用性和数据流可视化,适合快速原型设计。
  • python-node-editor:一个更基础、纯粹的示例项目,适合学习和深度定制。

总的来说,qtpynodeeditor 是一个功能全面、基于成熟 Qt 框架的节点编辑器解决方案,尤其适合需要深度集成到 Qt 应用程序或对界面有较高定制需求的开发者。

如果你对具体的安装步骤、创建一个最简单的“Hello World”节点编辑器示例,或者如何自定义一个节点类型感兴趣,我可以为你提供更详细的介绍。

安装

pip install qtpynodeeditor

文档

https://klauer.github.io/qtpynodeeditor/getting_started.html
https://github.com/klauer/qtpynodeeditor?tab=readme-ov-file

示例【示例代码见github官方仓库】

Connection colors连线的颜色

在这里插入图片描述

图片

在这里插入图片描述

自定义样式

在这里插入图片描述

好像是一个计算器

在这里插入图片描述

基本概念

qtpynodeeditor 的基本概念 = “一张图 + 三种对象 + 两条规则”
(全部名称对应源码类名,一次记全):

  1. scene -》 view -》 Node、Port、Connection

  1. 一张图:FlowScene
  • 就是整个画布(节点 + 连线 + 序列化)
  • 负责:增删节点、保存 JSON、端口兼容性检查

  1. 三种核心对象
对象 对应类 作用
节点 Node 画布上的矩形,可拖、可删、可嵌 QWidget
端口 Port 节点两侧的小圆点,分 input/output
连线 Connection 贝塞尔曲线,连接两个 Port

  1. 两条规则
  • 同类型才能连Port.data_type 字符串必须相等
  • 方向要对:output → input

  1. 你自己的代码只接触两个类
你要写的类 作用
NodeDataModel 定义节点:端口数、数据类型、算法、外观
DataModelRegistry 注册表:把自定义模型交给场景

  1. 一句话记住

“场景管图,模型管节点,端口管连线,同类型才能连。”

简单案例

import sys
from qtpy import QtWidgets, QtCore
import qtpynodeeditor as ne

# 1. 创建一个最简单的节点模型
class SimpleNode(ne.NodeDataModel):
    name = "SimpleNode"  # 节点名称
    caption = "简单节点"  # 节点显示标题
    
    # 端口设置:1个输入,1个输出
    num_ports = {
        ne.PortType.input: 0,
        ne.PortType.output: 1
    }
    
    # 输出的数据类型
    data_type = ne.NodeDataType("simple1", "输出")
    
    # 输出数据
    def out_data(self, port):
        return ne.NodeData()
    
    # 输入数据(什么都不做)
    def set_in_data(self, node_data, port):
        pass
    
    # 节点内部部件(空的)
    def embedded_widget(self):
        return None

# 2. 创建第二个节点
class OutputNode(ne.NodeDataModel):
    name = "OutputNode"
    caption = "输出节点"
    
    num_ports = {ne.PortType.input: 1, ne.PortType.output: 0}
    # 端口的id和名称,只有id一样的才可以连接
    data_type = ne.NodeDataType("simple1", "输入")
    
    def out_data(self, port):
        return None
    
    def set_in_data(self, node_data, port):
        print("收到了数据!", node_data, port)
        QtWidgets.QMessageBox.information(
                None,  # 父窗口(None表示没有父窗口)
                "提示",  # 标题
                "操作成功完成!"  # 消息内容
            )

    
    def embedded_widget(self):
        return None

# 3. 主程序
def main():
    app = QtWidgets.QApplication(sys.argv)

    # 注册节点
    registry = ne.DataModelRegistry()
    registry.register_model(SimpleNode, category="示例1")
    registry.register_model(OutputNode, category="示例")

    # 创建场景和视图(画布)
    scene = ne.FlowScene(registry=registry)
    view = ne.FlowView(scene)          # 这就是我们要塞进 layout 的 QWidget

    # 3. 纯 PyQt 窗口 + layout
    window = QtWidgets.QWidget()
    window.setWindowTitle("节点编辑器嵌入 layout")
    layout = QtWidgets.QVBoxLayout(window)
    layout.addWidget(QtWidgets.QLabel("节点编辑器"), 0, QtCore.Qt.AlignCenter)
    layout.addWidget(view)             # ← 一行嵌入
    layout.addWidget(QtWidgets.QPushButton("节点编辑器"), 0, QtCore.Qt.AlignCenter)

    # 4. 预置两个节点
    node1 = scene.create_node(SimpleNode)
    node2 = scene.create_node(OutputNode)
    node1.graphics_object.setPos(QtCore.QPointF(0, 150))
    node2.graphics_object.setPos(QtCore.QPointF(300, 150))
    
    # scene.create_connection(node1[ne.PortType.output][0],node2[ne.PortType.input][0], )

    window.resize(800, 600)
    window.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()


在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐