Этот проект не получает существенных обновлений, и в будущем у меня будет ограничено время для него. В последнем выпуске проект стал именно тем, чем я хотел его видеть: простым и гибким редактором и платформой для изучения вариантов использования визуальных сценариев на основе потоков в Python. Если у вас есть вопросы или идеи, смело открывайте проблемы или разделяйте проект и пробуйте его сами.
Ryven — экспериментальный редактор узлов, написанный на Python. Он реализует визуальный интерфейс на основе Qt для потокового визуального написания сценариев на Python. Он предоставляет мощную систему для разработки узлов, выполняющих любой код Python, а также редактор для построения графов с использованием этих узлов. Ryven имеет множество параметров конфигурации и автономный режим для запуска графиков без графического интерфейса. Некоторые соответствующие репозитории GitHub:
Библиотека ryvencore-qt
добавляет классы графического интерфейса на основе Qt для ryvencore ( ./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
для получения списка доступных опций.
Чтобы развернуть проект 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
из командной строкиFile -> Import Example Nodes
и выберите <installation_dir>/example_nodes/std/nodes.py
val
на сцену+
result
ctrl + scroll
Пакет узлов Ryven — это просто типичный пакет Python, который содержит как минимум файл nodes.py
и вызывает API узлов Ryven для предоставления определений узлов.
Перейдите в ~/.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 ))
и показать их Ривену
export_nodes ([
RandNode ,
PrintNode ,
])
Вот и все! Вы можете импортировать свой пакет узлов в Ryven ( File -> Import Nodes
), поместить узлы в граф и соединить их. Добавьте узел val
и подключите его к узлу Rand
, чтобы передать на его вход данные. Если вы введете число в виджет узла val
и нажмете Enter, оно отправит число в узел Rand
, который отправит масштабированное случайное число в узел Print
, который выведет его на стандартный вывод.
Обратите внимание, что стандартным выводом по умолчанию является консоль редактора, доступ к которой можно получить в самом низу окна редактора (перетащите синий маркер вверх, чтобы сделать его видимым).
Теперь вы можете оживить свои узлы с помощью графического интерфейса. Ryven работает на Qt, используя PySide2 или PySide6 (через библиотеку qtpy). Вы можете настроить графический интерфейс своих узлов в отдельном файле и добавить к своим узлам собственные виджеты Qt. Обязательно всегда четко отделяйте логику узла от компонентов графического интерфейса. Одной из центральных особенностей Ryven является возможность запуска проектов в автономном режиме (на ryvencore) без каких-либо зависимостей графического интерфейса. Чтобы это работало, ваши файлы nodes.py
никогда не должны напрямую зависеть от Qt. Вместо этого вы можете прикрепить пользовательский графический интерфейс к своим узлам из файлов графического интерфейса, как показано ниже.
Давайте придадим им немного цвета и добавим ползунок к узлу Rand
в gui.py
:
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
как «класс GUI» класса RandNode
, который служит контейнером для всех элементов пользовательского интерфейса. Вы можете добавлять собственные первичные («основные») виджеты к своим узлам, входным виджетам и дополнительно настраивать внешний вид узлов.
Значение, предоставленное виджетом ввода (например, self.update_node_input(val)
выше), будет возвращено в узле при вызове input()
(например, self.input(0)
в RandNode
), но только тогда, когда соответствующий ввод не подключен . В противном случае будет возвращено значение подключенного выхода.
Дополнительные ресурсы можно найти на вики-странице GitHub в этом репозитории.
Если вы явно не указали иное, любой вклад, намеренно представленный вами для включения в работу, должен лицензироваться, как указано выше, без каких-либо дополнительных положений и условий.
Вклад высоко ценится. Этот проект не существует без сообщества открытого исходного кода. Я хочу особенно поблагодарить людей, перечисленных в файле CREDITS.md
.