该项目没有收到实质性更新,我将来的时间有限。在最新版本中,该项目非常准确地实现了我想要的目标:一个简单灵活的编辑器和框架,用于探索 Python 中基于流的可视化脚本的用例。如果您有疑问或进一步的想法,请随时提出问题或分叉该项目并亲自尝试。
Ryven 是一个用 Python 编写的实验性节点编辑器。它为 Python 中基于流程的可视化脚本实现了基于 Qt 的可视化界面。它提供了一个用于开发执行任何 Python 代码的节点的强大系统,以及一个用于使用这些节点构建图形的编辑器。 Ryven 具有一系列配置选项和无头模式,无需任何 GUI 即可运行图形。一些相关的 GitHub 存储库:
ryvencore-qt
库为 ryvencore 添加了基于 Qt 的 GUI 类 ( ./ryvencore-qt/
),并且 Ryven 编辑器将它们组装成功能齐全的跨平台应用程序 ( ./ryven-editor/
)。
一旦安装了 Python 和 pip,Ryven 就可以通过 PyPI 使用
pip install ryven
还有一个 conda-forge 软件包( conda install -c conda-forge ryven
)。
可以通过键入ryven
从命令行启动 Ryven。如果您将 Ryven 安装到 Python 虚拟环境(或 conda 环境)中,则需要先激活该环境。
Ryven 本身仅附带一些小示例节点。您应该使用 Ryven 来开发节点,或者针对您的用例使用第三方节点包(如果有)。示例节点实际上只是示例,并且在任何方面都不稳定,因此您不应依赖它们。
安装后,ryven 将在您的用户主目录中创建一个目录~/.ryven/
其结构如下:
~/.ryven
├── nodes
│ ├── your_nodes_pkg_1
│ ├── nodes.py
│ └── gui.py
│ └── ...
├── saves
│ ├── your_project_1.json
│ └── ...
└── ryven.cfg
ryven.cfg
文件包含 Ryven 的全局配置。
Ryven 可以通过四种方式进行配置:
ryven --nodes your_nodes_pkg_1 --no-animations
~/.ryven/ryven.cfg
: nodes = your_nodes_pkg_1 no_animations = True
import ryven ryven . run_ryven ( nodes = [ 'your_nodes_pkg_1' ], no_animations = True )
键入ryven --help
以获取可用选项列表。
要部署无头(无任何 GUI)的 Ryven 项目,请使用ryven-console
命令。
> ryven-console /home/leon/.ryven/saves/basics.json
Welcome to the Ryven Console ! Your project has been loaded.
You can access the ryvencore session by typing ` session ` .
For more information, visit https://leon-thomm.github.io/ryvencore/
>>> f = session.flows[0]
>>> ctr_var_result_node = f.nodes[2]
>>> ctr_set_var_node = f.nodes[8]
>>> ctr_var_result_node.val
3738
>>> ctr_set_var_node.update(0)
>>> ctr_var_result_node.val
3739
ryven
打开 RyvenFile -> Import Example Nodes
并选择<installation_dir>/example_nodes/std/nodes.py
val
节点拖入场景中+
节点将它们连接在一起result
节点中ctrl + scroll
进行缩放Ryven 节点包只是一个典型的 Python 包,其中至少包含一个nodes.py
文件,并调用 Ryven 节点 API 来公开节点定义。
导航到~/.ryven/nodes/
并创建以下结构的子目录
~/.ryven/nodes
└── your_nodes_pkg_1
├── __init__.py
├── nodes.py
└── gui.py
包含以下内容:
nodes.py
:
from ryven . node_env import *
# your node definitions go here
export_nodes ([
# list your node classes here
])
@ on_gui_load
def load_gui ():
# import gui sources here only
from . import gui
和gui.py
:
from ryven . gui_env import *
from . import nodes
# your node gui definitions go here
您现在可以开始定义自己的节点。让我们定义两个基本节点。一种生成随机数的...
from random import random
class RandNode ( Node ):
"""Generates scaled random float values"""
title = 'Rand'
tags = [ 'random' , 'numbers' ]
init_inputs = [ NodeInputType ()]
init_outputs = [ NodeOutputType ()]
def update_event ( self , inp = - 1 ):
self . set_output_val ( 0 ,
Data ( random () * self . input ( 0 ). payload )
)
...还有另一个打印它们的
class PrintNode ( Node ):
title = 'Print'
init_inputs = [ NodeInputType ()]
def update_event ( self , inp = - 1 ):
print ( self . input ( 0 ))
并将它们暴露给 Ryven
export_nodes ([
RandNode ,
PrintNode ,
])
就是这样!您可以在 Ryven 中导入节点包( File -> Import Nodes
),将节点放置在图中,并将它们连接起来。添加一个val
节点并将其连接到Rand
节点,以向其输入提供数据。如果您在val
节点的小部件中输入一个数字并按 Enter 键,它将将该数字发送到Rand
节点,该节点将发送一个缩放后的随机数到Print
节点,后者会将其打印到标准输出。
请注意,默认情况下,标准输出是编辑器内控制台,您可以在编辑器窗口的最底部访问它(向上拖动蓝色手柄以使其可见)。
您现在可以使用一些 GUI 来为您的节点增添趣味。 Ryven 在 Qt 上运行,使用 PySide2 或 PySide6(通过 qtpy 库)。您可以在单独的文件中配置节点的 GUI,并向节点添加自定义 Qt 小部件。确保始终将节点逻辑与 GUI 组件明确分开。 Ryven 的核心功能之一是在没有任何 GUI 依赖的情况下(在 ryvencore 上)无头运行项目。为了使其工作,您的nodes.py
文件不应该直接依赖于Qt。相反,您可以将自定义 GUI 从 GUI 文件附加到节点,如下所示。
让我们给它们一些颜色,并在gui.py
中向Rand
节点添加一个滑块:
from qtpy . QtWidgets import QSlider
from qtpy . QtCore import Qt
from ryven . gui_env import *
from . import nodes
class RandSliderWidget ( NodeInputWidget , QSlider ):
"""a standard Qt slider widget, which updates the node
input it is attached to, every time the slider value changes"""
def __init__ ( self , params ):
NodeInputWidget . __init__ ( self , params )
QSlider . __init__ ( self )
self . setOrientation ( Qt . Horizontal )
self . setMinimumWidth ( 100 )
self . setMinimum ( 0 )
self . setMaximum ( 100 )
self . setValue ( 50 )
self . valueChanged . connect ( self . value_changed )
def value_changed ( self , val ):
# updates the node input this widget is attached to
self . update_node_input ( Data ( val ))
def get_state ( self ) -> dict :
# return the state of the widget
return { 'value' : self . value ()}
def set_state ( self , state : dict ):
# set the state of the widget
self . setValue ( state [ 'value' ])
@ node_gui ( nodes . RandNode )
class RandNodeGui ( NodeGUI ):
color = '#fcba03'
# register the input widget class
input_widget_classes = { 'slider' : RandSliderWidget }
# attach the slider widget to the first node input
# display it _below_ the input pin
init_input_widgets = {
0 : { 'name' : 'slider' , 'pos' : 'below' }
}
就是这样! Ryven 现在将RandNodeGui
注册为RandNode
类的“GUI 类”,它充当所有 UI 事物的容器。您可以将自定义主要(“主”)小部件添加到节点、输入小部件,并进一步自定义节点的外观。
当调用input()
(例如RandNode
中的self.input(0)
)时,输入小部件(例如上面的self.update_node_input(val)
)提供的值将在节点中返回,但仅当相应的输入不是时已连接。否则,将返回连接输出的值。
请在此存储库的 GitHub wiki 页面上查找更多资源。
除非您另有明确说明,否则您有意提交的包含在作品中的任何贡献均应按上述方式获得许可,无任何附加条款或条件。
高度赞赏您的贡献。如果没有开源社区,这个项目就不存在。我要特别感谢CREDITS.md
文件中列出的人员。