I have built a custom widget to show 3d Objects (in the past I used pythreejs, but since this project isn’t updated for quite some time, e.g. no recent version of threejs, I decided to move away and build my logic directly with threejs wrapped in an ipywidget)
I now want to call some of the Javascript functions from Python, i.e. control the object from Python or get values like positions back. At the moment I use custom messages (Widget.send) which work well if there is no relevant return value.
If I need the return value from Javascript, e.g. for getting the position, the Javascript method synchs a widget traitlet called “result”.
Firstly, this doesn’t feel like a clean way, and secondly, this is an asynchronous pattern which seems to make it difficult to evaluate in one JupyterLab cell . The only way that works in notebook cell I found is via callbacks - which “stops” the python kernel so that the widget state can be synched and then allows the kernel to call the callback (which includes my result value):
from ipywidgets import Output
out = Output()
def action(result):
with out:
print(json.loads(result))
widget.get("camera.zoom", callback=action)
out
This also means that I cannot use the value easily in the next cell. Looks like when I “Run all” the python kernel is too fast to allow the widget state to be synched before the next cell wants to access the traitlet - at least that is my explanation for the observed bahavior.
Is there a way with ipywidgets to get the result synchronously, as in
zoom = widget.get("camera.zoom")
In both examples, widget.get should ask the frontend for the value zoom of the javascript object camera