QNodeEditor.scene.NodeScene#
- class QNodeEditor.scene.NodeScene(parent: QWidget = None)#
Bases:
QObjectScene container holding nodes, sockets, layouts, edges, and utility functions.
This class represents a scene containing nodes connected by edges. The scene has a set number of nodes that can be used in the scene, with one being the dedicated output node.
See the
available_nodesproperty for details on how to set the nodes that can be used in the scene, and seeoutput_nodefor setting the dedicated output node.Examples
To create a new scene and add some nodes to it:
# Create a scene scene = NodeScene() # Set the nodes that can be used in the scene scene.available_nodes = { 'Some node': SomeNode, 'Another node': AnotherNode } # Set the node that is used as the output scene.output_node = SomeNode # Create two nodes and add them to the scene node1 = SomeNode() node2 = AnotherNode() scene.addNodes([node1, node2])
To display a node scene, use a
NodeViewinstance.Properties
Get or set the nodes that can be used in the scene.
errored(PyQt_PyObject)Signal that emits the error if once occurs during evaluation
evaluated(PyQt_PyObject)Signal that emits a dictionary with the result of evaluating the scene
Get or set the type of node that is considered the scene output.
progress(double)pyqtSignal -> Signal that emits the current progress of the evaluation [0.0, 1.0]
Methods
Create a new node scene.
Add a new node to the scene.
Add multiple new nodes to the scene.
Get a list of the class definitions of nodes that are available in the scene.
Get a list of the unique codes of all nodes that are available in the scene.
Remove all nodes (and thus all edges) from the scene.
Create a directional graph that represents the node scene.
Evaluate the scene by traversing the nodes and their connections.
Find the instance of the output node in the scene (if any)
Get a node class definition by its unique code
Get the state of this scene as a (JSON-safe) dictionary.
Check if the nodes and edges in the scene form a cycle.
Load the scene state from a file
Remove a node from the scene.
Save the scene state to a file.
Set a flag showing that content is being edited in a node.
Set the state of this scene from a state dictionary.
Get a directional graph representing the scene with only nodes connected to the output.
Get a dictionary of all sockets and their IDs in this scene
- __init__(parent: QWidget = None)#
Create a new node scene.
- Parameters:
parent (QWidget, optional) – Parent object for the node scene (if any)
- add_node(node: Node) None#
Add a new node to the scene.
- Parameters:
node (
Node) – Node to add to the scene- Return type:
None
- add_nodes(nodes: Iterable[Node]) None#
Add multiple new nodes to the scene.
- Parameters:
nodes (Iterable[
Node]) – Iterable of nodes to add to the scene- Return type:
None
- available_classes() list[Type[Node]]#
Get a list of the class definitions of nodes that are available in the scene.
Examples
With the following value for the
available_nodesproperty:scene.available_nodes = { 'Name 1': SomeNode, 'Group 1': { 'Name 2': AnotherNode, 'Name 3': YetAnotherNode }, 'Name 4': FinalNode }
This function would return:
[SomeNode, AnotherNode, YetAnotherNode, FinalNode]
- Returns:
List of node classes for all available nodes
- Return type:
list[Type[
Node]]
- available_codes() list[int]#
Get a list of the unique codes of all nodes that are available in the scene.
Examples
With the following value for the
available_nodesproperty:scene.available_nodes = { 'Name 1': SomeNode, # Unique code: 0 'Group 1': { 'Name 2': AnotherNode, # Unique code: 1 'Name 3': YetAnotherNode # Unique code: 2 }, 'Name 4': FinalNode # Unique code: 3 }
This function would return:
[0, 1, 2, 3]
- Returns:
List of unique codes for all available nodes
- Return type:
list[int]
- clear() None#
Remove all nodes (and thus all edges) from the scene.
- Return type:
None
- digraph() DiGraph#
Create a directional graph that represents the node scene.
This graph is used to check for cycles in the graph to prevent infinite recursion when evaluating.
- Returns:
Directional graph object representing the nodes and connections in the scene.
- Return type:
DiGraph
- evaluate() None#
Evaluate the scene by traversing the nodes and their connections.
This starts the asynchronous evaluation of the scene. All nodes leading up to the output node are evaluated, and the final result is emitted through the
evaluatedsignal.If an error occurs during the evaluation, it is emitted through the
erroredsignal (and nothing through theevaluatedsignal).For each node that is evaluated, the
progresssignal emits the current progress in the evaluation. The signal emits afloatthat represents the percentage of the current evaluation (0.0 to 1.0).- Return type:
None
- find_output_node() Node#
Find the instance of the output node in the scene (if any)
This function raises an error if the output node could not be found. This can be due to one of the following reasons:
No output node has been set through the
output_nodepropertyThere is no instance of the specified output node in the scene
There is more than one instances of the specified output node in the scene
- Returns:
Output node instance
- Return type:
- Raises:
ValueError – If the node could not be found, or there is more than one output node instance
- get_node_class(code: int) Type[Node]#
Get a node class definition by its unique code
This only works for nodes that are set in the
available_nodesproperty.- Parameters:
code (int) – Unique code of node class definition to retrieve
- Returns:
Node class definition matching the unique code
- Return type:
Type[
Node]- Raises:
ValueError – If no node with the specified unique code exists
- get_state() dict#
Get the state of this scene as a (JSON-safe) dictionary.
The dictionary contains:
'nodes': list of node states'edges': list of edge states
- Returns:
JSON-safe dictionary representing scene state
- Return type:
dict
- has_cycles() bool#
Check if the nodes and edges in the scene form a cycle.
- Returns:
Whether a cycle is present in the node scene
- Return type:
bool
- load(filepath: str) None#
Load the scene state from a file
- Parameters:
filepath (str) – Path to file to load scene state from
- Return type:
None
- remove_node(node: Node) None#
Remove a node from the scene.
Does not raise an error if the node does not exist.
- Parameters:
node (
Node) – Node to remove from the scene- Return type:
None
- save(filepath: str) None#
Save the scene state to a file.
- Parameters:
filepath (str) – Path to file to save scene state to
- Return type:
None
- set_editing_flag(editing: bool) None#
Set a flag showing that content is being edited in a node.
When this flag is set to
True, nodes will not be deleted when pressing theDeletekey.This flag is automatically set when a
ValueBoxis edited, as well as for select other widgets (seeconnect_signal()).- Parameters:
editing (bool) – Whether content is being edited in a node.
- Return type:
None
- set_state(state: dict, restore_id: bool = True) bool#
Set the state of this scene from a state dictionary.
The dictionary contains:
'nodes': list of node states'edges': list of edge states
- Parameters:
state (dict) – Dictionary representation of the desired scene state
restore_id (bool) – Whether to restore the internal IDs of the entry sockets (used to reconnect saved edges)
- Returns:
Whether setting the scene state succeeded
- Return type:
bool
- simplified_digraph() DiGraph#
Get a directional graph representing the scene with only nodes connected to the output.
This graph is used to determine how many nodes will have to be calculated during scene evaluation.
- Returns:
Directional graph object representing the nodes connected to the output node.
- Return type:
DiGraph
- socket_instances() dict[str, Socket]#
Get a dictionary of all sockets and their IDs in this scene
The returned dictionaries has the socket ID (string) and socket instance as keys and values respectively.
- Returns:
Dictionary of (ID, instance) pairs for all sockets in the scene
- Return type:
dict[str,
socket.Socket]
- property available_nodes: dict[str, Type[Node]]#
Get or set the nodes that can be used in the scene.
Setting the available nodes is done using a (nested) dictionary. The keys are used as names in the node editor context menu, and the corresponding values are types of a node that are placed when a name is selected.
You can only add nodes to the scene that are in the
available_nodesproperty. This is to keep track of the nodes such that they can be saved and loaded.Nodes may only appear once in the (nested) dictionary.
Examples
A scene with two nodes:
scene.available_nodes = { 'Name 1': SomeNode, 'Name 2': AnotherNode }
The resulting context menu would have the following structure:
Add node ├─ Name 1 └─ Name 2
Choosing either option results in placing a new instance of the corresponding node type.
A more complicated menu can be created like this:
scene.available_nodes = { 'Name 1': SomeNode, 'Group 1': { 'Name 2': AnotherNode, 'Name 3': YetAnotherNode }, 'Name 4': FinalNode }
The resulting context menu would now have the following structure:
Add node ├─ Name 1 ├─ Group 1 │ ├─ Name 2 │ └─ Name 3 └─ Name 4
- evaluated(PyQt_PyObject): Signal#
Signal that emits a dictionary with the result of evaluating the scene
- Type:
- property output_node: Type[Node]#
Get or set the type of node that is considered the scene output.
The node that is set will not be evaluated. Instead, all inputs of this node will be collected by traversing through the node scene. This is then collected and emitted as the result of the scene through the
evaluatedsignal.The output node can be set by either passing the class type, its unique
codeproperty, or an instance of that node.Examples
# Create a scene and set the available nodes and output node scene = NodeScene() scene.available_nodes = {'Some node': SomeNode} scene.output_node = SomeNode # Create an instance of the output node and add it to the scene node = SomeNode() # Node with two inputs, 'Value 1' and 'Value 2' scene.addNode(node) # Evaluate the scene (without any connections to the output node) scene.evaluated.connect(print) # Give the scene result to the 'print' function scene.evaluate() # Start the evaluation
The output of this script looks like this:
$ python test.py {'Value 1': None, 'Value 2': None}
The values for both items are
Nonesince nothing is wired into them.If the input entries in
SomeNodehad widgets such as aValueBox, its value would be used instead.If the input entries were wired to another node, it would be evaluated and that result would be used instead.