Created
May 7, 2024 19:42
-
-
Save niuniulla/85cbd84eb58e3bd44996d658f8617357 to your computer and use it in GitHub Desktop.
A minimal example to show the usage of dearpygui to construct an nodes app.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
""" | |
This is a minimal example to show the usage of dearpygui | |
to construct an app of nodes manipulations. | |
The basic functions includ: | |
* drag a button to create a node | |
* change node theme | |
* show some message based on the selected node | |
* connect and disconnect nodes | |
""" | |
import dearpygui.dearpygui as dpg | |
dpg.create_context() | |
dpg.configure_app(docking=True) | |
# some global variables | |
layer_data = {} # list of available layers | |
connection_data = [] # list of connections from layer to layer | |
LinkList = [] | |
current_layer = [] | |
selected_nodes = set() | |
nodes = [] | |
def show_layer_info(sender): | |
for selected_node in dpg.get_selected_nodes("NodeEditor"): | |
item_name = "Layer Attributes_" + str(selected_node) | |
if (selected_node not in nodes): | |
dpg.hide_item(item_name) | |
else: | |
dpg.show_item(item_name) | |
# Delete selected node | |
def callback_delete_item(sender): | |
for selected_node in dpg.get_selected_nodes("NodeEditor"): | |
# Deleting node and attached links | |
## Extract all children of the deleted node | |
selected_node_children = dpg.get_item_children(selected_node)[1] | |
## Extract all existing links in the Node Editor | |
nodeEditor_links = dpg.get_item_children("NodeEditor")[0] | |
## Iterate through NodeEditor elements and delete attached links | |
for link in nodeEditor_links: | |
if dpg.get_item_configuration(link)["attr_1"] in selected_node_children or dpg.get_item_configuration(link)["attr_2"] in selected_node_children: | |
dpg.delete_item(link) | |
## Iterate trough LinkList and remove attached links | |
for item in LinkList: | |
for sub_item in item: | |
if dpg.get_item_alias(selected_node) in sub_item: | |
LinkList.remove(item) | |
# Deleting node | |
dpg.delete_item(selected_node) | |
del model_data[selected_node] | |
# callback runs when user attempts to connect attributes | |
def link_callback(sender, app_data): | |
# app_data -> (link_id1, link_id2) | |
data = () | |
if type(app_data) == tuple: | |
dpg.add_node_link(app_data[0], app_data[1], parent=sender) | |
data = (dpg.get_item_alias(app_data[0]), dpg.get_item_alias(app_data[1])) | |
LinkList.append(data) | |
# callback runs when user attempts to disconnect attributes | |
def delink_callback(sender, app_data): | |
# app_data -> link_id | |
dpg.delete_item(app_data) | |
def input_callback(sender, app_data): | |
# get parent node | |
parent = dpg.get_item_parent(sender) | |
parent = dpg.get_item_parent(parent) | |
label = dpg.get_item_label(sender) | |
print("input callback: ", app_data, "parent: ", parent, "label: ", label) | |
model_data[parent]["parameters"][0]["value"] = dpg.get_value(sender) | |
print(model_data) | |
def on_drop(sender, app_data, user_data): | |
pos = dpg.get_mouse_pos(local=False) | |
layer_info = app_data | |
node_id = dpg.generate_uuid() | |
nodes.append(node_id) | |
with dpg.node(label="node_"+str(node_id), tag=node_id, parent="NodeEditor", pos=pos): | |
with dpg.node_attribute(): | |
dpg.add_input_int(label="input", callback=input_callback, width=100) | |
with dpg.node_attribute(attribute_type=dpg.mvNode_Attr_Output): | |
dpg.add_input_int(label="output", callback=input_callback, width=100) | |
# create group for display on window "layer_info" | |
group_lable = "Layer Attributes_" + str(node_id) | |
with dpg.group(label=group_lable, tag=group_lable, parent="window_info", show=False): | |
dpg.add_text("some info") | |
dpg.add_text("some more info") | |
# get selected nodes when dragging mouse | |
def on_drag(sender, app_data): | |
selected_nodes.clear() | |
for selected_node in dpg.get_selected_nodes("NodeEditor"): | |
selected_nodes.add(selected_node) | |
# | |
def get_selected_nodes_callback(sender, app_data): | |
if len(selected_nodes) == 0: | |
selected_nodes.clear() | |
return | |
print("selected nodes: ", selected_nodes) | |
with dpg.theme() as item_theme: | |
with dpg.theme_component(dpg.mvNode): | |
link_theme_color = dpg.add_theme_color(dpg.mvNodeCol_TitleBar, (0, 255, 0), category=dpg.mvThemeCat_Nodes) | |
# create window context | |
with dpg.window(label="Tutorial", width=1200, height=800): | |
# create node editor | |
with dpg.group(tag="nodes", drop_callback=on_drop, user_data="test"): | |
with dpg.node_editor(tag="NodeEditor", callback=link_callback, delink_callback=delink_callback): | |
with dpg.node(label="Input") as node_test: | |
with dpg.node_attribute(label="Node A1", attribute_type=dpg.mvNode_Attr_Static): | |
#dpg.add_input_float(label="F1", width=150) | |
pass | |
with dpg.node_attribute(label="Node A2", attribute_type=dpg.mvNode_Attr_Output): | |
dpg.add_input_int(label="F1", width=100) | |
dpg.add_input_int(label="F2", width=100) | |
dpg.bind_item_theme(node_test, item_theme) | |
# create button window | |
with dpg.window(label="buttons", pos=(200, 100)): | |
def add_button(name): | |
dpg.add_button(label=name, tag=name) | |
with dpg.drag_payload(parent=name): | |
dpg.add_text(name) | |
with dpg.group(tag="buttons"): | |
for i in range(5): | |
add_button(f"button{i}") | |
dpg.add_separator() | |
# window to show layer properties | |
with dpg.window(label="Info Window", tag="window_info", pos=(400, 100)): | |
dpg.add_text("Information", show=True) | |
dpg.add_separator(show=True) | |
# create menubar | |
with dpg.viewport_menu_bar(): | |
with dpg.menu(label="File"): | |
dpg.add_menu_item(label="save") | |
# input handlers | |
with dpg.handler_registry(): | |
dpg.add_key_release_handler(key=dpg.mvKey_Delete, callback=callback_delete_item) | |
dpg.add_mouse_click_handler(callback=show_layer_info) | |
dpg.add_mouse_drag_handler(callback=on_drag) | |
dpg.add_mouse_release_handler(callback=get_selected_nodes_callback) | |
dpg.create_viewport(title='Custom Title', width=1200, height=800) | |
dpg.setup_dearpygui() | |
dpg.show_viewport() | |
dpg.start_dearpygui() | |
dpg.destroy_context() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment