Node Overview

Creating Nodes

Creating a node is done by calling the NodeGraphQt.NodeGraph.create_node() function.
(see example below line: 23)
 1from Qt import QtWidgets
 2from NodeGraphQt import BaseNode, NodeGraph
 3
 4class MyNode(BaseNode):
 5
 6    __identifier__ = 'io.github.jchanvfx'
 7    NODE_NAME = 'my node'
 8
 9    def __init__(self):
10        super(MyNode, self).__init__()
11        self.add_input('foo')
12        self.add_input('hello')
13        self.add_output('bar')
14        self.add_output('world')
15
16if __name__ == '__main__':
17    app = QtWidgets.QApplication([])
18
19    node_graph = NodeGraph()
20    node_graph.register_node(MyNode)
21    node_graph.widget.show()
22
23    # here we create a couple nodes in the node graph.
24    node_a = node_graph.create_node('io.github.jchanvfx.MyNode', name='node a')
25    node_b = node_graph.create_node('io.github.jchanvfx.MyNode', name='node b', pos=[300, 100])
26
27    app.exec_()

Creating Node Widgets

The NodeGraphQt.BaseNode class allows you to embed some basic widgets inside a node here’s a example to simply embed a QComboBox widget when reimplementing the BaseNode.

 1from NodeGraphQt import BaseNode
 2
 3class MyListNode(BaseNode):
 4
 5    __identifier__ = 'io.github.jchanvfx'
 6    NODE_NAME = 'node'
 7
 8    def __init__(self):
 9        super(MyListNode, self).__init__()
10
11        items = ['apples', 'bananas', 'pears', 'mangos', 'oranges']
12        self.add_combo_menu('my_list', 'My List', items)

To you update the widget you can call the NodeGraphQt.NodeObject.set_property() function.

1node = MyListNode()
2node.set_property('my_list', 'mangos')

functions for embedding widgets into a base node:

See: Embedded Node Widgets for more node widget types.


Embedding Custom Widgets

Here’s an example to embed a custom widget where we subclass the NodeGraphQt.NodeBaseWidget and then add to the node with the NodeGraphQt.BaseNode.add_custom_widget() function.

 1from Qt import QtCore, QtWidgets
 2from NodeGraphQt import BaseNode, NodeBaseWidget
 3
 4class MyCustomWidget(QtWidgets.QWidget):
 5    """
 6    Custom widget to be embedded inside a node.
 7    """
 8
 9    def __init__(self, parent=None):
10        super(MyCustomWidget, self).__init__(parent)
11        self.combo_1 = QtWidgets.QComboBox()
12        self.combo_1.addItems(['a', 'b', 'c'])
13        self.combo_2 = QtWidgets.QComboBox()
14        self.combo_2.addItems(['a', 'b', 'c'])
15        self.btn_go = QtWidgets.QPushButton('Go')
16
17        layout = QtWidgets.QHBoxLayout(self)
18        layout.setContentsMargins(0, 0, 0, 0)
19        layout.addWidget(self.combo_1)
20        layout.addWidget(self.combo_2)
21        layout.addWidget(self.btn_go)
22
23
24class NodeWidgetWrapper(NodeBaseWidget):
25    """
26    Wrapper that allows the widget to be added in a node object.
27    """
28
29    def __init__(self, parent=None):
30        super(NodeWidgetWrapper, self).__init__(parent)
31
32        # set the name for node property.
33        self.set_name('my_widget')
34
35        # set the label above the widget.
36        self.set_label('Custom Widget')
37
38        # set the custom widget.
39        self.set_custom_widget(MyCustomWidget())
40
41        # connect up the signals & slots.
42        self.wire_signals()
43
44    def wire_signals(self):
45        widget = self.get_custom_widget()
46
47        # wire up the combo boxes.
48        widget.combo_1.currentIndexChanged.connect(self.on_value_changed)
49        widget.combo_2.currentIndexChanged.connect(self.on_value_changed)
50
51        # wire up the button.
52        widget.btn_go.clicked.connect(self.on_btn_go_clicked)
53
54    def on_btn_go_clicked(self):
55        print('Clicked on node: "{}"'.format(self.node.name()))
56
57    def get_value(self):
58        widget = self.get_custom_widget()
59        return '{}/{}'.format(widget.combo_1.currentText(),
60                              widget.combo_2.currentText())
61
62    def set_value(self, value):
63        value = value.split('/')
64        if len(value) < 2:
65            combo1_val = value[0]
66            combo2_val = ''
67        else:
68            combo1_val, combo2_val = value
69        widget = self.get_custom_widget()
70
71        cb1_index = widget.combo_1.findText(combo1_val, QtCore.Qt.MatchExactly)
72        cb2_index = widget.combo_1.findText(combo2_val, QtCore.Qt.MatchExactly)
73
74        widget.combo_1.setCurrentIndex(cb1_index)
75        widget.combo_2.setCurrentIndex(cb2_index)
76
77
78class MyNode(BaseNode):
79    """
80    Example node.
81    """
82
83    # set a unique node identifier.
84    __identifier__ = 'io.github.jchanvfx'
85
86    # set the initial default node name.
87    NODE_NAME = 'my node'
88
89    def __init__(self):
90        super(MyNode, self).__init__()
91
92        # create input and output port.
93        self.add_input('in')
94        self.add_output('out')
95
96        # add custom widget to node with "node.view" as the parent.
97        node_widget = NodeWidgetWrapper(self.view)
98        self.add_custom_widget(node_widget, tab='Custom')

To hide/show the embedded widget on a NodeGraphQt.BaseNode checkout the NodeGraphQt.BaseNode.hide_widget() and NodeGraphQt.BaseNode.show_widget() functions.

Connecting Nodes

There a multiple ways for connecting node ports here are a few examples below.

connecting nodes by the port index:

node_b.set_input(0, node_a.output(0))

connect nodes by the port name:

node_a.outputs()['bar'].connect_to(node_b.inputs()['foo'])

connecting nodes with the port objects:

# node_a "bar" output port.
port_a = node_a.output(0)
# node_b "foo" input port.
port_b = node_b.inputs()['foo']
# make the connection.
port_a.connect_to(port_b)

more on ports and connections.


Connecting a PropertiesBin

Here’s an example where we subclass the NodeGraph and connect it up to a PropertiesBinWidget and have it show when a node is double clicked.

 1from Qt import QtCore, QtWidgets
 2from NodeGraphQt import BaseNode, NodeGraph, PropertiesBinWidget
 3
 4
 5class MyNode(BaseNode):
 6
 7    __identifier__ = 'io.github.jchanvfx'
 8    NODE_NAME = 'my node'
 9
10    def __init__(self):
11        super(MyNode, self).__init__()
12        self.add_input('in')
13        self.add_output('out')
14
15
16class MyNodeGraph(NodeGraph):
17
18    def __init__(self, parent=None):
19        super(MyNodeGraph, self).__init__(parent)
20
21        # properties bin widget.
22        self._prop_bin = PropertiesBinWidget(node_graph=self)
23        self._prop_bin.setWindowFlags(QtCore.Qt.Tool)
24
25        # wire signal.
26        self.node_double_clicked.connect(self.display_prop_bin)
27
28    def display_prop_bin(self, node):
29        """
30        function for displaying the properties bin when a node
31        is double clicked
32        """
33        if not self._prop_bin.isVisible():
34            self._prop_bin.show()
35
36
37if __name__ == '__main__':
38    app = QtWidgets.QApplication([])
39
40    node_graph = MyNodeGraph()
41    node_graph.register_node(MyNode)
42    node_graph.widget.show()
43
44    node_a = node_graph.create_node('io.github.jchanvfx.MyNode')
45
46    app.exec_()

more on the properties bin and node_double_clicked signal