klauer / qtpynodeeditor Goto Github PK
View Code? Open in Web Editor NEWPython Qt NodeEditor (qtpy, PyQt5, PySide)
Home Page: https://klauer.github.io/qtpynodeeditor/
License: Other
Python Qt NodeEditor (qtpy, PyQt5, PySide)
Home Page: https://klauer.github.io/qtpynodeeditor/
License: Other
I'd like to customize the node background color, but there is no style setting to do so (or I missed it). Anyone knows how to do it?
TypeError: setWidth(self, width: int): argument 1 has unexpected type 'float'
Originally posted by @thorphil in #12 (comment):
I came across an issue where my NodeDataModel class input_connection_created was being called twice after a successful connection. Tracing this back, it seems to be caused by a the _FlowSceneModel constructor being called twice when the FlowScene is instantiated, thus registering two signal-slot connections. To fix, I changed the order of parents in FlowScene from (QGraphicsScene,_FlowSceneModel) to (_FlowSceneModel,QGraphicsScene). I am not entirely sure why this fixed the issue.
TypeConverter
class, TypeConverterId
can be awkward and unnecessary boilerplate.
Some preliminary discussion in #43 (comment):
I was thinking that class inheritance information could be used to indicate conversion compatibility, perhaps. At least in relatively simple graphs, it may even be possible to omit data_type = NodeDataType(...) then. That's aiming toward my hopeful overall goal of less boilerplate.
But data types may still be a necessity:
Perhaps, but there might be some very exotic conversions (e.g. an image into a text) and then the inheritance wouldn't help that much.
pytest is passing locally, but failing miserably on Travis CI.
See, for example, https://travis-ci.com/github/klauer/qtpynodeeditor/jobs/378887677
as subject
First option which made me search for something better:
Alternatives I've found (after spending the time porting nodeeditor, of course!):
Feel free to comment with other libraries here.
I can see from the calculator example how a nodes widget (e.g. the QLineEdit widget in NumberSourceDataModel) can output data 'downstream' in the nodegraph via the data_updated signal and subsequent call to the out_data() method. However, this process does not involve rerunning the nodes compute() method when a widget is updated and forces all node input variables to be additional nodes in the tree.
If I want to have a nodes widget play a part in the computation of the result (e.g. a 'math' node with 2 inputs connections and a QCombo box for selecting the math operation) what is a suitable approach? Move the computation of the result to the out_data() method and have an empty compute() method?
It seems that in flow_view.py (click_handler), the init is called once in self._scene.registry.create(model_name) and another time in self.scene.create_node(type)
NodeDataModel init method should be called only once per node when using the GUI for adding a node.
Note: this issue does not occur when the node is added directly in the Python script as it is done in calculator.py.
self._scene.registry.create(model_name) (line 168 of flow_view.py) should check whether a model exists already without having to create an instance.
If the model does exist, icreate an instance of that model thru the call to self.scene.create_node(type) (line 170 from flow_view.py)
self._scene.registry.create(model_name) creates an instance of the class "model_name" (hence calling init) and call init again in self.scene.create_node(type)
This occurs only when click_handler (line 163 of flow_view.py) is called
Calling init only once ensures that what is done inside the init will be done once.
If a model has been created already, do not create it again, what could be done by having a way to check whether a model has been created already
I have added a print('NumberSourceDataModel') in the init of NumberSourceDataModel in calculator.py (provided as an example by qtpynodeeditor).
When I run calculator.py, this message is printed 10 times as expected (5 * 2)
But when I add a NumberSourceDataModel from the screen, I have 2 print for a single instance, what I find not normal.
I have a NodeDataModel for Webcam acquisition using opencv.VideoCapture. This call is very long already but when called twice it is even worst.
python 3, pyqt5, last qtpynodeeditor version installed in July
QVariant
doesn't exist in PySide2 (only used for typing; to be removed)QT_API=PySide2 PYTEST_QT_API=PySide2
, lldb
points at QMessageLogger:qtpynodeeditor/tests/test_basic.py::test_instantiation Process 96282 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00007fff741812c6 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
-> 0x7fff741812c6 <+10>: jae 0x7fff741812d0 ; <+20>
0x7fff741812c8 <+12>: movq %rax, %rdi
0x7fff741812cb <+15>: jmp 0x7fff7417b457 ; cerror_nocancel
0x7fff741812d0 <+20>: retq
Target 0: (python) stopped.
(lldb) up
frame #1: 0x00007fff7423cbf1 libsystem_pthread.dylib`pthread_kill + 284
libsystem_pthread.dylib`pthread_kill:
-> 0x7fff7423cbf1 <+284>: movl %eax, %r15d
0x7fff7423cbf4 <+287>: cmpl $-0x1, %eax
0x7fff7423cbf7 <+290>: jne 0x7fff7423cc23 ; <+334>
0x7fff7423cbf9 <+292>: callq 0x7fff7423fafe ; symbol stub for: __error
(lldb)
frame #2: 0x00007fff740eb6a6 libsystem_c.dylib`abort + 127
libsystem_c.dylib`abort:
-> 0x7fff740eb6a6 <+127>: movl $0x2710, %edi ; imm = 0x2710
0x7fff740eb6ab <+132>: callq 0x7fff740be568 ; usleep$NOCANCEL
0x7fff740eb6b0 <+137>: callq 0x7fff740eb6b5 ; __abort
libsystem_c.dylib`__abort:
0x7fff740eb6b5 <+0>: cmpq $0x0, 0x367ebacb(%rip) ; gCRAnnotations + 7
(lldb)
frame #3: 0x00000001104325e9 QtCore`___lldb_unnamed_symbol171$$QtCore + 9
QtCore`___lldb_unnamed_symbol171$$QtCore:
-> 0x1104325e9 <+9>: nopl (%rax)
QtCore`___lldb_unnamed_symbol172$$QtCore:
0x1104325f0 <+0>: pushq %rbp
0x1104325f1 <+1>: movq %rsp, %rbp
0x1104325f4 <+4>: movq %rdi, %rax
(lldb)
frame #4: 0x0000000110433d34 QtCore`QMessageLogger::fatal(char const*, ...) const + 202
QtCore`QMessageLogger::fatal:
-> 0x110433d34 <+202>: ud2
0x110433d36 <+204>: jmp 0x110433d38 ; <+206>
0x110433d38 <+206>: movq %rax, %rbx
0x110433d3b <+209>: leaq -0x18(%rbp), %rdi
Upstream reference: paceholder/nodeeditor#268
QFontMetrics.horizontalAdvance()
is introduced in Qt-5.11. It's a rather new version, not always available in stable repos. For example in latest Anaconda, just PyQt-5.9 LTS conda package is provided, which is required by spyder4 etc, so pip-installing newer PyQt is not an option. So to use qtpynodeeditor in stable Anaconda this commit would be better reverted.
Originally posted by @NovA80 in #36 (comment)
I have connected the FlowScene connection_created
signal to a function responsible of complete clear and redrawing the graph sometimes. The problem is that this function is called before the connection is drawn! It is a problem because when I delete all the items from this function, it is impossible for qtpynodeeditor to finish the task.
I obtain the following traceback
Traceback (most recent call last):
File "/home/robin/.pyenv/versions/3.11.4/lib/python3.11/site-packages/qtpynodeeditor/connection_graphics_object.py", line 201, in mouseReleaseEvent
if node and interaction.try_connect():
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/robin/.pyenv/versions/3.11.4/lib/python3.11/site-packages/qtpynodeeditor/node_connection_interaction.py", line 175, in try_connect
self._node.graphics_object.move_connections()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'move_connections'
I've had a look at the source code and I think I've pinpointed the problem.
mouseReleaseEvent
method of connection_graphic_object.py, maybe call connection_created
at the end of this function ?try_connect
method of node_connection_interaction.py, at the line self._connection.connect_to(port)
the signal is triggered. As explicited in the traceback, the graphics_object
attribute of self._node
can be indirectly reset because of the signal trigger.connect_to
method of connection.py, the line self.connection_completed.emit(self)
trigger the connection_completed
signal. It is not directly the connection_created
signal.create_connection
method of flow_scene.py, the line connection.connection_completed.connect(self.connection_created.emit)
has previously associated the 2 signals. Why this two signals are connected?Maybe the solution could be to remove this signal alias in create_connection
method and trigger directly connection_created
at the end of try_connect
or mouseReleaseEvent
?
I'm not involved in the project, so maybe the solution I'm proposing will break something else ?
Thank you for this beautiful project, and if you guide me, I'm ready to try a pull request on this subject.
(*) As-is, conda-forge only installs and checks for importability of qtpynodeeditor:
https://github.com/conda-forge/qtpynodeeditor-feedstock/blob/master/recipe/meta.yaml
These lines:
follow to TypeError: 'int' object is not callable
i got this error while running the calc example
PS E:\me\Better-Dorky> & C:/Users/ahmed/AppData/Local/Programs/Python/Python310-32/python.exe e:/me/Better-Dorky/testingAPI.py
Traceback (most recent call last):
File "C:\Users\ahmed\AppData\Local\Programs\Python\Python310-32\lib\site-packages\qtpynodeeditor\connection_graphics_object.py", line 136, in paint
ConnectionPainter.paint(painter, self._connection, self._style)
File "C:\Users\ahmed\AppData\Local\Programs\Python\Python310-32\lib\site-packages\qtpynodeeditor\connection_painter.py", line 180, in paint
draw_normal_line(painter, connection, style)
File "C:\Users\ahmed\AppData\Local\Programs\Python\Python310-32\lib\site-packages\qtpynodeeditor\connection_painter.py", line 117, in draw_normal_line
p.setWidth(line_width)
TypeError: setWidth(self, width: int): argument 1 has unexpected type 'float'
Add the support of QundoCommand and QUndoStack to add ctrl+z/ctrl+y easily
I think we have to create:
Create_node_command
Delete_nodes_command
Move_nodes_command
Unlink_nodes_command
Link_nodes_command
Resize_nodes_command
and add the undo()/redo() action to scene
In the calculator example, both inputs of the operation nodes are connected to the same input node. In the following line, it should say node_b
instead of node_a
.
After updating pyqt5 from 5.14.2 to 5.15.5 5.15.0, nodes are no longer drawn correctly:
Console output:
qt.qpa.xcb: QXcbConnection: XCB error: 5 (BadAtom), sequence: 1083, resource id: 0, major code: 20 (GetProperty), minor code: 0
QPainter::begin: Paint device returned engine == 0, type: 2
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::setWorldTransform: Painter not active
QPainter::setClipRect: Painter not active
QPainter::font: Painter not active
QPainter::setPen: Painter not active
QPainter::setBrush: Painter not active
QPainter::setBrush: Painter not active
QPainter::setBrush: Painter not active
QPainter::setBrush: Painter not active
... (and many more lines like that)
Is something wrong with my installation, or can you reproduce this issue?
Arch Linux, Python 3.8.4, pyqt5 5.15.5 5.15.0, qtpy 1.9.0, qtpynodeeditor freshly cloned
Upstream issue: paceholder/nodeeditor#260
Styles have been reworked to be slightly less cumbersome than the original C++ version, but it's not perfect:
when I move a bunch of nodes, the edges sometimes move without staying attached at the other end to a static node.
the edge/connection would stay attached to the static node that's not moving
sometimes the edge moves without updating correctly
this results in a bad UX
move the static node a little, to refresh the edge
not always reproducable, think it's triggered by some kind of middle mouse click / shift combo
this is using the calculator example python -m qtpynodeeditor.examples.calculator
windows 11
pycharm
python 3.10.5 [MSC v.1929 64 bit (AMD64)] on win32
Qt 5.15.2
installed qtpynodeeditor from PyPi
The open issue paceholder/nodeeditor#198 actually has a working solution in the comments. I integrated it long time ago and had a problem with that, I don't know why he isn't merging it though.
This porting has the same issue or do implement that fix?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.